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

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
Wolfgang Denk преди 13 години
родител
ревизия
8fa3d2b816

+ 3 - 2
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    :

+ 3 - 1
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);

+ 71 - 24
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"

+ 8 - 8
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:
 

+ 17 - 5
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;
 	}
 

+ 3 - 2
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;
 		}
 	}

+ 7 - 6
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;
 }

+ 1 - 1
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;