Merge "mtd: msm_nand: Fix wrong uncorrectable error bit check" into msm-3.0
diff --git a/arch/arm/include/asm/mach/flash.h b/arch/arm/include/asm/mach/flash.h
index 36938ea..7ed9630 100644
--- a/arch/arm/include/asm/mach/flash.h
+++ b/arch/arm/include/asm/mach/flash.h
@@ -13,6 +13,11 @@
 struct mtd_partition;
 struct mtd_info;
 
+enum sw_version {
+	VERSION_1 = 0,
+	VERSION_2,
+};
+
 /*
  * map_name:	the map probe function name
  * name:	flash device name (eg, as used with mtdparts=)
@@ -24,6 +29,7 @@
  * mmcontrol:	method called to enable or disable Sync. Burst Read in OneNAND
  * parts:	optional array of mtd_partitions for static partitioning
  * nr_parts:	number of mtd_partitions for static partitoning
+ * version:	software register interface version
  */
 struct flash_platform_data {
 	const char	*map_name;
@@ -36,6 +42,7 @@
 	void		(*mmcontrol)(struct mtd_info *mtd, int sync_read);
 	struct mtd_partition *parts;
 	unsigned int	nr_parts;
+	enum sw_version	version;
 };
 
 #endif
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 76d79a6..85d00eb 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -627,8 +627,7 @@
 };
 
 struct flash_platform_data msm_nand_data = {
-	.parts		= NULL,
-	.nr_parts	= 0,
+	.version = VERSION_2,
 };
 
 struct platform_device msm_device_nand = {
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 2d79f62..4654606 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -417,7 +417,9 @@
 	},
 };
 
-struct flash_platform_data msm_nand_data;
+struct flash_platform_data msm_nand_data = {
+	.version = VERSION_2,
+};
 
 struct platform_device msm_device_nand = {
 	.name		= "msm_nand",
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index e055579..069714a 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -656,9 +656,7 @@
 };
 
 struct flash_platform_data msm_nand_data = {
-	.parts		= NULL,
-	.nr_parts	= 0,
-	.interleave     = 0,
+	.version = VERSION_2,
 };
 
 struct platform_device msm_device_nand = {
diff --git a/drivers/mtd/devices/msm_nand.c b/drivers/mtd/devices/msm_nand.c
index 3675d2c..798e9e2 100644
--- a/drivers/mtd/devices/msm_nand.c
+++ b/drivers/mtd/devices/msm_nand.c
@@ -76,6 +76,8 @@
 	uint32_t ecc_bch_cfg;
 	uint32_t ecc_parity_bytes;
 	unsigned cw_size;
+	unsigned int uncorrectable_bit_mask;
+	unsigned int num_err_mask;
 };
 
 #define CFG1_WIDE_FLASH (1U << 1)
@@ -1111,9 +1113,8 @@
 		}
 		if (pageerr) {
 			for (n = start_sector; n < cwperpage; n++) {
-				if (enable_bch_ecc ?
-			(dma_buffer->data.result[n].buffer_status & 0x10) :
-			(dma_buffer->data.result[n].buffer_status & 0x8)) {
+				if (dma_buffer->data.result[n].buffer_status &
+					chip->uncorrectable_bit_mask) {
 					/* not thread safe */
 					mtd->ecc_stats.failed++;
 					pageerr = -EBADMSG;
@@ -1123,9 +1124,9 @@
 		}
 		if (!rawerr) { /* check for corretable errors */
 			for (n = start_sector; n < cwperpage; n++) {
-				ecc_errors = enable_bch_ecc ?
-			(dma_buffer->data.result[n].buffer_status & 0xF) :
-			(dma_buffer->data.result[n].buffer_status & 0x7);
+				ecc_errors =
+				(dma_buffer->data.result[n].buffer_status
+				 & chip->num_err_mask);
 				if (ecc_errors) {
 					total_ecc_errors += ecc_errors;
 					/* not thread safe */
@@ -1893,7 +1894,7 @@
 		if (pageerr) {
 			for (n = start_sector; n < cwperpage; n++) {
 				if (dma_buffer->data.result[n].buffer_status
-					& MSM_NAND_BUF_STAT_UNCRCTBL_ERR) {
+					& chip->uncorrectable_bit_mask) {
 					/* not thread safe */
 					mtd->ecc_stats.failed++;
 					pageerr = -EBADMSG;
@@ -1905,7 +1906,7 @@
 			for (n = start_sector; n < cwperpage; n++) {
 				ecc_errors = dma_buffer->data.
 					result[n].buffer_status
-					& MSM_NAND_BUF_STAT_NUM_ERR_MASK;
+					& chip->num_err_mask;
 				if (ecc_errors) {
 					total_ecc_errors += ecc_errors;
 					/* not thread safe */
@@ -7043,6 +7044,15 @@
 	pr_info("%s: allocated dma buffer at %p, dma_addr %x\n",
 		__func__, info->msm_nand.dma_buffer, info->msm_nand.dma_addr);
 
+	/* Let default be VERSION_1 for backward compatibility */
+	info->msm_nand.uncorrectable_bit_mask = BIT(3);
+	info->msm_nand.num_err_mask = 0x7;
+
+	if (plat_data && (plat_data->version == VERSION_2)) {
+		info->msm_nand.uncorrectable_bit_mask = BIT(8);
+		info->msm_nand.num_err_mask = 0x1F;
+	}
+
 	info->mtd.name = dev_name(&pdev->dev);
 	info->mtd.priv = &info->msm_nand;
 	info->mtd.owner = THIS_MODULE;
diff --git a/drivers/mtd/devices/msm_nand.h b/drivers/mtd/devices/msm_nand.h
index 2729c6b..8156b92 100644
--- a/drivers/mtd/devices/msm_nand.h
+++ b/drivers/mtd/devices/msm_nand.h
@@ -187,9 +187,6 @@
 #define EBI2_CFG_REG		       	EBI2_REG(0x0004)
 #define EBI2_NAND_ADM_MUX       	EBI2_REG(0x005C)
 
-#define MSM_NAND_BUF_STAT_UNCRCTBL_ERR	(1 << 8)
-#define MSM_NAND_BUF_STAT_NUM_ERR_MASK	(enable_bch_ecc ? 0x1F : 0x0F)
-
 extern struct flash_platform_data msm_nand_data;
 
 #endif