Browse Source

Flex-OneNAND driver support

This patch adds support for Flex-OneNAND devices.

Signed-off-by: Rohit Hagargundgi <h.rohit@samsung.com>
Signed-off-by: Amul Kumar Saha <amul.saha@samsung.com>
Amul Kumar Saha 14 years ago
parent
commit
cacbe91958

File diff suppressed because it is too large
+ 611 - 81
drivers/mtd/onenand/onenand_base.c


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

@@ -69,6 +69,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t * buf,
 	loff_t from;
 	size_t readlen, ooblen;
 	struct mtd_oob_ops ops;
+	int rgn;
 
 	printk(KERN_INFO "Scanning device for bad blocks\n");
 
@@ -82,7 +83,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t * buf,
 	/* Note that numblocks is 2 * (real numblocks) here;
 	 * see i += 2 below as it makses shifting and masking less painful
 	 */
-	numblocks = mtd->size >> (bbm->bbt_erase_shift - 1);
+	numblocks = this->chipsize >> (bbm->bbt_erase_shift - 1);
 	startblock = 0;
 	from = 0;
 
@@ -115,7 +116,12 @@ static int create_bbt(struct mtd_info *mtd, uint8_t * buf,
 			}
 		}
 		i += 2;
-		from += (1 << bbm->bbt_erase_shift);
+
+		if (FLEXONENAND(this)) {
+			rgn = flexonenand_region(mtd, from);
+			from += mtd->eraseregions[rgn].erasesize;
+		} else
+			from += (1 << bbm->bbt_erase_shift);
 	}
 
 	return 0;
@@ -152,7 +158,7 @@ static int onenand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
 	uint8_t res;
 
 	/* Get block number * 2 */
