[PATCH RFC v3 3/4] nand: pl353: Add ONDIE ECC support

2014-06-26 Thread Punnaiah Choudary Kalluri
Added ONDIE ECC support. Currently this ecc mode is supported for
specific micron parts with oob size 64 bytes.

Signed-off-by: Punnaiah Choudary Kalluri 
---
 drivers/mtd/nand/pl353_nand.c |  131 +++-
 1 files changed, 127 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/pl353_nand.c b/drivers/mtd/nand/pl353_nand.c
index eca205f..4f56c7f 100644
--- a/drivers/mtd/nand/pl353_nand.c
+++ b/drivers/mtd/nand/pl353_nand.c
@@ -140,6 +140,48 @@ static struct nand_ecclayout nand_oob_64 = {
 .length = 50} }
 };
 
+static struct nand_ecclayout ondie_nand_oob_64 = {
+   .eccbytes = 32,
+
+   .eccpos = {
+   8, 9, 10, 11, 12, 13, 14, 15,
+   24, 25, 26, 27, 28, 29, 30, 31,
+   40, 41, 42, 43, 44, 45, 46, 47,
+   56, 57, 58, 59, 60, 61, 62, 63
+   },
+
+   .oobfree = {
+   { .offset = 4, .length = 4 },
+   { .offset = 20, .length = 4 },
+   { .offset = 36, .length = 4 },
+   { .offset = 52, .length = 4 }
+   }
+};
+
+/* Generic flash bbt decriptors */
+static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
+static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
+
+static struct nand_bbt_descr bbt_main_descr = {
+   .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+   | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+   .offs = 4,
+   .len = 4,
+   .veroffs = 20,
+   .maxblocks = 4,
+   .pattern = bbt_pattern
+};
+
+static struct nand_bbt_descr bbt_mirror_descr = {
+   .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+   | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+   .offs = 4,
+   .len = 4,
+   .veroffs = 20,
+   .maxblocks = 4,
+   .pattern = mirror_pattern
+};
+
 /**
  * pl353_nand_calculate_hwecc - Calculate Hardware ECC
  * @mtd:   Pointer to the mtd_info structure
@@ -816,15 +858,74 @@ static int pl353_nand_device_ready(struct mtd_info *mtd)
 }
 
 /**
+ * pl353_nand_detect_ondie_ecc - Get the flash ondie ecc state
+ * @mtd:   Pointer to the mtd_info structure
+ *
+ * This function enables the ondie ecc for the Micron ondie ecc capable devices
+ *
+ * Return: 1 on detect, 0 if fail to detect
+ */
+static int pl353_nand_detect_ondie_ecc(struct mtd_info *mtd)
+{
+   struct nand_chip *nand_chip = mtd->priv;
+   u8 maf_id, dev_id, i, get_feature;
+   u8 set_feature[4] = { 0x08, 0x00, 0x00, 0x00 };
+
+   /* Check if On-Die ECC flash */
+   nand_chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+   nand_chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
+
+   /* Read manufacturer and device IDs */
+   maf_id = readb(nand_chip->IO_ADDR_R);
+   dev_id = readb(nand_chip->IO_ADDR_R);
+
+   if ((maf_id == NAND_MFR_MICRON) &&
+   ((dev_id == 0xf1) || (dev_id == 0xa1) ||
+(dev_id == 0xb1) || (dev_id == 0xaa) ||
+(dev_id == 0xba) || (dev_id == 0xda) ||
+(dev_id == 0xca) || (dev_id == 0xac) ||
+(dev_id == 0xbc) || (dev_id == 0xdc) ||
+(dev_id == 0xcc) || (dev_id == 0xa3) ||
+(dev_id == 0xb3) ||
+(dev_id == 0xd3) || (dev_id == 0xc3))) {
+
+   nand_chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES,
+  ONDIE_ECC_FEATURE_ADDR, -1);
+   get_feature = readb(nand_chip->IO_ADDR_R);
+
+   if (get_feature & 0x08) {
+   return 1;
+   } else {
+   nand_chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES,
+  ONDIE_ECC_FEATURE_ADDR, -1);
+   for (i = 0; i < 4; i++)
+   writeb(set_feature[i], nand_chip->IO_ADDR_W);
+
+   ndelay(1000);
+
+   nand_chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES,
+  ONDIE_ECC_FEATURE_ADDR, -1);
+   get_feature = readb(nand_chip->IO_ADDR_R);
+
+   if (get_feature & 0x08)
+   return 1;
+   }
+   }
+
+   return 0;
+}
+
+/**
  * pl353_nand_ecc_init - Initialize the ecc information as per the ecc mode
  * @mtd:   Pointer to the mtd_info structure
+ * @ondie_ecc_state:   ondie ecc status
  *
  * This function initializes the ecc block and functional pointers as per the
  * ecc mode
  *
  * Return: Zero on success and error on failure.
  */
