diff options
| -rw-r--r-- | README | 6 | ||||
| -rw-r--r-- | board/bf537-stamp/Makefile | 1 | ||||
| -rw-r--r-- | board/bf537-stamp/nand.c | 100 | ||||
| -rw-r--r-- | board/davinci/sonata/sonata.c | 28 | ||||
| -rw-r--r-- | common/cmd_nand.c | 31 | ||||
| -rw-r--r-- | common/cmd_onenand.c | 35 | ||||
| -rw-r--r-- | common/env_nand.c | 51 | ||||
| -rw-r--r-- | common/env_onenand.c | 2 | ||||
| -rw-r--r-- | doc/README.nand | 9 | ||||
| -rw-r--r-- | drivers/mtd/nand/Makefile | 3 | ||||
| -rw-r--r-- | drivers/mtd/nand/davinci_nand.c | 289 | ||||
| -rw-r--r-- | drivers/mtd/nand/fsl_elbc_nand.c | 4 | ||||
| -rw-r--r-- | drivers/mtd/nand/nand_plat.c | 53 | ||||
| -rw-r--r-- | drivers/mtd/nand/nand_util.c | 20 | ||||
| -rw-r--r-- | include/asm-arm/arch-davinci/nand_defs.h | 130 | ||||
| -rw-r--r-- | include/configs/bf537-stamp.h | 42 | ||||
| -rw-r--r-- | include/configs/bfin_adi_common.h | 3 | ||||
| -rw-r--r-- | include/configs/smdk6400.h | 3 | ||||
| -rw-r--r-- | include/nand.h | 14 | ||||
| -rw-r--r-- | nand_spl/nand_boot.c | 28 | 
20 files changed, 272 insertions, 580 deletions
@@ -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 diff --git a/board/bf537-stamp/Makefile b/board/bf537-stamp/Makefile index 4c9e015a1..f728e2c0d 100644 --- a/board/bf537-stamp/Makefile +++ b/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) diff --git a/board/bf537-stamp/nand.c b/board/bf537-stamp/nand.c deleted file mode 100644 index 181e83d6a..000000000 --- a/board/bf537-stamp/nand.c +++ /dev/null @@ -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; -} diff --git a/board/davinci/sonata/sonata.c b/board/davinci/sonata/sonata.c index 7f9d9bba3..817970aea 100644 --- a/board/davinci/sonata/sonata.c +++ b/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 */ diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 94514160b..2f7052122 100644 --- a/common/cmd_nand.c +++ b/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) { diff --git a/common/cmd_onenand.c b/common/cmd_onenand.c index 85bd2cb68..9090940ae 100644 --- a/common/cmd_onenand.c +++ b/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" diff --git a/common/env_nand.c b/common/env_nand.c index 76569da0f..90a1c4547 100644 --- a/common/env_nand.c +++ b/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); diff --git a/common/env_onenand.c b/common/env_onenand.c index ed7705172..48089a960 100644 --- a/common/env_onenand.c +++ b/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; diff --git a/doc/README.nand b/doc/README.nand index bb722892d..b077d9ab3 100644 --- a/doc/README.nand +++ b/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:  ===== diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 71dd5b9b8..c1325b905 100644 --- a/drivers/mtd/nand/Makefile +++ b/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) diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 8ef18b812..ca40c6ac0 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/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_addr->NANDF1ECC; -	dummy = emif_addr->NANDF2ECC; -	dummy = emif_addr->NANDF3ECC; -	dummy = emif_addr->NANDF4ECC; +	dummy = emif_regs->NANDF1ECC; -	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]; - -	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); +	/* 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. +	 */ -			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;  } diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 3f318e02e..77a33c078 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/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 */ diff --git a/drivers/mtd/nand/nand_plat.c b/drivers/mtd/nand/nand_plat.c new file mode 100644 index 000000000..b35492b9f --- /dev/null +++ b/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; +} diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index 88206d067..fc16282c2 100644 --- a/drivers/mtd/nand/nand_util.c +++ b/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; diff --git a/include/asm-arm/arch-davinci/nand_defs.h b/include/asm-arm/arch-davinci/nand_defs.h index 187d3c343..386540e41 100644 --- a/include/asm-arm/arch-davinci/nand_defs.h +++ b/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 diff --git a/include/configs/bf537-stamp.h b/include/configs/bf537-stamp.h index 0a86e83fb..98300db7b 100644 --- a/include/configs/bf537-stamp.h +++ b/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)  /* diff --git a/include/configs/bfin_adi_common.h b/include/configs/bfin_adi_common.h index 4149a2947..1ca2e5142 100644 --- a/include/configs/bfin_adi_common.h +++ b/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 diff --git a/include/configs/smdk6400.h b/include/configs/smdk6400.h index cac58cf32..018f576ef 100644 --- a/include/configs/smdk6400.h +++ b/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;" \ diff --git a/include/nand.h b/include/nand.h index 065a42c3e..23f3ca1db 100644 --- a/include/nand.h +++ b/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); diff --git a/nand_spl/nand_boot.c b/nand_spl/nand_boot.c index c7eadad1b..b9fd6f544 100644 --- a/nand_spl/nand_boot.c +++ b/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);  |