diff options
| author | Wolfgang Denk <wd@denx.de> | 2012-05-20 22:47:40 +0200 | 
|---|---|---|
| committer | Wolfgang Denk <wd@denx.de> | 2012-05-20 22:47:40 +0200 | 
| commit | 8fa3d2b8161bb73b759c9db5c811c885ca5ec60c (patch) | |
| tree | f7aab3c7e50e90c22338450b2f417b3fff12b8a3 | |
| parent | 8bd07c9aaf4628931ab8da6eb0f83e517d9381a7 (diff) | |
| parent | e52fee9b04157c3f5bd73bb122e95d0c6ebb2270 (diff) | |
| download | olio-uboot-2014.01-8fa3d2b8161bb73b759c9db5c811c885ca5ec60c.tar.xz olio-uboot-2014.01-8fa3d2b8161bb73b759c9db5c811c885ca5ec60c.zip | |
Merge branch 'master' of git://git.denx.de/u-boot-nand-flash
* 'master' of git://git.denx.de/u-boot-nand-flash:
  NAND: Remove ONFI detection message to from bootup log
  driver/mtd:IFC: Fix possible memory leak
  driver/mtd: IFC NAND: Add support of ONFI NAND flash
  mtd, nand: move some printfs to debug output.
  nand_util: correct YAFFS image write function
  powerpc/85xx: fix NAND boot linker scripts for -fpic
  nand: extend .raw accesses to work on multiple pages
