Ver código fonte

Fix OneNAND read_oob/write_oob functions compatability

Also sync with kernel OneNAND codes

Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Scott Wood <scottwood@freescale.com>
Kyungmin Park 16 anos atrás
pai
commit
bfd7f38614

+ 33 - 16
common/cmd_onenand.c

@@ -85,15 +85,25 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 			ulong addr = simple_strtoul(argv[2], NULL, 16);
 			ulong ofs = simple_strtoul(argv[3], NULL, 16);
 			size_t len = simple_strtoul(argv[4], NULL, 16);
-			size_t retlen = 0;
 			int oob = strncmp(argv[1], "read.oob", 8) ? 0 : 1;
+			struct mtd_oob_ops ops;
+
+			ops.mode = MTD_OOB_PLACE;
+
+			if (oob) {
+				ops.len = 0;
+				ops.datbuf = NULL;
+				ops.ooblen = len;
+				ops.oobbuf = (u_char *) addr;
+			} else {
+				ops.len = len;
+				ops.datbuf = (u_char *) addr;
+				ops.ooblen = 0;
+				ops.oobbuf = NULL;
+			}
+			ops.retlen = ops.oobretlen = 0;
 
-			if (oob)
-				onenand_read_oob(&onenand_mtd, ofs, len,
-						 &retlen, (u_char *) addr);
-			else
-				onenand_read(&onenand_mtd, ofs, len, &retlen,
-					     (u_char *) addr);
+			onenand_mtd.read_oob(&onenand_mtd, ofs, &ops);
 			printf("Done\n");
 
 			return 0;
@@ -117,9 +127,12 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 			ulong block = simple_strtoul(argv[3], NULL, 10);
 			ulong page = simple_strtoul(argv[4], NULL, 10);
 			size_t len = simple_strtol(argv[5], NULL, 10);
-			size_t retlen = 0;
 			ulong ofs;
 			int oob = strncmp(argv[1], "block.oob", 9) ? 0 : 1;
+			struct mtd_oob_ops ops;
+
+			ops.mode = MTD_OOB_PLACE;
+
 
 			ofs = block << onenand_chip.erase_shift;
 			if (page)
@@ -127,17 +140,21 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 
 			if (!len) {
 				if (oob)
-					len = 64;
+					ops.ooblen = 64;
 				else
-					len = 512;
+					ops.len = 512;
+			}
+
+			if (oob) {
+				ops.datbuf = NULL;
+				ops.oobbuf = (u_char *) addr;
+			} else {
+				ops.datbuf = (u_char *) addr;
+				ops.oobbuf = NULL;
 			}
+			ops.retlen = ops.oobretlen = 0;
 
-			if (oob)
-				onenand_read_oob(&onenand_mtd, ofs, len,
-						 &retlen, (u_char *) addr);
-			else
-				onenand_read(&onenand_mtd, ofs, len, &retlen,
-					     (u_char *) addr);
+			onenand_read_oob(&onenand_mtd, ofs, &ops);
 			return 0;
 		}
 

Diferenças do arquivo suprimidas por serem muito extensas
+ 664 - 185
drivers/mtd/onenand/onenand_base.c


+ 12 - 10
drivers/mtd/onenand/onenand_bbt.c

@@ -68,6 +68,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t * buf,
 	int startblock;
 	loff_t from;
 	size_t readlen, ooblen;
+	struct mtd_oob_ops ops;
 
 	printk(KERN_INFO "Scanning device for bad blocks\n");
 
