lkml.org 
[lkml]   [2019]   [May]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2] mtd: rawnand: Add Macronix NAND read retry support
    Date
    Add support for Macronix NAND read retry.

    Macronix NANDs support specific read operation for data recovery,
    which can be enabled/disabled with a SET/GET_FEATURE.
    Driver checks byte 167 of Vendor Blocks in ONFI parameter page table
    to see if this high-reliability function is supported.

    Signed-off-by: Mason Yang <masonccyang@mxic.com.tw>
    ---
    drivers/mtd/nand/raw/nand_macronix.c | 57 ++++++++++++++++++++++++++++++++++++
    1 file changed, 57 insertions(+)

    diff --git a/drivers/mtd/nand/raw/nand_macronix.c b/drivers/mtd/nand/raw/nand_macronix.c
    index e287e71..1a4dc92 100644
    --- a/drivers/mtd/nand/raw/nand_macronix.c
    +++ b/drivers/mtd/nand/raw/nand_macronix.c
    @@ -17,6 +17,62 @@

    #include "internals.h"

    +#define MACRONIX_READ_RETRY_BIT BIT(0)
    +#define MACRONIX_READ_RETRY_MODE 6
    +
    +struct nand_onfi_vendor_macronix {
    + u8 reserved[1];
    + u8 reliability_func;
    +} __packed;
    +
    +/*
    + * Macronix NANDs support using SET/GET_FEATURES to enter/exit read retry mode
    + */
    +static int macronix_nand_setup_read_retry(struct nand_chip *chip, int mode)
    +{
    + u8 feature[ONFI_SUBFEATURE_PARAM_LEN];
    + int ret, feature_addr = ONFI_FEATURE_ADDR_READ_RETRY;
    +
    + if (chip->parameters.supports_set_get_features &&
    + test_bit(feature_addr, chip->parameters.set_feature_list) &&
    + test_bit(feature_addr, chip->parameters.get_feature_list)) {
    + feature[0] = mode;
    + ret = nand_set_features(chip, feature_addr, feature);
    + if (ret)
    + pr_err("Failed to set read retry moded:%d\n", mode);
    +
    + ret = nand_get_features(chip, feature_addr, feature);
    + if (ret || feature[0] != mode)
    + pr_err("Failed to verify read retry moded:%d(%d)\n",
    + mode, feature[0]);
    + }
    +
    + return ret;
    +}
    +
    +static void macronix_nand_onfi_init(struct nand_chip *chip)
    +{
    + struct nand_parameters *p = &chip->parameters;
    + struct nand_onfi_vendor_macronix *mxic;
    +
    + if (!p->onfi)
    + return;
    +
    + mxic = (struct nand_onfi_vendor_macronix *)p->onfi->vendor;
    + if ((mxic->reliability_func & MACRONIX_READ_RETRY_BIT) == 0)
    + return;
    +
    + chip->read_retries = MACRONIX_READ_RETRY_MODE;
    + chip->setup_read_retry = macronix_nand_setup_read_retry;
    +
    + if (p->supports_set_get_features) {
    + bitmap_set(p->set_feature_list,
    + ONFI_FEATURE_ADDR_READ_RETRY, 1);
    + bitmap_set(p->get_feature_list,
    + ONFI_FEATURE_ADDR_READ_RETRY, 1);
    + }
    +}
    +
    /*
    * Macronix AC series does not support using SET/GET_FEATURES to change
    * the timings unlike what is declared in the parameter page. Unflag
    @@ -65,6 +121,7 @@ static int macronix_nand_init(struct nand_chip *chip)
    chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;

    macronix_nand_fix_broken_get_timings(chip);
    + macronix_nand_onfi_init(chip);

    return 0;
    }
    --
    1.9.1
    \
     
     \ /
      Last update: 2019-05-17 08:32    [W:5.537 / U:0.124 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site