[U-Boot-Users] [PATCH] Fix OneNAND build break

Kyungmin Park kmpark at infradead.org
Wed Aug 13 02:11:02 CEST 2008


Since page size field is changed from oobblock to writesize. But OneNAND is not updated.
- fix bufferram management at erase operation
This patch includes the NAND/OneNAND state filed too.

generated against latest git tree

Thank you,
Kyungmin Park

Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
---
diff --git a/common/env_onenand.c b/common/env_onenand.c
index dbd0883..d5c907c 100644
--- a/common/env_onenand.c
+++ b/common/env_onenand.c
@@ -40,7 +40,7 @@ extern struct onenand_chip onenand_chip;
 /* References to names in env_common.c */
 extern uchar default_environment[];
 
-#define ONENAND_ENV_SIZE(mtd)	(mtd.oobblock - ENV_HEADER_SIZE)
+#define ONENAND_ENV_SIZE(mtd)	(mtd.writesize - ENV_HEADER_SIZE)
 
 char *env_name_spec = "OneNAND";
 
@@ -68,12 +68,12 @@ void env_relocate_spec(void)
 	env_addr = CFG_ENV_ADDR;
 
 	/* Check OneNAND exist */
-	if (onenand_mtd.oobblock)
+	if (onenand_mtd.writesize)
 		/* Ignore read fail */
