Преглед на файлове

Merge branch 'master' of /home/wd/git/u-boot/custodians

Wolfgang Denk преди 16 години
родител
ревизия
23bca26ab0

+ 6 - 0
README

@@ -2428,6 +2428,12 @@ to save the current settings.
 	to a block boundary, and CONFIG_ENV_SIZE must be a multiple of
 	the NAND devices block size.
 
+- CONFIG_NAND_ENV_DST
+
+	Defines address in RAM to which the nand_spl code should copy the
+	environment. If redundant environment is used, it will be copied to
+	CONFIG_NAND_ENV_DST + CONFIG_ENV_SIZE.
+
 - CONFIG_SYS_SPI_INIT_OFFSET
 
 	Defines offset to the initial SPI buffer area in DPRAM. The

+ 0 - 1
board/bf537-stamp/Makefile

@@ -32,7 +32,6 @@ LIB	= $(obj)lib$(BOARD).a
 COBJS-y	:= $(BOARD).o cmd_bf537led.o
 COBJS-$(CONFIG_BFIN_IDE)   += ide-cf.o
 COBJS-$(CONFIG_CMD_EEPROM) += spi_flash.o
-COBJS-$(CONFIG_CMD_NAND)   += nand.o
 COBJS-$(CONFIG_POST)       += post.o post-memory.o
 
 SRCS	:= $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)

+ 0 - 100
board/bf537-stamp/nand.c

@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2006-2007 Analog Devices Inc.
- *
- * 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 <asm/io.h>
-
-#include <nand.h>
-
-#define CONCAT(a,b,c,d) a ## b ## c ## d
-#define PORT(a,b)  CONCAT(pPORT,a,b,)
-
-#ifndef CONFIG_NAND_GPIO_PORT
-#define CONFIG_NAND_GPIO_PORT F
-#endif
-
-/*
- * hardware specific access to control-lines
- */
-static void bfin_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-{
-	register struct nand_chip *this = mtd->priv;
-	u32 IO_ADDR_W = (u32) this->IO_ADDR_W;
-
-	if (ctrl & NAND_CTRL_CHANGE) {
-		if (ctrl & NAND_CLE)
-			IO_ADDR_W = CONFIG_SYS_NAND_BASE + BFIN_NAND_CLE;
-		else
-			IO_ADDR_W = CONFIG_SYS_NAND_BASE;
-		if (ctrl & NAND_ALE)
-			IO_ADDR_W = CONFIG_SYS_NAND_BASE + BFIN_NAND_ALE;
-		else
-			IO_ADDR_W = CONFIG_SYS_NAND_BASE;
-		this->IO_ADDR_W = (void __iomem *) IO_ADDR_W;
-	}
-	this->IO_ADDR_R = this->IO_ADDR_W;
-
-	/* Drain the writebuffer */
-	SSYNC();
-
-	if (cmd != NAND_CMD_NONE)
-		writeb(cmd, this->IO_ADDR_W);
-}
-
-int bfin_device_ready(struct mtd_info *mtd)
-{
-	int ret = (*PORT(CONFIG_NAND_GPIO_PORT, IO) & BFIN_NAND_READY) ? 1 : 0;
-	SSYNC();
-	return ret;
-}
-
-/*
- * Board-specific NAND initialization. The following members of the
- * argument are board-specific (per include/linux/mtd/nand.h):
- * - IO_ADDR_R?: address to read the 8 I/O lines of the flash device
- * - IO_ADDR_W?: address to write the 8 I/O lines of the flash device
- * - cmd_ctrl: hardwarespecific function for accesing control-lines
- * - dev_ready: hardwarespecific function for  accesing device ready/busy line
- * - enable_hwecc?: function to enable (reset)  hardware ecc generator. Must
- *   only be provided if a hardware ECC is available
- * - ecc.mode: mode of ecc, see defines
- * - chip_delay: chip dependent delay for transfering data from array to
- *   read regs (tR)
- * - options: various chip options. They can partly be set to inform
- *   nand_scan about special functionality. See the defines for further
- *   explanation
- * Members with a "?" were not set in the merged testing-NAND branch,
- * so they are not set here either.
- */
-int board_nand_init(struct nand_chip *nand)
-{
-	*PORT(CONFIG_NAND_GPIO_PORT, _FER) &= ~BFIN_NAND_READY;
-	*PORT(CONFIG_NAND_GPIO_PORT, IO_DIR) &= ~BFIN_NAND_READY;
-	*PORT(CONFIG_NAND_GPIO_PORT, IO_INEN) |= BFIN_NAND_READY;
-
-	nand->cmd_ctrl = bfin_hwcontrol;
-	nand->ecc.mode = NAND_ECC_SOFT;
-	nand->dev_ready = bfin_device_ready;
-	nand->chip_delay = 30;
-
-	return 0;
-}

+ 28 - 0
board/davinci/sonata/sonata.c

@@ -25,6 +25,8 @@
  */
 
 #include <common.h>
+#include <nand.h>
+#include <asm/arch/nand_defs.h>
 #include <asm/arch/hardware.h>
 #include "../common/misc.h"
 
@@ -72,3 +74,29 @@ int misc_init_r(void)
 
 	return(0);
 }
+
+#ifdef CONFIG_NAND_DAVINCI
+
+/* Set WP on deselect, write enable on select */
+static void nand_sonata_select_chip(struct mtd_info *mtd, int chip)
+{
+#define GPIO_SET_DATA01	0x01c67018
+#define GPIO_CLR_DATA01	0x01c6701c
+#define GPIO_NAND_WP	(1 << 4)
+#ifdef SONATA_BOARD_GPIOWP
+	if (chip < 0) {
+		REG(GPIO_CLR_DATA01) |= GPIO_NAND_WP;
+	} else {
+		REG(GPIO_SET_DATA01) |= GPIO_NAND_WP;
+	}
+#endif
+}
+
+int board_nand_init(struct nand_chip *nand)
+{
+	davinci_nand_init(nand);
+	nand->select_chip = nand_sonata_select_chip;
+	return 0;
+}
+
+#endif /* CONFIG_NAND_DAVINCI */

+ 21 - 10
common/cmd_nand.c

