mtd: msm_nand: Fix wrong uncorrectable error bit check
For the Nand controller on 7x30 and 7x27a, the
uncorrectable error bit in the NANDC_BUFFER_STATUS
register is changed to BIT(8) from BIT(3) (in legacy
targets) due to change in the ECC requirements. Currently,
this is handled only in dual nandc mode (default for 7x30
and 7x27a). In case, if only single nandc is used, the
uncorrectable bit check is broken and the driver wouldn't
detect any ECC errors.
Add software version info in platform data to differentiate
between the targets that have different register interface.
CRs-Fixed: 365433
Change-Id: I3c33ccb0e936e262116dd20798d56530dbae900f
Signed-off-by: Sujit Reddy Thumma <sthumma@codeaurora.org>
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