-		onenand_read(&onenand_mtd, env_addr, onenand_mtd.oobblock,
+		onenand_read(&onenand_mtd, env_addr, onenand_mtd.writesize,
 			     &retlen, (u_char *) env_ptr);
 	else
-		onenand_mtd.oobblock = MAX_ONENAND_PAGESIZE;
+		onenand_mtd.writesize = MAX_ONENAND_PAGESIZE;
 
 	if (crc32(0, env_ptr->data, ONENAND_ENV_SIZE(onenand_mtd)) !=
 	    env_ptr->crc)
@@ -109,7 +109,7 @@ int saveenv(void)
 	env_ptr->crc =
 	    crc32(0, env_ptr->data, ONENAND_ENV_SIZE(onenand_mtd));
 
-	if (onenand_write(&onenand_mtd, env_addr, onenand_mtd.oobblock, &retlen,
+	if (onenand_write(&onenand_mtd, env_addr, onenand_mtd.writesize, &retlen,
 	     (u_char *) env_ptr)) {
 		printf("OneNAND: write failed at 0x%08x\n", instr.addr);
 		return 2;
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index ded1706..d63f392 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -331,7 +331,7 @@ static inline int onenand_bufferram_offset(struct mtd_info *mtd, int area)
 
 	if (ONENAND_CURRENT_BUFFERRAM(this)) {
 		if (area == ONENAND_DATARAM)
-			return mtd->oobblock;
+			return mtd->writesize;
 		if (area == ONENAND_SPARERAM)
 			return mtd->oobsize;
 	}
@@ -482,6 +482,30 @@ static int onenand_update_bufferram(struct mtd_info *mtd, loff_t addr,
 }
 
 /**
+ * onenand_invalidate_bufferram - [GENERIC] Invalidate BufferRAM information
+ * @param mtd           MTD data structure
+ * @param addr          start address to invalidate
+ * @param len           length to invalidate
+ *
+ * Invalidate BufferRAM information
+ */
+static void onenand_invalidate_bufferram(struct mtd_info *mtd, loff_t addr,
+                unsigned int len)
+{
+        struct onenand_chip *this = mtd->priv;
+        int i;
+        loff_t end_addr = addr + len;
+
+        /* Invalidate BufferRAM */
+	for (i = 0; i < MAX_BUFFERRAM; i++) {
+		loff_t buf_addr = this->bufferram[i].block << this->erase_shift;
+
+		if (buf_addr >= addr && buf_addr < end_addr)
+			this->bufferram[i].valid = 0;
+	}
+}
+
+/**
  * onenand_get_device - [GENERIC] Get chip for selected access
  * @param mtd		MTD device structure
  * @param new_state	the state which is requested
@@ -541,15 +565,15 @@ static int onenand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
 	onenand_get_device(mtd, FL_READING);
 
 	while (read < len) {
-		thislen = min_t(int, mtd->oobblock, len - read);
+		thislen = min_t(int, mtd->writesize, len - read);
 
-		column = from & (mtd->oobblock - 1);
-		if (column + thislen > mtd->oobblock)
-			thislen = mtd->oobblock - column;
+		column = from & (mtd->writesize - 1);
+		if (column + thislen > mtd->writesize)
+			thislen = mtd->writesize - column;
 
 		if (!onenand_check_bufferram(mtd, from)) {
 			this->command(mtd, ONENAND_CMD_READ, from,
-				      mtd->oobblock);
+				      mtd->writesize);
 			ret = this->wait(mtd, FL_READING);
 			/* First copy data and check return value for ECC handling */
 			onenand_update_bufferram(mtd, from, 1);
@@ -664,7 +688,7 @@ int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
 		/* Read more? */
 		if (read < len) {
 			/* Page size */
-			from += mtd->oobblock;
+			from += mtd->writesize;
 			column = 0;
 		}
 	}
@@ -691,7 +715,7 @@ static int onenand_verify_page(struct mtd_info *mtd, u_char * buf,
 	void __iomem *dataram0, *dataram1;
 	int ret = 0;
 
-	this->command(mtd, ONENAND_CMD_READ, addr, mtd->oobblock);
+	this->command(mtd, ONENAND_CMD_READ, addr, mtd->writesize);
 
 	ret = this->wait(mtd, FL_READING);
 	if (ret)
@@ -701,9 +725,9 @@ static int onenand_verify_page(struct mtd_info *mtd, u_char * buf,
 
 	/* Check, if the two dataram areas are same */
 	dataram0 = this->base + ONENAND_DATARAM;
-	dataram1 = dataram0 + mtd->oobblock;
+	dataram1 = dataram0 + mtd->writesize;
 
-	if (memcmp(dataram0, dataram1, mtd->oobblock))
+	if (memcmp(dataram0, dataram1, mtd->writesize))
 		return -EBADMSG;
 
 	return 0;
@@ -712,7 +736,7 @@ static int onenand_verify_page(struct mtd_info *mtd, u_char * buf,
 #define onenand_verify_page(...)	(0)
 #endif
 
-#define NOTALIGNED(x)	((x & (mtd->oobblock - 1)) != 0)
+#define NOTALIGNED(x)	((x & (mtd->writesize - 1)) != 0)
 
 /**
  * onenand_write_ecc - [MTD Interface] OneNAND write with ECC
@@ -760,15 +784,15 @@ static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
 
 	/* Loop until all data write */
 	while (written < len) {
-		int thislen = min_t(int, mtd->oobblock, len - written);
+		int thislen = min_t(int, mtd->writesize, len - written);
 
-		this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobblock);
+		this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->writesize);
 
 		this->write_bufferram(mtd, ONENAND_DATARAM, buf, 0, thislen);
 		this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0,
 				      mtd->oobsize);
 
-		this->command(mtd, ONENAND_CMD_PROG, to, mtd->oobblock);
+		this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize);
 
 		onenand_update_bufferram(mtd, to, 1);
 
@@ -893,6 +917,25 @@ int onenand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
 }
 
 /**
+ * onenand_block_isbad_nolock - [GENERIC] Check if a block is marked bad
+ * @param mtd		MTD device structure
+ * @param ofs		offset from device start
+ * @param allowbbt	1, if its allowed to access the bbt area
+ *
+ * Check, if the block is bad, Either by reading the bad block table or
+ * calling of the scan function.
+ */
+static int onenand_block_isbad_nolock(struct mtd_info *mtd, loff_t ofs, int allowbbt)
+{
+	struct onenand_chip *this = mtd->priv;
+	struct bbm_info *bbm = this->bbm;
+
+	/* Return info from the table */
+	return bbm->isbad_bbt(mtd, ofs, allowbbt);
+}
+
+
+/**
  * onenand_erase - [MTD Interface] erase block(s)
  * @param mtd		MTD device structure
  * @param instr		erase instruction
@@ -950,6 +993,8 @@ int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
 
 		this->command(mtd, ONENAND_CMD_ERASE, addr, block_size);
 
+		onenand_invalidate_bufferram(mtd, addr, block_size);
+
 		ret = this->wait(mtd, FL_ERASING);
 		/* Check, if it is write protected */
 		if (ret) {
@@ -1005,30 +1050,45 @@ void onenand_sync(struct mtd_info *mtd)
  * onenand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad
  * @param mtd		MTD device structure
  * @param ofs		offset relative to mtd start
+ *
+ * Check whether the block is bad
  */
 int onenand_block_isbad(struct mtd_info *mtd, loff_t ofs)
 {
-	/*
-	 * TODO
-	 * 1. Bad block table (BBT)
-	 *   -> using NAND BBT to support JFFS2
-	 * 2. Bad block management (BBM)
-	 *   -> bad block replace scheme
-	 *
-	 * Currently we do nothing
-	 */
-	return 0;
+	int ret;
+
+	/* Check for invalid offset */
+	if (ofs > mtd->size)
+		return -EINVAL;
+
+	onenand_get_device(mtd, FL_READING);
+	ret = onenand_block_isbad_nolock(mtd,ofs, 0);
+	onenand_release_device(mtd);
+	return ret;
 }
 
 /**
  * onenand_block_markbad - [MTD Interface] Mark the block at the given offset as bad
  * @param mtd		MTD device structure
  * @param ofs		offset relative to mtd start
+ *
+ * Mark the block as bad
  */
 int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs)
 {
-	/* see above */
-	return 0;
+	struct onenand_chip *this = mtd->priv;
+	int ret;
+
+	ret = onenand_block_isbad(mtd, ofs);
+	if (ret) {
+		/* If it was bad already, return success and do nothing */
+		if (ret > 0)
+			return 0;
+		return ret;
+	}
+
+	ret = this->block_markbad(mtd, ofs);
+	return ret;
 }
 
 /**
@@ -1184,10 +1244,8 @@ static int onenand_probe(struct mtd_info *mtd)
 	/* Reset OneNAND to read default register values */
 	this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_BOOTRAM);
 
-	{
-		int i;
-		for (i = 0; i < 10000; i++) ;
-	}
+	/* Wait reset */
+	this->wait(mtd, FL_RESETING);
 
 	/* Read manufacturer and device IDs from Register */
 	maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
@@ -1212,16 +1270,16 @@ static int onenand_probe(struct mtd_info *mtd)
 
 	/* OneNAND page size & block size */
 	/* The data buffer size is equal to page size */
-	mtd->oobblock =
+	mtd->writesize =
 	    this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE);