-	block = (int)(offs >> (bbm->bbt_erase_shift - 1));
+	block = (int) (onenand_block(this, offs) << 1);
 	res = (bbm->bbt[block >> 3] >> (block & 0x06)) & 0x03;
 
 	MTDDEBUG (MTD_DEBUG_LEVEL2,
@@ -191,7 +197,7 @@ int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 	struct bbm_info *bbm = this->bbm;
 	int len, ret = 0;
 
-	len = mtd->size >> (this->erase_shift + 2);
+	len = this->chipsize >> (this->erase_shift + 2);
 	/* Allocate memory (2bit per block) */
 	bbm->bbt = malloc(len);
 	if (!bbm->bbt) {

+ 3 - 1
drivers/mtd/onenand/onenand_uboot.c

@@ -40,8 +40,10 @@ void onenand_init(void)
 
 	onenand_scan(&onenand_mtd, 1);
 
+	if (onenand_chip.device_id & DEVICE_IS_FLEXONENAND)
+		puts("Flex-");
 	puts("OneNAND: ");
-	print_size(onenand_mtd.size, "\n");
+	print_size(onenand_chip.chipsize, "\n");
 
 #ifdef CONFIG_MTD_DEVICE
 	/*

+ 15 - 1
include/linux/mtd/onenand.h

@@ -20,8 +20,9 @@
 #include <linux/mtd/compat.h>
 #include <linux/mtd/bbm.h>
 
+#define MAX_DIES		2
 #define MAX_BUFFERRAM		2
-#define MAX_ONENAND_PAGESIZE	(2048 + 64)
+#define MAX_ONENAND_PAGESIZE	(4096 + 128)
 
 /* Scan and identify a OneNAND device */
 extern int onenand_scan (struct mtd_info *mtd, int max_chips);
@@ -39,9 +40,14 @@ struct onenand_bufferram {
 /**
  * struct onenand_chip - OneNAND Private Flash Chip Data
  * @param base		[BOARDSPECIFIC] address to access OneNAND
+ * @dies:               [INTERN][FLEXONENAND] number of dies on chip
+ * @boundary:           [INTERN][FLEXONENAND] Boundary of the dies
+ * @diesize:            [INTERN][FLEXONENAND] Size of the dies
  * @param chipsize	[INTERN] the size of one chip for multichip arrays
  * @param device_id	[INTERN] device ID
  * @param verstion_id	[INTERN] version ID
+ * @technology		[INTERN] describes the internal NAND array technology such as SLC or MLC.
+ * @density_mask:	[INTERN] chip density, used for DDP devices
  * @param options	[BOARDSPECIFIC] various chip options. They can partly be set to inform onenand_scan about
  * @param erase_shift	[INTERN] number of address bits in a block
  * @param page_shift	[INTERN] number of address bits in a page
@@ -64,9 +70,13 @@ struct onenand_bufferram {
  */
 struct onenand_chip {
 	void __iomem *base;
+	unsigned int dies;
+	unsigned int boundary[MAX_DIES];
+	unsigned int diesize[MAX_DIES];
 	unsigned int chipsize;
 	unsigned int device_id;
 	unsigned int version_id;
+	unsigned int technology;
 	unsigned int density_mask;
 	unsigned int options;
 
@@ -124,6 +134,8 @@ struct onenand_chip {
 #define ONENAND_SET_BUFFERRAM0(this)		(this->bufferram_index = 0)
 #define ONENAND_SET_BUFFERRAM1(this)		(this->bufferram_index = 1)
 
+#define FLEXONENAND(this)	(this->device_id & DEVICE_IS_FLEXONENAND)
+#define ONENAND_IS_MLC(this)	(this->technology & ONENAND_TECHNOLOGY_IS_MLC)
 #define ONENAND_IS_DDP(this)						\
 	(this->device_id & ONENAND_DEVICE_IS_DDP)
 
@@ -157,4 +169,6 @@ struct onenand_manufacturers {
 int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
 			struct mtd_oob_ops *ops);
 
+unsigned int onenand_block(struct onenand_chip *this, loff_t addr);
+int flexonenand_region(struct mtd_info *mtd, loff_t addr);
 #endif				/* __LINUX_MTD_ONENAND_H */

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

@@ -67,6 +67,9 @@
 /*
  * Device ID Register F001h (R)
  */
+#define DEVICE_IS_FLEXONENAND		(1 << 9)
+#define FLEXONENAND_PI_MASK		(0x3ff)
+#define FLEXONENAND_PI_UNLOCK_SHIFT	(14)
 #define ONENAND_DEVICE_DENSITY_MASK	(0xf)
 #define ONENAND_DEVICE_DENSITY_SHIFT	(4)
 #define ONENAND_DEVICE_IS_DDP		(1 << 3)
@@ -83,6 +86,11 @@
  */
 #define ONENAND_VERSION_PROCESS_SHIFT	(8)
 
+/*
+ * Technology Register F006h (R)
+ */
+#define ONENAND_TECHNOLOGY_IS_MLC	(1 << 0)
+
 /*
  * Start Address 1 F100h (R/W)
  */
@@ -93,7 +101,7 @@
 /*
  * Start Address 8 F107h (R/W)
  */
-#define ONENAND_FPA_MASK		(0x3f)
+#define ONENAND_FPA_MASK		(0x7f)
 #define ONENAND_FPA_SHIFT		(2)
 #define ONENAND_FSA_MASK		(0x03)
 
@@ -105,7 +113,7 @@
 #define ONENAND_BSA_BOOTRAM		(0 << 2)
 #define ONENAND_BSA_DATARAM0		(2 << 2)
 #define ONENAND_BSA_DATARAM1		(3 << 2)
-#define ONENAND_BSC_MASK		(0x03)
+#define ONENAND_BSC_MASK		(0x07)
 
 /*
  * Command Register F220h (R/W)
@@ -125,9 +133,14 @@
 #define ONENAND_CMD_ERASE_VERIFY	(0x71)
 #define ONENAND_CMD_RESET		(0xF0)
 #define ONENAND_CMD_READID		(0x90)
+#define FLEXONENAND_CMD_RESET		(0xF3)
+#define FLEXONENAND_CMD_PI_UPDATE	(0x05)
+#define FLEXONENAND_CMD_PI_ACCESS	(0x66)
+#define FLEXONENAND_CMD_RECOVER_LSB	(0x05)
 
 /* NOTE: Those are not *REAL* commands */
 #define ONENAND_CMD_BUFFERRAM		(0x1978)
+#define FLEXONENAND_CMD_READ_PI		(0x1985)
 
 /*
  * System Configuration 1 Register F221h (R, R/W)
@@ -190,5 +203,6 @@
 #define ONENAND_ECC_2BIT		(1 << 1)
 #define ONENAND_ECC_2BIT_ALL		(0xAAAA)
 #define ONENAND_ECC_4BIT_UNCORRECTABLE	(0x1010)
+#define FLEXONENAND_UNCORRECTABLE_ERROR (0x1010)
 
 #endif				/* __ONENAND_REG_H */

+ 10 - 0
include/onenand_uboot.h

@@ -23,6 +23,7 @@ struct erase_info;
 struct onenand_chip;
 
 extern struct mtd_info onenand_mtd;
+extern struct onenand_chip onenand_chip;
 
 /* board */
 extern void onenand_board_init(struct mtd_info *);
@@ -38,6 +39,15 @@ extern int onenand_erase(struct mtd_info *mtd, struct erase_info *instr);
 
 extern char *onenand_print_device_info(int device, int version);
 
+extern unsigned onenand_block(struct onenand_chip *this, loff_t addr);
+
+extern loff_t onenand_addr(struct onenand_chip *this, int block);
+
+extern int flexonenand_region(struct mtd_info *mtd, loff_t addr);
+
+extern int flexonenand_set_boundary(struct mtd_info *mtd, int die,
+					int boundary, int lock);
+
 /* S3C64xx */
 extern void s3c64xx_onenand_init(struct mtd_info *);
 extern void s3c64xx_set_width_regs(struct onenand_chip *);

Some files were not shown because too many files changed in this diff