mtd: rawnand: Ensure the nand chip supports cached reads
authorRouven Czerwinski <r.czerwinski@pengutronix.de>
Fri, 22 Sep 2023 14:17:16 +0000 (16:17 +0200)
committerMiquel Raynal <miquel.raynal@bootlin.com>
Mon, 16 Oct 2023 08:47:22 +0000 (10:47 +0200)
Both the JEDEC and ONFI specification say that read cache sequential
support is an optional command. This means that we not only need to
check whether the individual controller supports the command, we also
need to check the parameter pages for both ONFI and JEDEC NAND flashes
before enabling sequential cache reads.

This fixes support for NAND flashes which don't support enabling cache
reads, i.e. Samsung K9F4G08U0F or Toshiba TC58NVG0S3HTA00.

Sequential cache reads are now only available for ONFI and JEDEC
devices, if individual vendors implement this, it needs to be enabled
per vendor.

Tested on i.MX6Q with a Samsung NAND flash chip that doesn't support
sequential reads.

Fixes: 003fe4b9545b ("mtd: rawnand: Support for sequential cache reads")
Cc: stable@vger.kernel.org
Signed-off-by: Rouven Czerwinski <r.czerwinski@pengutronix.de>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20230922141717.35977-1-r.czerwinski@pengutronix.de
drivers/mtd/nand/raw/nand_base.c
drivers/mtd/nand/raw/nand_jedec.c
drivers/mtd/nand/raw/nand_onfi.c
include/linux/mtd/jedec.h
include/linux/mtd/onfi.h
include/linux/mtd/rawnand.h

index d4b55155aeae90e8d32917917b56026c758cb5de..1fcac403cee60f70348014f41d0cea32f6fcf5b3 100644 (file)
@@ -5110,6 +5110,9 @@ static void rawnand_check_cont_read_support(struct nand_chip *chip)
 {
        struct mtd_info *mtd = nand_to_mtd(chip);
 
+       if (!chip->parameters.supports_read_cache)
+               return;
+
        if (chip->read_retries)
                return;
 
index 836757717660b92612253c1e4244c80cbe35ba57..b3cc8f360529169cd65daf38faf4be1835036745 100644 (file)
@@ -94,6 +94,9 @@ int nand_jedec_detect(struct nand_chip *chip)
                goto free_jedec_param_page;
        }
 
+       if (p->opt_cmd[0] & JEDEC_OPT_CMD_READ_CACHE)
+               chip->parameters.supports_read_cache = true;
+
        memorg->pagesize = le32_to_cpu(p->byte_per_page);
        mtd->writesize = memorg->pagesize;
 
index f15ef90aec8cd6d76f3c4da5d078d1c5ddfd1fdc..861975e44b552db0acad7e299cf15af410070602 100644 (file)
@@ -303,6 +303,9 @@ int nand_onfi_detect(struct nand_chip *chip)
                           ONFI_FEATURE_ADDR_TIMING_MODE, 1);
        }
 
+       if (le16_to_cpu(p->opt_cmd) & ONFI_OPT_CMD_READ_CACHE)
+               chip->parameters.supports_read_cache = true;
+
        onfi = kzalloc(sizeof(*onfi), GFP_KERNEL);
        if (!onfi) {
                ret = -ENOMEM;
index 0b6b59f7cfbdcd46826b33a2c23f518ab1755f52..56047a4e54c9c21350ca2e0d74705e369acc0189 100644 (file)
@@ -21,6 +21,9 @@ struct jedec_ecc_info {
 /* JEDEC features */
 #define JEDEC_FEATURE_16_BIT_BUS       (1 << 0)
 
+/* JEDEC Optional Commands */
+#define JEDEC_OPT_CMD_READ_CACHE       BIT(1)
+
 struct nand_jedec_params {
        /* rev info and features block */
        /* 'J' 'E' 'S' 'D'  */
index a7376f9beddfd6de749f25583196548fda718f35..55ab2e4d62f9476c427bdf68412c0a3102d4bbe2 100644 (file)
@@ -55,6 +55,7 @@
 #define ONFI_SUBFEATURE_PARAM_LEN      4
 
 /* ONFI optional commands SET/GET FEATURES supported? */
+#define ONFI_OPT_CMD_READ_CACHE                BIT(1)
 #define ONFI_OPT_CMD_SET_GET_FEATURES  BIT(2)
 
 struct nand_onfi_params {
index 90a141ba2a5acc18eb347baeb31dd8dc52d24f19..c29ace15a053a69a13e2d97ef9f30debe3d3f830 100644 (file)
@@ -225,6 +225,7 @@ struct gpio_desc;
  * struct nand_parameters - NAND generic parameters from the parameter page
  * @model: Model name
  * @supports_set_get_features: The NAND chip supports setting/getting features
+ * @supports_read_cache: The NAND chip supports read cache operations
  * @set_feature_list: Bitmap of features that can be set
  * @get_feature_list: Bitmap of features that can be get
  * @onfi: ONFI specific parameters
@@ -233,6 +234,7 @@ struct nand_parameters {
        /* Generic parameters */
        const char *model;
        bool supports_set_get_features;
+       bool supports_read_cache;
        DECLARE_BITMAP(set_feature_list, ONFI_FEATURE_NUMBER);
        DECLARE_BITMAP(get_feature_list, ONFI_FEATURE_NUMBER);