@@ -85,25 +86,26 @@ static int create_bbt(struct mtd_info *mtd, uint8_t * buf,
 	startblock = 0;
 	from = 0;
 
+	ops.mode = MTD_OOB_PLACE;
+	ops.ooblen = readlen;
+	ops.oobbuf = buf;
+	ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
+
 	for (i = startblock; i < numblocks;) {
 		int ret;
 
 		for (j = 0; j < len; j++) {
-			size_t retlen;
-
 			/* No need to read pages fully,
 			 * just read required OOB bytes */
-			ret = onenand_read_oob(mtd,
+			ret = onenand_bbt_read_oob(mtd,
 					     from + j * mtd->writesize +
-					     bd->offs, readlen, &retlen,
-					     &buf[0]);
+					     bd->offs, &ops);
 
-			if (ret && ret != -EAGAIN) {
-				printk("ret = %d\n", ret);
-				return ret;
-			}
+			/* If it is a initial bad block, just ignore it */
+                        if (ret == ONENAND_BBT_READ_FATAL_ERROR)
+                                return -EIO;
 
-			if (check_short_pattern
+			if (ret || check_short_pattern
 			    (&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
 				bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
 				printk(KERN_WARNING

+ 7 - 0
include/linux/mtd/bbm.h

@@ -97,6 +97,13 @@ struct nand_bbt_descr {
  */
 #define ONENAND_BADBLOCK_POS	0
 
+/*
+ * Bad block scanning errors
+ */
+#define ONENAND_BBT_READ_ERROR          1
+#define ONENAND_BBT_READ_ECC_ERROR      2
+#define ONENAND_BBT_READ_FATAL_ERROR    4
+
 /**
  * struct bbt_info - [GENERIC] Bad Block Table data structure
  * @param bbt_erase_shift	[INTERN] number of address bits in a bbt entry

+ 20 - 2
include/linux/mtd/onenand.h

@@ -75,6 +75,7 @@ struct onenand_chip {
 	unsigned int page_shift;
 	unsigned int ppb_shift;	/* Pages per block shift */
 	unsigned int page_mask;
+	unsigned int writesize;
 
 	unsigned int bufferram_index;
 	struct onenand_bufferram bufferram[MAX_BUFFERRAM];
@@ -93,25 +94,39 @@ struct onenand_chip {
 	int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
 	int (*scan_bbt)(struct mtd_info *mtd);
 
-	spinlock_t chip_lock;
-	wait_queue_head_t wq;
 	int state;
+	unsigned char *page_buf;
+	unsigned char *oob_buf;
 
 	struct nand_oobinfo *autooob;
+	struct nand_ecclayout *ecclayout;
 
 	void *bbm;
 
 	void *priv;
 };
 
+/*
+ * Helper macros
+ */
 #define ONENAND_CURRENT_BUFFERRAM(this)		(this->bufferram_index)
 #define ONENAND_NEXT_BUFFERRAM(this)		(this->bufferram_index ^ 1)
 #define ONENAND_SET_NEXT_BUFFERRAM(this)	(this->bufferram_index ^= 1)
+#define ONENAND_SET_PREV_BUFFERRAM(this)	(this->bufferram_index ^= 1)
+#define ONENAND_SET_BUFFERRAM0(this)		(this->bufferram_index = 0)
+#define ONENAND_SET_BUFFERRAM1(this)		(this->bufferram_index = 1)
+
+#define ONENAND_IS_DDP(this)						\
+	(this->device_id & ONENAND_DEVICE_IS_DDP)
+
+#define ONENAND_IS_2PLANE(this)			(0)
 
 /*
  * Options bits
  */
 #define ONENAND_CONT_LOCK		(0x0001)
+#define ONENAND_PAGEBUF_ALLOC		(0x1000)
+#define ONENAND_OOBBUF_ALLOC		(0x2000)
 
 /*
  * OneNAND Flash Manufacturer ID Codes
@@ -129,4 +144,7 @@ struct onenand_manufacturers {
 	char *name;
 };
 
+int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
+			struct mtd_oob_ops *ops);
+
 #endif				/* __LINUX_MTD_ONENAND_H */

+ 2 - 0
include/linux/mtd/onenand_regs.h

@@ -83,6 +83,8 @@
  * Start Address 1 F100h (R/W)
  */
 #define ONENAND_DDP_SHIFT		(15)
+#define ONENAND_DDP_CHIP0		(0)
+#define ONENAND_DDP_CHIP1		(1 << ONENAND_DDP_SHIFT)
 
 /*
  * Start Address 8 F107h (R/W)

+ 4 - 10
include/onenand_uboot.h

@@ -16,23 +16,17 @@
 
 #include <linux/types.h>
 
-struct kvec {
-	void *iov_base;
-	size_t iov_len;
-};
-
-typedef int spinlock_t;
-typedef int wait_queue_head_t;
-
 struct mtd_info;
 struct erase_info;
 
+extern struct mtd_info onenand_mtd;
+
 /* Functions */
 extern void onenand_init(void);
 extern int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
 			size_t * retlen, u_char * buf);
-extern int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
-			    size_t * retlen, u_char * buf);
+extern int onenand_read_oob(struct mtd_info *mtd, loff_t from,
+			    struct mtd_oob_ops *ops);
 extern int onenand_write(struct mtd_info *mtd, loff_t from, size_t len,
 			 size_t * retlen, const u_char * buf);
 extern int onenand_erase(struct mtd_info *mtd, struct erase_info *instr);

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff