lkml.org 
[lkml]   [2016]   [Nov]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 33/39] mtd: nand: denali: support 1024 byte ECC step size
    Date
    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.masahiro@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
    \
     
     \ /
      Last update: 2016-11-26 19:11    [W:2.218 / U:0.048 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site