@@ -414,18 +414,29 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 	}
 
 	if (strcmp(cmd, "markbad") == 0) {
-		addr = (ulong)simple_strtoul(argv[2], NULL, 16);
+		argc -= 2;
+		argv += 2;
 
-		int ret = nand->block_markbad(nand, addr);
-		if (ret == 0) {
-			printf("block 0x%08lx successfully marked as bad\n",
-			       (ulong) addr);
-			return 0;
-		} else {
-			printf("block 0x%08lx NOT marked as bad! ERROR %d\n",
-			       (ulong) addr, ret);
+		if (argc <= 0)
+			goto usage;
+
+		while (argc > 0) {
+			addr = simple_strtoul(*argv, NULL, 16);
+
+			if (nand->block_markbad(nand, addr)) {
+				printf("block 0x%08lx NOT marked "
+					"as bad! ERROR %d\n",
+					addr, ret);
+				ret = 1;
+			} else {
+				printf("block 0x%08lx successfully "
+					"marked as bad\n",
+					addr);
+			}
+			--argc;
+			++argv;
 		}
-		return 1;
+		return ret;
 	}
 
 	if (strcmp(cmd, "biterr") == 0) {

+ 23 - 12
common/cmd_onenand.c

@@ -340,7 +340,7 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 	int blocksize;
 	ulong addr, ofs;
 	size_t len, retlen = 0;
-	int ret;
+	int ret = 0;
 	char *cmd, *s;
 
 	mtd = &onenand_mtd;
@@ -434,18 +434,29 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 		}
 
 		if (strcmp(cmd, "markbad") == 0) {
-			addr = (ulong)simple_strtoul(argv[2], NULL, 16);
+			argc -= 2;
+			argv += 2;
 
-			int ret = mtd->block_markbad(mtd, addr);
-			if (ret == 0) {
-				printf("block 0x%08lx successfully marked as bad\n",
-						(ulong) addr);
-				return 0;
-			} else {
-				printf("block 0x%08lx NOT marked as bad! ERROR %d\n",
-						(ulong) addr, ret);
+			if (argc <= 0)
+				goto usage;
+
+			while (argc > 0) {
+				addr = simple_strtoul(*argv, NULL, 16);
+
+				if (mtd->block_markbad(mtd, addr)) {
+					printf("block 0x%08lx NOT marked "
+						"as bad! ERROR %d\n",
+						addr, ret);
+					ret = 1;
+				} else {
+					printf("block 0x%08lx successfully "
+						"marked as bad\n",
+						addr);
+				}
+				--argc;
+				++argv;
 			}
-			return 1;
+			return ret;
 		}
 
 		if (strncmp(cmd, "dump", 4) == 0) {
@@ -474,7 +485,7 @@ usage:
 }
 
 U_BOOT_CMD(
-	onenand,	6,	1,	do_onenand,
+	onenand,	CONFIG_SYS_MAXARGS,	1,	do_onenand,
 	"OneNAND sub-system",
 	"info - show available OneNAND devices\n"
 	"onenand bad - show bad blocks\n"

+ 29 - 22
common/env_nand.c

@@ -68,9 +68,11 @@ extern int default_environment_size;
 char * env_name_spec = "NAND";
 
 
-#ifdef ENV_IS_EMBEDDED
+#if defined(ENV_IS_EMBEDDED)
 extern uchar environment[];
 env_t *env_ptr = (env_t *)(&environment[0]);
+#elif defined(CONFIG_NAND_ENV_DST)
+env_t *env_ptr = (env_t *)CONFIG_NAND_ENV_DST;
 #else /* ! ENV_IS_EMBEDDED */
 env_t *env_ptr = 0;
 #endif /* ENV_IS_EMBEDDED */
@@ -102,26 +104,33 @@ uchar env_get_char_spec (int index)
  */
 int env_init(void)
 {
-#if defined(ENV_IS_EMBEDDED)
-	size_t total;
+#if defined(ENV_IS_EMBEDDED) || defined(CONFIG_NAND_ENV_DST)
 	int crc1_ok = 0, crc2_ok = 0;
-	env_t *tmp_env1, *tmp_env2;
+	env_t *tmp_env1;
 
-	total = CONFIG_ENV_SIZE;
+#ifdef CONFIG_ENV_OFFSET_REDUND
+	env_t *tmp_env2;
 
-	tmp_env1 = env_ptr;
 	tmp_env2 = (env_t *)((ulong)env_ptr + CONFIG_ENV_SIZE);
+	crc2_ok = (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc);
+#endif
+
+	tmp_env1 = env_ptr;
 
 	crc1_ok = (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc);
-	crc2_ok = (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc);
 
-	if (!crc1_ok && !crc2_ok)
+	if (!crc1_ok && !crc2_ok) {
+		gd->env_addr  = 0;
 		gd->env_valid = 0;
-	else if(crc1_ok && !crc2_ok)
+
+		return 0;
+	} else if (crc1_ok && !crc2_ok) {
 		gd->env_valid = 1;
-	else if(!crc1_ok && crc2_ok)
+	}
+#ifdef CONFIG_ENV_OFFSET_REDUND
+	else if (!crc1_ok && crc2_ok) {
 		gd->env_valid = 2;
-	else {
+	} else {
 		/* both ok - check serial */
 		if(tmp_env1->flags == 255 && tmp_env2->flags == 0)
 			gd->env_valid = 2;
@@ -135,14 +144,19 @@ int env_init(void)
 			gd->env_valid = 1;
 	}
 
+	if (gd->env_valid == 2)
+		env_ptr = tmp_env2;
+	else
+#endif
 	if (gd->env_valid == 1)
 		env_ptr = tmp_env1;
-	else if (gd->env_valid == 2)
-		env_ptr = tmp_env2;
-#else /* ENV_IS_EMBEDDED */
+
+	gd->env_addr = (ulong)env_ptr->data;
+
+#else /* ENV_IS_EMBEDDED || CONFIG_NAND_ENV_DST */
 	gd->env_addr  = (ulong)&default_environment[0];
 	gd->env_valid = 1;
-#endif /* ENV_IS_EMBEDDED */
+#endif /* ENV_IS_EMBEDDED || CONFIG_NAND_ENV_DST */
 
 	return (0);
 }
@@ -183,12 +197,10 @@ int writeenv(size_t offset, u_char *buf)
 #ifdef CONFIG_ENV_OFFSET_REDUND
 int saveenv(void)
 {
-	size_t total;
 	int ret = 0;
 	nand_erase_options_t nand_erase_options;
 
 	env_ptr->flags++;
-	total = CONFIG_ENV_SIZE;
 
 	nand_erase_options.length = CONFIG_ENV_RANGE;
 	nand_erase_options.quiet = 0;
@@ -226,7 +238,6 @@ int saveenv(void)
 #else /* ! CONFIG_ENV_OFFSET_REDUND */
 int saveenv(void)
 {
-	size_t total;
 	int ret = 0;
 	nand_erase_options_t nand_erase_options;
 
@@ -243,7 +254,6 @@ int saveenv(void)
 		return 1;
 
 	puts ("Writing to Nand... ");
-	total = CONFIG_ENV_SIZE;
 	if (writeenv(CONFIG_ENV_OFFSET, (u_char *) env_ptr)) {
 		puts("FAILED!\n");
 		return 1;
@@ -287,12 +297,9 @@ int readenv (size_t offset, u_char * buf)
 void env_relocate_spec (void)
 {
 #if !defined(ENV_IS_EMBEDDED)
-	size_t total;
 	int crc1_ok = 0, crc2_ok = 0;
 	env_t *tmp_env1, *tmp_env2;
 
-	total = CONFIG_ENV_SIZE;
-
 	tmp_env1 = (env_t *) malloc(CONFIG_ENV_SIZE);
 	tmp_env2 = (env_t *) malloc(CONFIG_ENV_SIZE);
 

+ 1 - 1
common/env_onenand.c

@@ -58,7 +58,7 @@ uchar env_get_char_spec(int index)
 
 void env_relocate_spec(void)
 {
-	unsigned long env_addr;
+	loff_t env_addr;
 	int use_default = 0;
 	size_t retlen;
 

+ 0 - 9
doc/README.nand

@@ -101,15 +101,6 @@ Configuration Options:
    CONFIG_SYS_NAND_MAX_CHIPS
       The maximum number of NAND chips per device to be supported.
 
-   CONFIG_SYS_DAVINCI_BROKEN_ECC
-      Versions of U-Boot <= 1.3.3 and Montavista Linux kernels
-      generated bogus ECCs on large-page NAND. Both large and small page
-      NAND ECCs were incompatible with the Linux davinci git tree (since
-      NAND was integrated in 2.6.24).
-      Turn this ON if you want backwards compatibility.
-      Turn this OFF if you want U-Boot and the Linux davinci git kernel
-      to use the same ECC format.
-
 NOTE:
 =====
 

+ 2 - 1
drivers/mtd/nand/Makefile

@@ -42,9 +42,10 @@ COBJS-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_nand.o
 COBJS-$(CONFIG_NAND_FSL_UPM) += fsl_upm.o
 COBJS-$(CONFIG_NAND_MPC5121_NFC) += mpc5121_nfc.o
 COBJS-$(CONFIG_NAND_NOMADIK) += nomadik.o
-COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.c
+COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o
 COBJS-$(CONFIG_NAND_S3C64XX) += s3c64xx.o
 COBJS-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o
+COBJS-$(CONFIG_NAND_PLAT) += nand_plat.o
 endif
 
 COBJS	:= $(COBJS-y)

+ 37 - 252
drivers/mtd/nand/davinci_nand.c

@@ -47,7 +47,7 @@
 #include <asm/arch/nand_defs.h>
 #include <asm/arch/emif_defs.h>
 
-extern struct nand_chip nand_dev_desc[CONFIG_SYS_MAX_NAND_DEVICE];
+static emif_registers *const emif_regs = (void *) DAVINCI_ASYNC_EMIF_CNTRL_BASE;
 
 static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
@@ -68,81 +68,30 @@ static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int c
 		writeb(cmd, this->IO_ADDR_W);
 }
 
-/* Set WP on deselect, write enable on select */
-static void nand_davinci_select_chip(struct mtd_info *mtd, int chip)
-{
-#define GPIO_SET_DATA01	0x01c67018
-#define GPIO_CLR_DATA01	0x01c6701c
-#define GPIO_NAND_WP	(1 << 4)
-#ifdef SONATA_BOARD_GPIOWP
-	if (chip < 0) {
-		REG(GPIO_CLR_DATA01) |= GPIO_NAND_WP;
-	} else {
-		REG(GPIO_SET_DATA01) |= GPIO_NAND_WP;
-	}
-#endif
-}
-
 #ifdef CONFIG_SYS_NAND_HW_ECC
-#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC
-/* Linux-compatible ECC uses MTD defaults. */
-/* These layouts are not compatible with Linux or RBL/UBL. */
-#ifdef CONFIG_SYS_NAND_LARGEPAGE
-static struct nand_ecclayout davinci_nand_ecclayout = {
-	.eccbytes = 12,
-	.eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58},
-	.oobfree = {
-		{.offset = 2, .length = 6},
-		{.offset = 12, .length = 12},
-		{.offset = 28, .length = 12},
-		{.offset = 44, .length = 12},
-		{.offset = 60, .length = 4}
-	}
-};
-#elif defined(CONFIG_SYS_NAND_SMALLPAGE)
-static struct nand_ecclayout davinci_nand_ecclayout = {
-	.eccbytes = 3,
-	.eccpos = {0, 1, 2},
-	.oobfree = {
-		{.offset = 6, .length = 2},
-		{.offset = 8, .length = 8}
-	}
-};
-#else
-#error "Either CONFIG_SYS_NAND_LARGEPAGE or CONFIG_SYS_NAND_SMALLPAGE must be defined!"
-#endif
-#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */
 
 static void nand_davinci_enable_hwecc(struct mtd_info *mtd, int mode)
 {
-	emifregs	emif_addr;
 	int		dummy;
 
-	emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE;
+	dummy = emif_regs->NANDF1ECC;
 
-	dummy = emif_addr->NANDF1ECC;
-	dummy = emif_addr->NANDF2ECC;
-	dummy = emif_addr->NANDF3ECC;
-	dummy = emif_addr->NANDF4ECC;
-
-	emif_addr->NANDFCR |= (1 << 8);
+	/* FIXME:  only chipselect 0 is supported for now */
+	emif_regs->NANDFCR |= 1 << 8;
 }
 
 static u_int32_t nand_davinci_readecc(struct mtd_info *mtd, u_int32_t region)
 {
 	u_int32_t	ecc = 0;
-	emifregs	emif_base_addr;
-
-	emif_base_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE;
 
 	if (region == 1)
-		ecc = emif_base_addr->NANDF1ECC;
+		ecc = emif_regs->NANDF1ECC;
 	else if (region == 2)
-		ecc = emif_base_addr->NANDF2ECC;
+		ecc = emif_regs->NANDF2ECC;
 	else if (region == 3)
-		ecc = emif_base_addr->NANDF3ECC;
+		ecc = emif_regs->NANDF3ECC;
 	else if (region == 4)
-		ecc = emif_base_addr->NANDF4ECC;
+		ecc = emif_regs->NANDF4ECC;
 
 	return(ecc);
 }
@@ -150,29 +99,6 @@ static u_int32_t nand_davinci_readecc(struct mtd_info *mtd, u_int32_t region)
 static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
 {
 	u_int32_t		tmp;
-#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC
-	/*
-	 * This is not how you should read ECCs on large page Davinci devices.
-	 * The region parameter gets you ECCs for flash chips on different chip
-	 * selects, not the 4x512 byte pages in a 2048 byte page.
-	 *
-	 * Preserved for backwards compatibility though.
-	 */
-
-	int			region, n;
-	struct nand_chip	*this = mtd->priv;
-
-	n = (this->ecc.size/512);
-
-	region = 1;
-	while (n--) {
-		tmp = nand_davinci_readecc(mtd, region);
-		*ecc_code++ = tmp;
-		*ecc_code++ = tmp >> 16;
-		*ecc_code++ = ((tmp >> 8) & 0x0f) | ((tmp >> 20) & 0xf0);
-		region++;
-	}
-#else
 	const int region = 1;
 
 	tmp = nand_davinci_readecc(mtd, region);
@@ -187,148 +113,26 @@ static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u
 	*ecc_code++ = tmp;
 	*ecc_code++ = tmp >>  8;
 	*ecc_code++ = tmp >> 16;
-#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */
-	return(0);
-}
-
-#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC
-static void nand_davinci_gen_true_ecc(u_int8_t *ecc_buf)
-{
-	u_int32_t	tmp = ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xf0) << 20) | ((ecc_buf[2] & 0x0f) << 8);
-
-	ecc_buf[0] = ~(P64o(tmp) | P64e(tmp) | P32o(tmp) | P32e(tmp) | P16o(tmp) | P16e(tmp) | P8o(tmp) | P8e(tmp));
-	ecc_buf[1] = ~(P1024o(tmp) | P1024e(tmp) | P512o(tmp) | P512e(tmp) | P256o(tmp) | P256e(tmp) | P128o(tmp) | P128e(tmp));
-	ecc_buf[2] = ~( P4o(tmp) | P4e(tmp) | P2o(tmp) | P2e(tmp) | P1o(tmp) | P1e(tmp) | P2048o(tmp) | P2048e(tmp));
-}
-
-static int nand_davinci_compare_ecc(u_int8_t *ecc_nand, u_int8_t *ecc_calc, u_int8_t *page_data)
-{
-	u_int32_t	i;
-	u_int8_t	tmp0_bit[8], tmp1_bit[8], tmp2_bit[8];
-	u_int8_t	comp0_bit[8], comp1_bit[8], comp2_bit[8];
-	u_int8_t	ecc_bit[24];
-	u_int8_t	ecc_sum = 0;
-	u_int8_t	find_bit = 0;
-	u_int32_t	find_byte = 0;
-	int		is_ecc_ff;
-
-	is_ecc_ff = ((*ecc_nand == 0xff) && (*(ecc_nand + 1) == 0xff) && (*(ecc_nand + 2) == 0xff));
-
-	nand_davinci_gen_true_ecc(ecc_nand);
-	nand_davinci_gen_true_ecc(ecc_calc);
-
-	for (i = 0; i <= 2; i++) {
-		*(ecc_nand + i) = ~(*(ecc_nand + i));
-		*(ecc_calc + i) = ~(*(ecc_calc + i));
-	}
 
-	for (i = 0; i < 8; i++) {
-		tmp0_bit[i] = *ecc_nand % 2;
-		*ecc_nand = *ecc_nand / 2;
-	}
-
-	for (i = 0; i < 8; i++) {
-		tmp1_bit[i] = *(ecc_nand + 1) % 2;
-		*(ecc_nand + 1) = *(ecc_nand + 1) / 2;
-	}
-
-	for (i = 0; i < 8; i++) {
-		tmp2_bit[i] = *(ecc_nand + 2) % 2;
-		*(ecc_nand + 2) = *(ecc_nand + 2) / 2;
-	}
-
-	for (i = 0; i < 8; i++) {
-		comp0_bit[i] = *ecc_calc % 2;
-		*ecc_calc = *ecc_calc / 2;
-	}
-
-	for (i = 0; i < 8; i++) {
-		comp1_bit[i] = *(ecc_calc + 1) % 2;
-		*(ecc_calc + 1) = *(ecc_calc + 1) / 2;
-	}
-
-	for (i = 0; i < 8; i++) {
-		comp2_bit[i] = *(ecc_calc + 2) % 2;
-		*(ecc_calc + 2) = *(ecc_calc + 2) / 2;
-	}
-
-	for (i = 0; i< 6; i++)
-		ecc_bit[i] = tmp2_bit[i + 2] ^ comp2_bit[i + 2];
-
-	for (i = 0; i < 8; i++)
-		ecc_bit[i + 6] = tmp0_bit[i] ^ comp0_bit[i];
-
-	for (i = 0; i < 8; i++)
-		ecc_bit[i + 14] = tmp1_bit[i] ^ comp1_bit[i];
-
-	ecc_bit[22] = tmp2_bit[0] ^ comp2_bit[0];
-	ecc_bit[23] = tmp2_bit[1] ^ comp2_bit[1];
-
-	for (i = 0; i < 24; i++)
-		ecc_sum += ecc_bit[i];
+	/* NOTE:  the above code matches mainline Linux:
+	 *	.PQR.stu ==> ~PQRstu
+	 *
+	 * MontaVista/TI kernels encode those bytes differently, use
+	 * complicated (and allegedly sometimes-wrong) correction code,
+	 * and usually shipped with U-Boot that uses software ECC:
+	 *	.PQR.stu ==> PsQRtu
+	 *
+	 * If you need MV/TI compatible NAND I/O in U-Boot, it should
+	 * be possible to (a) change the mangling above, (b) reverse
+	 * that mangling in nand_davinci_correct_data() below.
+	 */
 
-	switch (ecc_sum) {
-		case 0:
-			/* Not reached because this function is not called if
-			   ECC values are equal */
-			return 0;
-		case 1:
-			/* Uncorrectable error */
-			MTDDEBUG (MTD_DEBUG_LEVEL0,
-			          "ECC UNCORRECTED_ERROR 1\n");
-			return(-1);
-		case 12:
-			/* Correctable error */
-			find_byte = (ecc_bit[23] << 8) +
-				(ecc_bit[21] << 7) +
-				(ecc_bit[19] << 6) +
-				(ecc_bit[17] << 5) +
-				(ecc_bit[15] << 4) +
-				(ecc_bit[13] << 3) +
-				(ecc_bit[11] << 2) +
-				(ecc_bit[9]  << 1) +
-				ecc_bit[7];
-
-			find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1];
-
-			MTDDEBUG (MTD_DEBUG_LEVEL0, "Correcting single bit ECC "
-			          "error at offset: %d, bit: %d\n",
-			          find_byte, find_bit);
-
-			page_data[find_byte] ^= (1 << find_bit);
-
-			return(0);
-		default:
-			if (is_ecc_ff) {
-				if (ecc_calc[0] == 0 && ecc_calc[1] == 0 && ecc_calc[2] == 0)
-					return(0);
-			}
-			MTDDEBUG (MTD_DEBUG_LEVEL0,
-			          "UNCORRECTED_ERROR default\n");
-			return(-1);
-	}
+	return 0;
 }
-#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */
 
 static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
 {
 	struct nand_chip *this = mtd->priv;
-#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC
-	int			block_count = 0, i, rc;
-
-	block_count = (this->ecc.size/512);
-	for (i = 0; i < block_count; i++) {
-		if (memcmp(read_ecc, calc_ecc, 3) != 0) {
-			rc = nand_davinci_compare_ecc(read_ecc, calc_ecc, dat);
-			if (rc < 0) {
-				return(rc);
-			}
-		}
-		read_ecc += 3;
-		calc_ecc += 3;
-		dat += 512;
-	}
-#else
 	u_int32_t ecc_nand = read_ecc[0] | (read_ecc[1] << 8) |
 					  (read_ecc[2] << 16);
 	u_int32_t ecc_calc = calc_ecc[0] | (calc_ecc[1] << 8) |
@@ -362,31 +166,24 @@ static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char *
 			return -1;
 		}
 	}
-#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */
 	return(0);
 }
 #endif /* CONFIG_SYS_NAND_HW_ECC */
 
 static int nand_davinci_dev_ready(struct mtd_info *mtd)
 {
-	emifregs	emif_addr;
-
-	emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE;
-
-	return(emif_addr->NANDFSR & 0x1);
-}
-
-static int nand_davinci_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
-{
-	while(!nand_davinci_dev_ready(mtd)) {;}
-	*NAND_CE0CLE = NAND_STATUS;
-	return(*NAND_CE0DATA);
+	return emif_regs->NANDFSR & 0x1;
 }
 
 static void nand_flash_init(void)
 {
+	/* This is for DM6446 EVM and *very* similar.  DO NOT GROW THIS!
+	 * Instead, have your board_init() set EMIF timings, based on its
+	 * knowledge of the clocks and what devices are hooked up ... and
+	 * don't even do that unless no UBL handled it.
+	 */
+#ifdef CONFIG_SOC_DM6446
 	u_int32_t	acfg1 = 0x3ffffffc;
-	emifregs	emif_regs;
 
 	/*------------------------------------------------------------------*
 	 *  NAND FLASH CHIP TIMEOUT @ 459 MHz                               *
@@ -408,39 +205,22 @@ static void nand_flash_init(void)
 		| (0 << 0 )	/* asyncSize	8-bit bus */
 		;
 
-	emif_regs = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE;
-
 	emif_regs->AB1CR = acfg1; /* CS2 */
 
 	emif_regs->NANDFCR = 0x00000101; /* NAND flash on CS2 */
+#endif
 }
 
-int board_nand_init(struct nand_chip *nand)
+void davinci_nand_init(struct nand_chip *nand)
 {
-	nand->IO_ADDR_R   = (void  __iomem *)NAND_CE0DATA;
-	nand->IO_ADDR_W   = (void  __iomem *)NAND_CE0DATA;
 	nand->chip_delay  = 0;
-	nand->select_chip = nand_davinci_select_chip;
 #ifdef CONFIG_SYS_NAND_USE_FLASH_BBT
 	nand->options	  = NAND_USE_FLASH_BBT;
 #endif
 #ifdef CONFIG_SYS_NAND_HW_ECC
 	nand->ecc.mode = NAND_ECC_HW;
-#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC
-	nand->ecc.layout  = &davinci_nand_ecclayout;
-#ifdef CONFIG_SYS_NAND_LARGEPAGE
-	nand->ecc.size = 2048;
-	nand->ecc.bytes = 12;
-#elif defined(CONFIG_SYS_NAND_SMALLPAGE)
 	nand->ecc.size = 512;
 	nand->ecc.bytes = 3;
-#else
-#error "Either CONFIG_SYS_NAND_LARGEPAGE or CONFIG_SYS_NAND_SMALLPAGE must be defined!"
-#endif
-#else
-	nand->ecc.size = 512;
-	nand->ecc.bytes = 3;
-#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */
 	nand->ecc.calculate = nand_davinci_calculate_ecc;
 	nand->ecc.correct  = nand_davinci_correct_data;
 	nand->ecc.hwctl  = nand_davinci_enable_hwecc;
@@ -452,9 +232,14 @@ int board_nand_init(struct nand_chip *nand)
 	nand->cmd_ctrl = nand_davinci_hwcontrol;
 
 	nand->dev_ready = nand_davinci_dev_ready;
-	nand->waitfunc = nand_davinci_waitfunc;
 
 	nand_flash_init();
+}
 
-	return(0);
+int board_nand_init(struct nand_chip *chip) __attribute__((weak));
+
+int board_nand_init(struct nand_chip *chip)
+{
+	davinci_nand_init(chip);
+	return 0;
 }

+ 4 - 0
drivers/mtd/nand/fsl_elbc_nand.c

@@ -766,6 +766,9 @@ int board_nand_init(struct nand_chip *nand)
 	nand->waitfunc = fsl_elbc_wait;
 
 	/* set up nand options */
+	/* redirect the pointer of bbt pattern to RAM */
+	bbt_main_descr.pattern = bbt_pattern;
+	bbt_mirror_descr.pattern = mirror_pattern;
 	nand->bbt_td = &bbt_main_descr;
 	nand->bbt_md = &bbt_mirror_descr;
 
@@ -812,6 +815,7 @@ int board_nand_init(struct nand_chip *nand)
 	/* Large-page-specific setup */
 	if (or & OR_FCM_PGS) {
 		priv->page_size = 1;
+		largepage_memorybased.pattern = scan_ff_pattern;
 		nand->badblock_pattern = &largepage_memorybased;
 
 		/* adjust ecc setup if needed */

+ 53 - 0
drivers/mtd/nand/nand_plat.c

@@ -0,0 +1,53 @@
+/*
+ * Genericish driver for memory mapped NAND devices
+ *
+ * Copyright (c) 2006-2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
+ */
+
+/* Your board must implement the following macros:
+ *  NAND_PLAT_WRITE_CMD(chip, cmd)
+ *  NAND_PLAT_WRITE_ADR(chip, cmd)
+ *  NAND_PLAT_INIT()
+ *
+ * It may also implement the following:
+ *  NAND_PLAT_DEV_READY(chip)
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+#include <nand.h>
+
+static void plat_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+	struct nand_chip *this = mtd->priv;
+
+	if (cmd == NAND_CMD_NONE)
+		return;
+
+	if (ctrl & NAND_CLE)
+		NAND_PLAT_WRITE_CMD(this, cmd);
+	else
+		NAND_PLAT_WRITE_ADR(this, cmd);
+}
+
+#ifdef NAND_PLAT_DEV_READY
+static int plat_dev_ready(struct mtd_info *mtd)
+{
+	return NAND_PLAT_DEV_READY((struct nand_chip *)mtd->priv);
+}
+#else
+# define plat_dev_ready NULL
+#endif
+
+int board_nand_init(struct nand_chip *nand)
+{
+	NAND_PLAT_INIT();
+
+	nand->cmd_ctrl = plat_cmd_ctrl;
+	nand->dev_ready = plat_dev_ready;
+	nand->ecc.mode = NAND_ECC_SOFT;
+
+	return 0;
+}

+ 10 - 10
drivers/mtd/nand/nand_util.c

@@ -315,7 +315,7 @@ int nand_lock(struct mtd_info *mtd, int tight)
  *			  NAND_LOCK_STATUS_UNLOCK: page unlocked
  *
  */
-int nand_get_lock_status(struct mtd_info *mtd, ulong offset)
+int nand_get_lock_status(struct mtd_info *mtd, loff_t offset)
 {
 	int ret = 0;
 	int chipnr;
@@ -436,7 +436,7 @@ int nand_unlock(struct mtd_info *mtd, ulong start, ulong length)
  * @param length image length
  * @return image length including bad blocks
  */
-static size_t get_len_incl_bad (nand_info_t *nand, size_t offset,
+static size_t get_len_incl_bad (nand_info_t *nand, loff_t offset,
 				const size_t length)
 {
 	size_t len_incl_bad = 0;
@@ -473,7 +473,7 @@ static size_t get_len_incl_bad (nand_info_t *nand, size_t offset,
  * @param buf           buffer to read from
  * @return		0 in case of success
  */
-int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
+int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
 			u_char *buffer)
 {
 	int rval;
@@ -498,7 +498,7 @@ int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
 	if (len_incl_bad == *length) {
 		rval = nand_write (nand, offset, length, buffer);
 		if (rval != 0)
-			printf ("NAND write to offset %zx failed %d\n",
+			printf ("NAND write to offset %llx failed %d\n",
 				offset, rval);
 
 		return rval;
@@ -509,7 +509,7 @@ int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
 		size_t write_size;
 
 		if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) {
-			printf ("Skip bad block 0x%08zx\n",
+			printf ("Skip bad block 0x%08llx\n",
 				offset & ~(nand->erasesize - 1));
 			offset += nand->erasesize - block_offset;
 			continue;
@@ -522,7 +522,7 @@ int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
 
 		rval = nand_write (nand, offset, &write_size, p_buffer);
 		if (rval != 0) {
-			printf ("NAND write to offset %zx failed %d\n",
+			printf ("NAND write to offset %llx failed %d\n",
 				offset, rval);
 			*length -= left_to_write;
 			return rval;
@@ -550,7 +550,7 @@ int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
  * @param buffer buffer to write to
  * @return 0 in case of success
  */
-int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
+int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
 		       u_char *buffer)
 {
 	int rval;
@@ -568,7 +568,7 @@ int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
 	if (len_incl_bad == *length) {
 		rval = nand_read (nand, offset, length, buffer);
 		if (rval != 0)
-			printf ("NAND read from offset %zx failed %d\n",
+			printf ("NAND read from offset %llx failed %d\n",
 				offset, rval);
 
 		return rval;
@@ -579,7 +579,7 @@ int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
 		size_t read_length;
 
 		if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) {
-			printf ("Skipping bad block 0x%08zx\n",
+			printf ("Skipping bad block 0x%08llx\n",
 				offset & ~(nand->erasesize - 1));
 			offset += nand->erasesize - block_offset;
 			continue;
@@ -592,7 +592,7 @@ int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
 
 		rval = nand_read (nand, offset, &read_length, p_buffer);
 		if (rval != 0) {
-			printf ("NAND read from offset %zx failed %d\n",
+			printf ("NAND read from offset %llx failed %d\n",
 				offset, rval);
 			*length -= left_to_read;
 			return rval;

+ 7 - 123
include/asm-arm/arch-davinci/nand_defs.h

@@ -28,134 +28,18 @@
 
 #include <asm/arch/hardware.h>
 
+#ifdef CONFIG_SOC_DM646x
+#define	MASK_CLE	0x80000
+#define	MASK_ALE	0x40000
+#else
 #define	MASK_CLE	0x10
-#define	MASK_ALE	0x0a
-
-#define NAND_CE0CLE	((volatile u_int8_t *)(CONFIG_SYS_NAND_BASE + 0x10))
-#define NAND_CE0ALE	((volatile u_int8_t *)(CONFIG_SYS_NAND_BASE + 0x0a))
-#define NAND_CE0DATA	((volatile u_int8_t *)CONFIG_SYS_NAND_BASE)
-
-typedef struct  {
-	u_int32_t	NRCSR;
-	u_int32_t	AWCCR;
-	u_int8_t	RSVD0[8];
-	u_int32_t	AB1CR;
-	u_int32_t	AB2CR;
-	u_int32_t	AB3CR;
-	u_int32_t	AB4CR;
-	u_int8_t	RSVD1[32];
-	u_int32_t	NIRR;
-	u_int32_t	NIMR;
-	u_int32_t	NIMSR;
-	u_int32_t	NIMCR;
-	u_int8_t	RSVD2[16];
-	u_int32_t	NANDFCR;
-	u_int32_t	NANDFSR;
-	u_int8_t	RSVD3[8];
-	u_int32_t	NANDF1ECC;
-	u_int32_t	NANDF2ECC;
-	u_int32_t	NANDF3ECC;
-	u_int32_t	NANDF4ECC;
-	u_int8_t	RSVD4[4];
-	u_int32_t	IODFTECR;
-	u_int32_t	IODFTGCR;
-	u_int8_t	RSVD5[4];
-	u_int32_t	IODFTMRLR;
-	u_int32_t	IODFTMRMR;
-	u_int32_t	IODFTMRMSBR;
-	u_int8_t	RSVD6[20];
-	u_int32_t	MODRNR;
-	u_int8_t	RSVD7[76];
-	u_int32_t	CE0DATA;
-	u_int32_t	CE0ALE;
-	u_int32_t	CE0CLE;
-	u_int8_t	RSVD8[4];
-	u_int32_t	CE1DATA;
-	u_int32_t	CE1ALE;
-	u_int32_t	CE1CLE;
-	u_int8_t	RSVD9[4];
-	u_int32_t	CE2DATA;
-	u_int32_t	CE2ALE;
-	u_int32_t	CE2CLE;
-	u_int8_t	RSVD10[4];
-	u_int32_t	CE3DATA;
-	u_int32_t	CE3ALE;
-	u_int32_t	CE3CLE;
-} nand_registers;
-
-typedef volatile nand_registers	*nandregs;
+#define	MASK_ALE	0x08
+#endif
 
 #define NAND_READ_START		0x00
 #define NAND_READ_END		0x30
 #define NAND_STATUS		0x70
 
-#ifdef CONFIG_SYS_NAND_HW_ECC
-#define NAND_Ecc_P1e		(1 << 0)
-#define NAND_Ecc_P2e		(1 << 1)
-#define NAND_Ecc_P4e		(1 << 2)
-#define NAND_Ecc_P8e		(1 << 3)
-#define NAND_Ecc_P16e		(1 << 4)
-#define NAND_Ecc_P32e		(1 << 5)
-#define NAND_Ecc_P64e		(1 << 6)
-#define NAND_Ecc_P128e		(1 << 7)
-#define NAND_Ecc_P256e		(1 << 8)
-#define NAND_Ecc_P512e		(1 << 9)
-#define NAND_Ecc_P1024e		(1 << 10)
-#define NAND_Ecc_P2048e		(1 << 11)
-
-#define NAND_Ecc_P1o		(1 << 16)
-#define NAND_Ecc_P2o		(1 << 17)
-#define NAND_Ecc_P4o		(1 << 18)
-#define NAND_Ecc_P8o		(1 << 19)
-#define NAND_Ecc_P16o		(1 << 20)
-#define NAND_Ecc_P32o		(1 << 21)
-#define NAND_Ecc_P64o		(1 << 22)
-#define NAND_Ecc_P128o		(1 << 23)
-#define NAND_Ecc_P256o		(1 << 24)
-#define NAND_Ecc_P512o		(1 << 25)
-#define NAND_Ecc_P1024o		(1 << 26)
-#define NAND_Ecc_P2048o		(1 << 27)
-
-#define TF(v)			(v ? 1 : 0)
-
-#define P2048e(a)		(TF(a & NAND_Ecc_P2048e) << 0)
-#define P2048o(a)		(TF(a & NAND_Ecc_P2048o) << 1)
-#define P1e(a)			(TF(a & NAND_Ecc_P1e) << 2)
-#define P1o(a)			(TF(a & NAND_Ecc_P1o) << 3)
-#define P2e(a)			(TF(a & NAND_Ecc_P2e) << 4)
-#define P2o(a)			(TF(a & NAND_Ecc_P2o) << 5)
-#define P4e(a)			(TF(a & NAND_Ecc_P4e) << 6)
-#define P4o(a)			(TF(a & NAND_Ecc_P4o) << 7)
-
-#define P8e(a)			(TF(a & NAND_Ecc_P8e) << 0)
-#define P8o(a)			(TF(a & NAND_Ecc_P8o) << 1)
-#define P16e(a)			(TF(a & NAND_Ecc_P16e) << 2)
-#define P16o(a)			(TF(a & NAND_Ecc_P16o) << 3)
-#define P32e(a)			(TF(a & NAND_Ecc_P32e) << 4)
-#define P32o(a)			(TF(a & NAND_Ecc_P32o) << 5)
-#define P64e(a)			(TF(a & NAND_Ecc_P64e) << 6)
-#define P64o(a)			(TF(a & NAND_Ecc_P64o) << 7)
-
-#define P128e(a)		(TF(a & NAND_Ecc_P128e) << 0)
-#define P128o(a)		(TF(a & NAND_Ecc_P128o) << 1)
-#define P256e(a)		(TF(a & NAND_Ecc_P256e) << 2)
-#define P256o(a)		(TF(a & NAND_Ecc_P256o) << 3)
-#define P512e(a)		(TF(a & NAND_Ecc_P512e) << 4)
-#define P512o(a)		(TF(a & NAND_Ecc_P512o) << 5)
-#define P1024e(a)		(TF(a & NAND_Ecc_P1024e) << 6)
-#define P1024o(a)		(TF(a & NAND_Ecc_P1024o) << 7)
-
-#define P8e_s(a)		(TF(a & NAND_Ecc_P8e) << 0)
-#define P8o_s(a)		(TF(a & NAND_Ecc_P8o) << 1)
-#define P16e_s(a)		(TF(a & NAND_Ecc_P16e) << 2)
-#define P16o_s(a)		(TF(a & NAND_Ecc_P16o) << 3)
-#define P1e_s(a)		(TF(a & NAND_Ecc_P1e) << 4)
-#define P1o_s(a)		(TF(a & NAND_Ecc_P1o) << 5)
-#define P2e_s(a)		(TF(a & NAND_Ecc_P2e) << 6)
-#define P2o_s(a)		(TF(a & NAND_Ecc_P2o) << 7)
-
-#define P4e_s(a)		(TF(a & NAND_Ecc_P4e) << 0)
-#define P4o_s(a)		(TF(a & NAND_Ecc_P4o) << 1)
-#endif
+extern void davinci_nand_init(struct nand_chip *nand);
 
 #endif

+ 18 - 26
include/configs/bf537-stamp.h

@@ -151,36 +151,28 @@
 /*
  * NAND Settings
  */
-/* #define CONFIG_BF537_NAND */
-#ifdef CONFIG_BF537_NAND
-# define CONFIG_CMD_NAND
-#endif
-
-#define CONFIG_SYS_NAND_ADDR		0x20212000
-#define CONFIG_SYS_NAND_BASE		CONFIG_SYS_NAND_ADDR
+/* #define CONFIG_NAND_PLAT */
+#define CONFIG_SYS_NAND_BASE		0x20212000
 #define CONFIG_SYS_MAX_NAND_DEVICE	1
-#define SECTORSIZE		512
-#define ADDR_COLUMN		1
-#define ADDR_PAGE		2
-#define ADDR_COLUMN_PAGE	3
-#define NAND_ChipID_UNKNOWN	0x00
-#define NAND_MAX_FLOORS		1
-#define BFIN_NAND_READY		PF3
-
-#define NAND_WAIT_READY(nand) \
+
+#define BFIN_NAND_CLE(chip) ((unsigned long)(chip)->IO_ADDR_W | (1 << 2))
+#define BFIN_NAND_ALE(chip) ((unsigned long)(chip)->IO_ADDR_W | (1 << 1))
+#define BFIN_NAND_READY     PF3
+#define BFIN_NAND_WRITE(addr, cmd) \
 	do { \
-		int timeout = 0; \
-		while (!(*pPORTFIO & PF3)) \
-			if (timeout++ > 100000) \
-				break; \
+		bfin_write8(addr, cmd); \
+		SSYNC(); \
 	} while (0)
 
-#define BFIN_NAND_CLE		(1 << 2)	/* A2 -> Command Enable */
-#define BFIN_NAND_ALE		(1 << 1)	/* A1 -> Address Enable */
-#define WRITE_NAND_COMMAND(d, adr) bfin_write8(adr | BFIN_NAND_CLE, d)
-#define WRITE_NAND_ADDRESS(d, adr) bfin_write8(adr | BFIN_NAND_ALE, d)
-#define WRITE_NAND(d, adr)         bfin_write8(adr, d)
-#define READ_NAND(adr)             bfin_read8(adr)
+#define NAND_PLAT_WRITE_CMD(chip, cmd) BFIN_NAND_WRITE(BFIN_NAND_CLE(chip), cmd)
+#define NAND_PLAT_WRITE_ADR(chip, cmd) BFIN_NAND_WRITE(BFIN_NAND_ALE(chip), cmd)
+#define NAND_PLAT_DEV_READY(chip)      (bfin_read_PORTFIO() & BFIN_NAND_READY)
+#define NAND_PLAT_INIT() \
+	do { \
+		bfin_write_PORTF_FER(bfin_read_PORTF_FER() & ~BFIN_NAND_READY); \
+		bfin_write_PORTFIO_DIR(bfin_read_PORTFIO_DIR() & ~BFIN_NAND_READY); \
+		bfin_write_PORTFIO_INEN(bfin_read_PORTFIO_INEN() | BFIN_NAND_READY); \
+	} while (0)
 
 
 /*

+ 3 - 0
include/configs/bfin_adi_common.h

@@ -38,6 +38,9 @@
 #  define CONFIG_CMD_USB_STORAGE
 #  define CONFIG_DOS_PARTITION
 # endif
+# ifdef CONFIG_NAND_PLAT
+#  define CONFIG_CMD_NAND
+# endif
 # ifdef CONFIG_POST
 #  define CONFIG_CMD_DIAG
 # endif

+ 3 - 0
include/configs/smdk6400.h

@@ -209,6 +209,9 @@
 /* total memory available to uboot */
 #define CONFIG_SYS_UBOOT_SIZE		(1024 * 1024)
 
+/* Put environment copies after the end of U-Boot owned RAM */
+#define CONFIG_NAND_ENV_DST	(CONFIG_SYS_UBOOT_BASE + CONFIG_SYS_UBOOT_SIZE)
+
 #ifdef CONFIG_ENABLE_MMU
 #define CONFIG_SYS_MAPPED_RAM_BASE	0xc0000000
 #define CONFIG_BOOTCOMMAND	"nand read 0xc0018000 0x60000 0x1c0000;" \

+ 7 - 7
include/nand.h

@@ -38,22 +38,22 @@ typedef struct mtd_info nand_info_t;
 extern int nand_curr_device;
 extern nand_info_t nand_info[];
 
-static inline int nand_read(nand_info_t *info, off_t ofs, size_t *len, u_char *buf)
+static inline int nand_read(nand_info_t *info, loff_t ofs, size_t *len, u_char *buf)
 {
 	return info->read(info, ofs, *len, (size_t *)len, buf);
 }
 
-static inline int nand_write(nand_info_t *info, off_t ofs, size_t *len, u_char *buf)
+static inline int nand_write(nand_info_t *info, loff_t ofs, size_t *len, u_char *buf)
 {
 	return info->write(info, ofs, *len, (size_t *)len, buf);
 }
 
-static inline int nand_block_isbad(nand_info_t *info, off_t ofs)
+static inline int nand_block_isbad(nand_info_t *info, loff_t ofs)
 {
 	return info->block_isbad(info, ofs);
 }
 
-static inline int nand_erase(nand_info_t *info, off_t off, size_t size)
+static inline int nand_erase(nand_info_t *info, loff_t off, size_t size)
 {
 	struct erase_info instr;
 
@@ -110,9 +110,9 @@ struct nand_erase_options {
 
 typedef struct nand_erase_options nand_erase_options_t;
 
-int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
+int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
 		       u_char *buffer);
-int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
+int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
 			u_char *buffer);
 int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts);
 
@@ -122,7 +122,7 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts);
 
 int nand_lock( nand_info_t *meminfo, int tight );
 int nand_unlock( nand_info_t *meminfo, ulong start, ulong length );
-int nand_get_lock_status(nand_info_t *meminfo, ulong offset);
+int nand_get_lock_status(nand_info_t *meminfo, loff_t offset);
 
 #ifdef CONFIG_SYS_NAND_SELECT_DEVICE
 void board_nand_select_device(struct nand_chip *nand, int chip);

+ 21 - 7
nand_spl/nand_boot.c

@@ -47,11 +47,13 @@ static int nand_command(struct mtd_info *mtd, int block, int page, int offs, u8
 	/* Set ALE and clear CLE to start address cycle */
 	/* Column address */
 	this->cmd_ctrl(mtd, offs, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
-	this->cmd_ctrl(mtd, page_addr & 0xff, 0); /* A[16:9] */
-	this->cmd_ctrl(mtd, (page_addr >> 8) & 0xff, 0); /* A[24:17] */
+	this->cmd_ctrl(mtd, page_addr & 0xff, NAND_CTRL_ALE); /* A[16:9] */
+	this->cmd_ctrl(mtd, (page_addr >> 8) & 0xff,
+		       NAND_CTRL_ALE); /* A[24:17] */
 #ifdef CONFIG_SYS_NAND_4_ADDR_CYCLE
 	/* One more address cycle for devices > 32MiB */
-	this->cmd_ctrl(mtd, (page_addr >> 16) & 0x0f, 0); /* A[28:25] */
+	this->cmd_ctrl(mtd, (page_addr >> 16) & 0x0f,
+		       NAND_CTRL_ALE); /* A[28:25] */
 #endif
 	/* Latch in address */
 	this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
@@ -94,13 +96,15 @@ static int nand_command(struct mtd_info *mtd, int block, int page, int offs, u8
 	/* Column address */
 	this->cmd_ctrl(mtd, offs & 0xff,
 		       NAND_CTRL_ALE | NAND_CTRL_CHANGE); /* A[7:0] */
-	this->cmd_ctrl(mtd, (offs >> 8) & 0xff, 0); /* A[11:9] */
+	this->cmd_ctrl(mtd, (offs >> 8) & 0xff, NAND_CTRL_ALE); /* A[11:9] */
 	/* Row address */
-	this->cmd_ctrl(mtd, (page_addr & 0xff), 0); /* A[19:12] */
-	this->cmd_ctrl(mtd, ((page_addr >> 8) & 0xff), 0); /* A[27:20] */
+	this->cmd_ctrl(mtd, (page_addr & 0xff), NAND_CTRL_ALE); /* A[19:12] */
+	this->cmd_ctrl(mtd, ((page_addr >> 8) & 0xff),
+		       NAND_CTRL_ALE); /* A[27:20] */
 #ifdef CONFIG_SYS_NAND_5_ADDR_CYCLE
 	/* One more address cycle for devices > 128MiB */
-	this->cmd_ctrl(mtd, (page_addr >> 16) & 0x0f, 0); /* A[31:28] */
+	this->cmd_ctrl(mtd, (page_addr >> 16) & 0x0f,
+		       NAND_CTRL_ALE); /* A[31:28] */
 #endif
 	/* Latch in address */
 	this->cmd_ctrl(mtd, NAND_CMD_READSTART,
@@ -246,6 +250,16 @@ void nand_boot(void)
 	ret = nand_load(&nand_info, CONFIG_SYS_NAND_U_BOOT_OFFS, CONFIG_SYS_NAND_U_BOOT_SIZE,
 			(uchar *)CONFIG_SYS_NAND_U_BOOT_DST);
 
+#ifdef CONFIG_NAND_ENV_DST
+	nand_load(&nand_info, CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
+		  (uchar *)CONFIG_NAND_ENV_DST);
+
+#ifdef CONFIG_ENV_OFFSET_REDUND
+	nand_load(&nand_info, CONFIG_ENV_OFFSET_REDUND, CONFIG_ENV_SIZE,
+		  (uchar *)CONFIG_NAND_ENV_DST + CONFIG_ENV_SIZE);
+#endif
+#endif
+
 	if (nand_chip.select_chip)
 		nand_chip.select_chip(&nand_info, -1);