-	mtd->oobsize = mtd->oobblock >> 5;
+	mtd->oobsize = mtd->writesize >> 5;
 	/* Pagers per block is always 64 in OneNAND */
-	mtd->erasesize = mtd->oobblock << 6;
+	mtd->erasesize = mtd->writesize << 6;
 
 	this->erase_shift = ffs(mtd->erasesize) - 1;
-	this->page_shift = ffs(mtd->oobblock) - 1;
+	this->page_shift = ffs(mtd->writesize) - 1;
 	this->ppb_shift = (this->erase_shift - this->page_shift);
-	this->page_mask = (mtd->erasesize / mtd->oobblock) - 1;
+	this->page_mask = (mtd->erasesize / mtd->writesize) - 1;
 
 	/* REVIST: Multichip handling */
 
@@ -1240,11 +1298,10 @@ static int onenand_probe(struct mtd_info *mtd)
 		this->options |= ONENAND_CONT_LOCK;
 	}
 
+	mtd->flags = MTD_CAP_NANDFLASH;
 	mtd->erase = onenand_erase;
 	mtd->read = onenand_read;
 	mtd->write = onenand_write;
-	mtd->read_ecc = onenand_read_ecc;
-	mtd->write_ecc = onenand_write_ecc;
 	mtd->read_oob = onenand_read_oob;
 	mtd->write_oob = onenand_write_oob;
 	mtd->sync = onenand_sync;
diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c
index 87344ab..318d877 100644
--- a/drivers/mtd/onenand/onenand_bbt.c
+++ b/drivers/mtd/onenand/onenand_bbt.c
@@ -97,7 +97,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t * buf,
 			/* No need to read pages fully,
 			 * just read required OOB bytes */
 			ret = onenand_read_oob(mtd,
-					     from + j * mtd->oobblock +
+					     from + j * mtd->writesize +
 					     bd->offs, readlen, &retlen,
 					     &buf[0]);
 