-static int pl353_nand_ecc_init(struct mtd_info *mtd)
+static int pl353_nand_ecc_init(struct mtd_info *mtd, int ondie_ecc_state)
 {
struct nand_chip *nand_chip = mtd->priv;
struct pl353_nand_info *xnand =
@@ -838,12 +939,28 @@ static int pl353_nand_ecc_init(struct mtd_info *mtd)
 
switch (xnand->ecc_mode) {
case NAND_ECC_HW:
-   if (mtd->writesize > 2048) {
+   

[PATCH RFC v3 3/4] nand: pl353: Add ONDIE ECC support

2014-06-26 Thread Punnaiah Choudary Kalluri
Added ONDIE ECC support. Currently this ecc mode is supported for
specific micron parts with oob size 64 bytes.

Signed-off-by: Punnaiah Choudary Kalluri punn...@xilinx.com
---
 drivers/mtd/nand/pl353_nand.c |  131 +++-
 1 files changed, 127 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/pl353_nand.c b/drivers/mtd/nand/pl353_nand.c
index eca205f..4f56c7f 100644
--- a/drivers/mtd/nand/pl353_nand.c
+++ b/drivers/mtd/nand/pl353_nand.c
@@ -140,6 +140,48 @@ static struct nand_ecclayout nand_oob_64 = {
 .length = 50} }
 };
 
+static struct nand_ecclayout ondie_nand_oob_64 = {
+   .eccbytes = 32,
+
+   .eccpos = {
+   8, 9, 10, 11, 12, 13, 14, 15,
+   24, 25, 26, 27, 28, 29, 30, 31,
+   40, 41, 42, 43, 44, 45, 46, 47,
+   56, 57, 58, 59, 60, 61, 62, 63
+   },
+
+   .oobfree = {
+   { .offset = 4, .length = 4 },
+   { .offset = 20, .length = 4 },
+   { .offset = 36, .length = 4 },
+   { .offset = 52, .length = 4 }
+   }
+};
+
+/* Generic flash bbt decriptors */
+static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
+static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
+
+static struct nand_bbt_descr bbt_main_descr = {
+   .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+   | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+   .offs = 4,
+   .len = 4,
+   .veroffs = 20,
+   .maxblocks = 4,
+   .pattern = bbt_pattern
+};
+
+static struct nand_bbt_descr bbt_mirror_descr = {
+   .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+   | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+   .offs = 4,
+   .len = 4,
+   .veroffs = 20,
+   .maxblocks = 4,
+   .pattern = mirror_pattern
+};
+
 /**
  * pl353_nand_calculate_hwecc - Calculate Hardware ECC
  * @mtd:   Pointer to the mtd_info structure
@@ -816,15 +858,74 @@ static int pl353_nand_device_ready(struct mtd_info *mtd)
 }
 
 /**
+ * pl353_nand_detect_ondie_ecc - Get the flash ondie ecc state
+ * @mtd:   Pointer to the mtd_info structure
+ *
+ * This function enables the ondie ecc for the Micron ondie ecc capable devices
+ *
+ * Return: 1 on detect, 0 if fail to detect
+ */
+static int pl353_nand_detect_ondie_ecc(struct mtd_info *mtd)
+{
+   struct nand_chip *nand_chip = mtd-priv;
+   u8 maf_id, dev_id, i, get_feature;
+   u8 set_feature[4] = { 0x08, 0x00, 0x00, 0x00 };
+
+   /* Check if On-Die ECC flash */
+   nand_chip-cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+   nand_chip-cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
+
+   /* Read manufacturer and device IDs */
+   maf_id = readb(nand_chip-IO_ADDR_R);
+   dev_id = readb(nand_chip-IO_ADDR_R);
+
+   if ((maf_id == NAND_MFR_MICRON) 
+   ((dev_id == 0xf1) || (dev_id == 0xa1) ||
+(dev_id == 0xb1) || (dev_id == 0xaa) ||
+(dev_id == 0xba) || (dev_id == 0xda) ||
+(dev_id == 0xca) || (dev_id == 0xac) ||
+(dev_id == 0xbc) || (dev_id == 0xdc) ||
+(dev_id == 0xcc) || (dev_id == 0xa3) ||
+(dev_id == 0xb3) ||
+(dev_id == 0xd3) || (dev_id == 0xc3))) {
+
+   nand_chip-cmdfunc(mtd, NAND_CMD_GET_FEATURES,
+  ONDIE_ECC_FEATURE_ADDR, -1);
+   get_feature = readb(nand_chip-IO_ADDR_R);
+
+   if (get_feature  0x08) {
+   return 1;
+   } else {
+   nand_chip-cmdfunc(mtd, NAND_CMD_SET_FEATURES,
+  ONDIE_ECC_FEATURE_ADDR, -1);
+   for (i = 0; i  4; i++)
+   writeb(set_feature[i], nand_chip-IO_ADDR_W);
+
+   ndelay(1000);
+
+   nand_chip-cmdfunc(mtd, NAND_CMD_GET_FEATURES,
+  ONDIE_ECC_FEATURE_ADDR, -1);
+   get_feature = readb(nand_chip-IO_ADDR_R);
+
+   if (get_feature  0x08)
+   return 1;
+   }
+   }
+
+   return 0;
+}
+
+/**
  * pl353_nand_ecc_init - Initialize the ecc information as per the ecc mode
  * @mtd:   Pointer to the mtd_info structure
+ * @ondie_ecc_state:   ondie ecc status
  *
  * This function initializes the ecc block and functional pointers as per the
  * ecc mode
  *
  * Return: Zero on success and error on failure.
  */
-static int pl353_nand_ecc_init(struct mtd_info *mtd)
+static int pl353_nand_ecc_init(struct mtd_info *mtd, int ondie_ecc_state)
 {
struct nand_chip *nand_chip = mtd-priv;
struct pl353_nand_info *xnand =
@@ -838,12 +939,28 @@ static int pl353_nand_ecc_init(struct mtd_info *mtd)
 
switch (xnand-ecc_mode) {
case NAND_ECC_HW:
-   if (mtd-writesize  2048) {
+