| -rw-r--r-- | arch/powerpc/cpu/mpc85xx/u-boot-nand.lds | 5 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc85xx/u-boot-nand_spl.lds | 4 | ||||
| -rw-r--r-- | common/cmd_nand.c | 95 | ||||
| -rw-r--r-- | doc/README.nand | 16 | ||||
| -rw-r--r-- | drivers/mtd/nand/fsl_ifc_nand.c | 22 | ||||
| -rw-r--r-- | drivers/mtd/nand/nand_base.c | 5 | ||||
| -rw-r--r-- | drivers/mtd/nand/nand_bbt.c | 13 | ||||
| -rw-r--r-- | drivers/mtd/nand/nand_util.c | 2 | 
8 files changed, 113 insertions, 49 deletions
| diff --git a/arch/powerpc/cpu/mpc85xx/u-boot-nand.lds b/arch/powerpc/cpu/mpc85xx/u-boot-nand.lds index b1a1dac16..8ba939916 100644 --- a/arch/powerpc/cpu/mpc85xx/u-boot-nand.lds +++ b/arch/powerpc/cpu/mpc85xx/u-boot-nand.lds @@ -51,13 +51,14 @@ SECTIONS    PROVIDE (erotext = .);    .reloc   :    { -    KEEP(*(.got))      _GOT2_TABLE_ = .;      KEEP(*(.got2)) +    KEEP(*(.got)) +    PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4);      _FIXUP_TABLE_ = .;      KEEP(*(.fixup))    } -  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2; +  __got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1;    __fixup_entries = (. - _FIXUP_TABLE_) >> 2;    .data    : diff --git a/arch/powerpc/cpu/mpc85xx/u-boot-nand_spl.lds b/arch/powerpc/cpu/mpc85xx/u-boot-nand_spl.lds index 852f9aa4a..668158f70 100644 --- a/arch/powerpc/cpu/mpc85xx/u-boot-nand_spl.lds +++ b/arch/powerpc/cpu/mpc85xx/u-boot-nand_spl.lds @@ -37,10 +37,12 @@ SECTIONS  	.reloc : {  		_GOT2_TABLE_ = .;  		KEEP(*(.got2)) +		KEEP(*(.got)) +		PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4);  		_FIXUP_TABLE_ = .;  		KEEP(*(.fixup))  	} -	__got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2; +	__got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1;  	__fixup_entries = (. - _FIXUP_TABLE_) >> 2;  	. = ALIGN(8); diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 0fd3a6c41..f060a317e 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -11,7 +11,7 @@   * Added 16-bit nand support   * (C) 2004 Texas Instruments   * - * Copyright 2010 Freescale Semiconductor + * Copyright 2010, 2012 Freescale Semiconductor   * The portions of this file whose copyright is held by Freescale and which   * are not considered a derived work of GPL v2-only code may be distributed   * and/or modified under the terms of the GNU General Public License as @@ -390,6 +390,41 @@ static void nand_print_and_set_info(int idx)  	setenv("nand_erasesize", buf);  } +static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count, +			int read) +{ +	int ret = 0; +	size_t rwsize; + +	while (count--) { +		/* Raw access */ +		mtd_oob_ops_t ops = { +			.datbuf = (u8 *)addr, +			.oobbuf = ((u8 *)addr) + nand->writesize, +			.len = nand->writesize, +			.ooblen = nand->oobsize, +			.mode = MTD_OOB_RAW +		}; + +		rwsize = nand->writesize + nand->oobsize; +		if (read) +			ret = nand->read_oob(nand, off, &ops); +		else +			ret = nand->write_oob(nand, off, &ops); + +		if (ret) { +			printf("%s: error at offset %llx, ret %d\n", +				__func__, (long long)off, ret); +			break; +		} + +		addr += nand->writesize + nand->oobsize; +		off += nand->writesize; +	} + +	return ret; +} +  int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])  {  	int i, ret = 0; @@ -568,7 +603,9 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])  	if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {  		size_t rwsize; +		ulong pagecount = 1;  		int read; +		int raw;  		if (argc < 4)  			goto usage; @@ -577,13 +614,36 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])  		read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */  		printf("\nNAND %s: ", read ? "read" : "write"); -		if (arg_off_size(argc - 3, argv + 3, &dev, &off, &size) != 0) -			return 1;  		nand = &nand_info[dev]; -		rwsize = size;  		s = strchr(cmd, '.'); + +		if (!strcmp(s, ".raw")) { +			raw = 1; + +			if (arg_off(argv[3], &dev, &off, &size)) +				return 1; + +			if (argc > 4 && !str2long(argv[4], &pagecount)) { +				printf("'%s' is not a number\n", argv[4]); +				return 1; +			} + +			if (pagecount * nand->writesize > size) { +				puts("Size exceeds partition or device limit\n"); +				return -1; +			} + +			rwsize = pagecount * (nand->writesize + nand->oobsize); +		} else { +			if (arg_off_size(argc - 3, argv + 3, &dev, +						&off, &size) != 0) +				return 1; + +			rwsize = size; +		} +  		if (!s || !strcmp(s, ".jffs2") ||  		    !strcmp(s, ".e") || !strcmp(s, ".i")) {  			if (read) @@ -609,7 +669,8 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])  				return 1;  			}  			ret = nand_write_skip_bad(nand, off, &rwsize, -						(u_char *)addr, WITH_YAFFS_OOB); +						(u_char *)addr, +						WITH_INLINE_OOB);  #endif  		} else if (!strcmp(s, ".oob")) {  			/* out-of-band data */ @@ -623,22 +684,8 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])  				ret = nand->read_oob(nand, off, &ops);  			else  				ret = nand->write_oob(nand, off, &ops); -		} else if (!strcmp(s, ".raw")) { -			/* Raw access */ -			mtd_oob_ops_t ops = { -				.datbuf = (u8 *)addr, -				.oobbuf = ((u8 *)addr) + nand->writesize, -				.len = nand->writesize, -				.ooblen = nand->oobsize, -				.mode = MTD_OOB_RAW -			}; - -			rwsize = nand->writesize + nand->oobsize; - -			if (read) -				ret = nand->read_oob(nand, off, &ops); -			else -				ret = nand->write_oob(nand, off, &ops); +		} else if (raw) { +			ret = raw_access(nand, addr, off, pagecount, read);  		} else {  			printf("Unknown nand command suffix '%s'.\n", s);  			return 1; @@ -732,9 +779,9 @@ U_BOOT_CMD(  	"nand write - addr off|partition size\n"  	"    read/write 'size' bytes starting at offset 'off'\n"  	"    to/from memory address 'addr', skipping bad blocks.\n" -	"nand read.raw - addr off|partition\n" -	"nand write.raw - addr off|partition\n" -	"    Use read.raw/write.raw to avoid ECC and access the page as-is.\n" +	"nand read.raw - addr off|partition [count]\n" +	"nand write.raw - addr off|partition [count]\n" +	"    Use read.raw/write.raw to avoid ECC and access the flash as-is.\n"  #ifdef CONFIG_CMD_NAND_TRIMFFS  	"nand write.trimffs - addr off|partition size\n"  	"    write 'size' bytes starting at offset 'off' from memory address\n" diff --git a/doc/README.nand b/doc/README.nand index 04a87c991..1602b5eee 100644 --- a/doc/README.nand +++ b/doc/README.nand @@ -94,14 +94,14 @@ Commands:        of data for one 512-byte page or 2 256-byte pages. There is no check        for bad blocks. -   nand read.raw addr ofs|partition -      Read page from `ofs' in NAND flash to `addr'. This reads the raw page, -      so ECC is avoided and the OOB area is read as well. - -   nand write.raw addr ofs|partition -      Write page from `addr' to `ofs' in NAND flash. This writes the raw page, -      so ECC is avoided and the OOB area is written as well, making the whole -      page written as-is. +   nand read.raw addr ofs|partition [count] +   nand write.raw addr ofs|partition [count] +      Read or write one or more pages at "ofs" in NAND flash, from or to +      "addr" in memory.  This is a raw access, so ECC is avoided and the +      OOB area is transferred as well.  If count is absent, it is assumed +      to be one page.  As with .yaffs2 accesses, the data is formatted as +      a packed sequence of "data, oob, data, oob, ..." -- no alignment of +      individual pages is maintained.  Configuration Options: diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index 5cac78b29..b3b7c705e 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c @@ -384,19 +384,30 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,  	/* READID must read all possible bytes while CEB is active */  	case NAND_CMD_READID: +	case NAND_CMD_PARAM: { +		int timing = IFC_FIR_OP_RB; +		if (command == NAND_CMD_PARAM) +			timing = IFC_FIR_OP_RBCD; +  		out_be32(&ifc->ifc_nand.nand_fir0,  				(IFC_FIR_OP_CMD0 << IFC_NAND_FIR0_OP0_SHIFT) |  				(IFC_FIR_OP_UA  << IFC_NAND_FIR0_OP1_SHIFT) | -				(IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT)); +				(timing << IFC_NAND_FIR0_OP2_SHIFT));  		out_be32(&ifc->ifc_nand.nand_fcr0, -				NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT); -		/* 4 bytes for manuf, device and exts */ -		out_be32(&ifc->ifc_nand.nand_fbcr, 4); -		ctrl->read_bytes = 4; +				command << IFC_NAND_FCR0_CMD0_SHIFT); +		out_be32(&ifc->ifc_nand.row3, column); + +		/* +		 * although currently it's 8 bytes for READID, we always read +		 * the maximum 256 bytes(for PARAM) +		 */ +		out_be32(&ifc->ifc_nand.nand_fbcr, 256); +		ctrl->read_bytes = 256;  		set_addr(mtd, 0, 0, 0);  		fsl_ifc_run_command(mtd);  		return; +	}  	/* ERASE1 stores the block and page address */  	case NAND_CMD_ERASE1: @@ -764,6 +775,7 @@ int board_nand_init(struct nand_chip *nand)  	if (priv->bank >= MAX_BANKS) {  		printf("%s: address did not match any "  		       "chip selects\n", __func__); +		kfree(priv);  		return -ENODEV;  	} diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index bef79bed0..bfd668fa0 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2530,13 +2530,14 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,  		chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I')  		return 0; -	printk(KERN_INFO "ONFI flash detected\n"); +	MTDDEBUG(MTD_DEBUG_LEVEL0, "ONFI flash detected\n");  	chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);  	for (i = 0; i < 3; i++) {  		chip->read_buf(mtd, (uint8_t *)p, sizeof(*p));  		if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==  				le16_to_cpu(p->crc)) { -			printk(KERN_INFO "ONFI param page %d valid\n", i); +			MTDDEBUG(MTD_DEBUG_LEVEL0, +				 "ONFI param page %d valid\n", i);  			break;  		}  	} diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index dc6c6480e..74a7061b0 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -259,10 +259,10 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,  					mtd->ecc_stats.bbtblocks++;  					continue;  				} -				/* Leave it for now, if its matured we can move this -				 * message to MTD_DEBUG_LEVEL0 */ -				printk(KERN_DEBUG "nand_read_bbt: Bad block at 0x%012llx\n", -				       (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift); +				MTDDEBUG(MTD_DEBUG_LEVEL0, "nand_read_bbt: " \ +					"Bad block at 0x%012llx\n", +					(loff_t)((offs << 2) + (act >> 1)) +					<< this->bbt_erase_shift);  				/* Factory marked bad or worn out ? */  				if (tmp == 0)  					this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06); @@ -651,8 +651,9 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr  		if (td->pages[i] == -1)  			printk(KERN_WARNING "Bad block table not found for chip %d\n", i);  		else -			printk(KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i], -			       td->version[i]); +			MTDDEBUG(MTD_DEBUG_LEVEL0, "Bad block table found " \ +				"at page %d, version 0x%02X\n", td->pages[i], +				td->version[i]);  	}  	return 0;  } diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index 60c778e63..7ed8b1891 100644 --- a/drivers/mtd/nand/nand_util.c +++ b/drivers/mtd/nand/nand_util.c @@ -564,7 +564,7 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,  				ops.oobbuf = ops.datbuf + pagesize;  				rval = nand->write_oob(nand, offset, &ops); -				if (!rval) +				if (rval != 0)  					break;  				offset += pagesize; |