This driver was originally written for the Intel MRST platform with
several platform specific parameters hard-coded.  Another thing we
need to fix is the hard-coded ECC step size.  Currently, it is
defined as follows:

  #define ECC_SECTOR_SIZE 512

(somehow, it is defined in both denali.c and denali.h)

This must be avoided because the Denali IP supports 1024 byte ECC
size as well.  Add a new flag DENALI_CAPS_ECC_SIZE_1024. If it is
specified, ecc.size is set to 1024, otherwise set to 512.

We can use "nand-ecc-step-size" DT property to override the ecc.size
if we want, but this capability flag can provide the reasonable
default because it is associated with the DT compatible strings.

Signed-off-by: Masahiro Yamada <yamada.masah...@socionext.com>
---

 .../devicetree/bindings/mtd/denali-nand.txt        |  4 ++++
 drivers/mtd/nand/denali.c                          | 26 +++++++++++-----------
 drivers/mtd/nand/denali.h                          |  3 +--
 3 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/Documentation/devicetree/bindings/mtd/denali-nand.txt 
b/Documentation/devicetree/bindings/mtd/denali-nand.txt
index 603110b..e9d5818 100644
--- a/Documentation/devicetree/bindings/mtd/denali-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/denali-nand.txt
@@ -6,6 +6,10 @@ Required properties:
   - reg-names: Should contain the reg names "nand_data" and "denali_reg"
   - interrupts : The interrupt number.
 
+Optional properties:
+  - nand-ecc-step-size: must be 512 or 1024.  If not specified, default to 512.
+    see nand.txt for details.
+
 The device tree may optionally contain sub-nodes describing partitions of the
 address space. See partition.txt for more detail.
 
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 63f7500..5d80f16 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -894,8 +894,6 @@ static bool denali_hw_ecc_fixup(struct denali_nand_info 
*denali,
        return false;
 }
 
-#define ECC_SECTOR_SIZE 512
-
 #define ECC_SECTOR(x)  (((x) & ECC_ERROR_ADDRESS__SECTOR_NR) >> 12)
 #define ECC_BYTE(x)    (((x) & ECC_ERROR_ADDRESS__OFFSET))
 #define ECC_CORRECTION_VALUE(x) ((x) & ERR_CORRECTION_INFO__BYTEMASK)
@@ -908,6 +906,7 @@ static bool denali_sw_ecc_fixup(struct denali_nand_info 
*denali, u8 *buf,
 {
        bool check_erased_page = false;
        unsigned int bitflips = 0;
+       unsigned int ecc_size = denali->nand.ecc.size;
        u32 err_address, err_correction_info, err_byte, err_sector, err_device,
            err_correction_value;
 
@@ -930,18 +929,18 @@ static bool denali_sw_ecc_fixup(struct denali_nand_info 
*denali, u8 *buf,
 
                if (ECC_ERROR_CORRECTABLE(err_correction_info)) {
                        /*
-                        * If err_byte is larger than ECC_SECTOR_SIZE, means 
error
+                        * If err_byte is larger than ecc_size, means error
                         * happened in OOB, so we ignore it. It's no need for
                         * us to correct it err_device is represented the NAND
                         * error bits are happened in if there are more than
                         * one NAND connected.
                         */
-                       if (err_byte < ECC_SECTOR_SIZE) {
+                       if (err_byte < ecc_size) {
                                struct mtd_info *mtd =
                                        nand_to_mtd(&denali->nand);
                                int offset;
 
-                               offset = (err_sector * ECC_SECTOR_SIZE + 
err_byte) *
+                               offset = (err_sector * ecc_size + err_byte) *
                                        denali->devnum + err_device;
                                /* correct the ECC error */
                                buf[offset] ^= err_correction_value;
@@ -1590,22 +1589,25 @@ int denali_init(struct denali_nand_info *denali)
        /* no subpage writes on denali */
        chip->options |= NAND_NO_SUBPAGE_WRITE;
 
+       /* If "nand-ecc-step-size" DT property is specified, respect it */
+       if (!chip->ecc.size)
+               chip->ecc.size = denali->caps & DENALI_CAPS_ECC_SIZE_1024 ?
+                                                               1024 : 512;
+
        /*
         * Denali Controller only support 15bit and 8bit ECC in MRST,
         * so just let controller do 15bit ECC for MLC and 8bit ECC for
         * SLC if possible.
         * */
        if (!nand_is_slc(chip) &&
-                       (mtd->oobsize > (denali->bbtskipbytes +
-                       ECC_15BITS * (mtd->writesize /
-                       ECC_SECTOR_SIZE)))) {
+                       mtd->oobsize > denali->bbtskipbytes +
+                       ECC_15BITS * (mtd->writesize / chip->ecc.size)) {
                /* if MLC OOB size is large enough, use 15bit ECC*/
                chip->ecc.strength = 15;
                chip->ecc.bytes = ECC_15BITS;
                iowrite32(15, denali->flash_reg + ECC_CORRECTION);
-       } else if (mtd->oobsize < (denali->bbtskipbytes +
-                       ECC_8BITS * (mtd->writesize /
-                       ECC_SECTOR_SIZE))) {
+       } else if (mtd->oobsize <
+                  denali->bbtskipbytes + ECC_8BITS * (mtd->writesize / 
chip->ecc.size)) {
                pr_err("Your NAND chip OOB is not large enough to contain 8bit 
ECC correction codes");
                goto failed_req_irq;
        } else {
@@ -1616,8 +1618,6 @@ int denali_init(struct denali_nand_info *denali)
 
        mtd_set_ooblayout(mtd, &denali_ooblayout_ops);
 
-       /* override the default read operations */
-       chip->ecc.size = ECC_SECTOR_SIZE;
        chip->ecc.read_page = denali_read_page;
        chip->ecc.read_page_raw = denali_read_page_raw;
        chip->ecc.write_page = denali_write_page;
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index d621b74..5209625 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -396,8 +396,6 @@
 #define MODE_10    0x08000000
 #define MODE_11    0x0C000000
 
-#define ECC_SECTOR_SIZE     512
-
 struct nand_buf {
        int head;
        int tail;
@@ -434,6 +432,7 @@ struct denali_nand_info {
 #define DENALI_CAPS_HW_ECC_FIXUP               BIT(0)
 #define DENALI_CAPS_DMA_64BIT                  BIT(1)
 #define DENALI_CAPS_NEW_N_BANKS_FORMAT         BIT(2)
+#define DENALI_CAPS_ECC_SIZE_1024              BIT(3)
 };
 
 extern int denali_init(struct denali_nand_info *denali);
-- 
2.7.4

Reply via email to