@@ -107,7 +107,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t * buf,
 			}
 
 			if (check_short_pattern
-			    (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {
+			    (&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
 				bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
 				printk(KERN_WARNING
 				       "Bad eraseblock %d at 0x%08x\n", i >> 1,
diff --git a/include/linux/mtd/compat.h b/include/linux/mtd/compat.h
index 9036b74..a4dc3e9 100644
--- a/include/linux/mtd/compat.h
+++ b/include/linux/mtd/compat.h
@@ -18,7 +18,11 @@
 #define KERN_DEBUG
 
 #define kmalloc(size, flags)	malloc(size)
-#define kzalloc(size, flags)	calloc(size, 1)
+#define kzalloc(size, flags)	({					\
+	void *__ret = malloc(size);					\
+	memset(__ret, 0, size);						\
+	__ret;								\
+})
 #define vmalloc(size)			malloc(size)
 #define kfree(ptr)				free(ptr)
 #define vfree(ptr)				free(ptr)
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 8e0dc00..131d7aa 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -22,6 +22,21 @@
 #define MTD_ERASE_DONE          0x08
 #define MTD_ERASE_FAILED        0x10
 
+/*
+ * Enumeration for NAND/OneNAND flash chip state
+ */
+enum {
+	FL_READY,
+	FL_READING,
+	FL_WRITING,
+	FL_ERASING,
+	FL_SYNCING,
+	FL_CACHEDPRG,
+	FL_RESETING,
+	FL_UNLOCKING,
+	FL_LOCKING,
+};
+
 /* If the erase fails, fail_addr might indicate exactly which block failed.  If
    fail_addr = 0xffffffff, the failure was not at the device level or was not
    specific to any particular block. */
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 2993a89..7ac72de 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -213,20 +213,6 @@ typedef enum {
 #define NAND_CI_CHIPNR_MSK	0x03
 #define NAND_CI_CELLTYPE_MSK	0x0C
 
-/*
- * nand_state_t - chip states
- * Enumeration for NAND flash chip state
- */
-typedef enum {
-	FL_READY,
-	FL_READING,
-	FL_WRITING,
-	FL_ERASING,
-	FL_SYNCING,
-	FL_CACHEDPRG,
-	FL_PM_SUSPENDED,
-} nand_state_t;
-
 /* Keep gcc happy */
 struct nand_chip;
 
@@ -416,7 +402,7 @@ struct nand_chip {
 	uint8_t		cellinfo;
 	int		badblockpos;
 
-	nand_state_t	state;
+	int 		state;
 
 	uint8_t		*oob_poi;
 	struct nand_hw_control  *controller;
diff --git a/include/linux/mtd/nand_legacy.h b/include/linux/mtd/nand_legacy.h
index b05e726..bb66e45 100644
--- a/include/linux/mtd/nand_legacy.h
+++ b/include/linux/mtd/nand_legacy.h
@@ -55,18 +55,6 @@
 #define NAND_CMD_RESET		0xff
 
 /*
- * Enumeration for NAND flash chip state
- */
-typedef enum {
-	FL_READY,
-	FL_READING,
-	FL_WRITING,
-	FL_ERASING,
-	FL_SYNCING
-} nand_state_t;
-
-
-/*
  * NAND Private Flash Chip Data
  *
  * Structure overview:
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index 4b0c2df..8a0fd0d 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -17,6 +17,7 @@
 /* Note: The header order is impoertant */
 #include <onenand_uboot.h>
 
+#include <linux/mtd/compat.h>
 #include <linux/mtd/bbm.h>
 
 #define MAX_BUFFERRAM		2
@@ -28,20 +29,6 @@ extern int onenand_scan (struct mtd_info *mtd, int max_chips);
 extern void onenand_release (struct mtd_info *mtd);
 
 /**
- * onenand_state_t - chip states
- * Enumeration for OneNAND flash chip state
- */
-typedef enum {
-	FL_READY,
-	FL_READING,
-	FL_WRITING,
-	FL_ERASING,
-	FL_SYNCING,
-	FL_UNLOCKING,
-	FL_LOCKING,
-} onenand_state_t;
-
-/**
  * struct onenand_bufferram - OneNAND BufferRAM Data
  * @param block		block address in BufferRAM
  * @param page		page address in BufferRAM
@@ -103,10 +90,12 @@ struct onenand_chip {
 	unsigned short (*read_word) (void __iomem * addr);
 	void (*write_word) (unsigned short value, void __iomem * addr);
 	void (*mmcontrol) (struct mtd_info * mtd, int sync_read);
+	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;
-	onenand_state_t state;
+	int state;
 
 	struct nand_oobinfo *autooob;
 
diff --git a/include/onenand_uboot.h b/include/onenand_uboot.h
index 4260ee7..41e30a2 100644
--- a/include/onenand_uboot.h
+++ b/include/onenand_uboot.h
@@ -15,18 +15,13 @@
 #define __UBOOT_ONENAND_H
 
 #include <linux/types.h>
-
-struct kvec {
-	void *iov_base;
-	size_t iov_len;
-};
-
-typedef int spinlock_t;
-typedef int wait_queue_head_t;
+#include <mtd_uboot.h>
 
 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,




More information about the U-Boot mailing list