]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
mtd: rawnand: Support enabling NV-DDR through SET_FEATURES
authorMiquel Raynal <miquel.raynal@bootlin.com>
Wed, 5 May 2021 21:37:44 +0000 (23:37 +0200)
committerMiquel Raynal <miquel.raynal@bootlin.com>
Wed, 26 May 2021 08:51:00 +0000 (10:51 +0200)
Until now the parameter of the ADDR_TIMING_MODE feature was just the
ONFI timing mode (from 0 to 5) because we were only supporting the SDR
data interface. In the same byte, bits 4 and 5 indicate which data
interface is being configured so use them to set the right mode and also
read them back to ensure the right timing has been setup on the chip's
side.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20210505213750.257417-17-miquel.raynal@bootlin.com
drivers/mtd/nand/raw/nand_base.c
include/linux/mtd/onfi.h

index b8a515a74379f08b1e2439c7d2d5cb1a53c55853..cfe8257bf17519ea830f90773f0d8dfc0bea307d 100644 (file)
@@ -832,7 +832,7 @@ static int nand_reset_interface(struct nand_chip *chip, int chipnr)
 static int nand_setup_interface(struct nand_chip *chip, int chipnr)
 {
        const struct nand_controller_ops *ops = chip->controller->ops;
-       u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = { };
+       u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = { }, request;
        int ret;
 
        if (!nand_controller_can_setup_interface(chip))
@@ -848,7 +848,12 @@ static int nand_setup_interface(struct nand_chip *chip, int chipnr)
        if (!chip->best_interface_config)
                return 0;
 
-       tmode_param[0] = chip->best_interface_config->timings.mode;
+       request = chip->best_interface_config->timings.mode;
+       if (nand_interface_is_sdr(chip->best_interface_config))
+               request |= ONFI_DATA_INTERFACE_SDR;
+       else
+               request |= ONFI_DATA_INTERFACE_NVDDR;
+       tmode_param[0] = request;
 
        /* Change the mode on the chip side (if supported by the NAND chip) */
        if (nand_supports_set_features(chip, ONFI_FEATURE_ADDR_TIMING_MODE)) {
@@ -877,10 +882,13 @@ static int nand_setup_interface(struct nand_chip *chip, int chipnr)
        if (ret)
                goto err_reset_chip;
 
-       if (tmode_param[0] != chip->best_interface_config->timings.mode) {
-               pr_warn("timing mode %d not acknowledged by the NAND chip\n",
+       if (request != tmode_param[0]) {
+               pr_warn("%s timing mode %d not acknowledged by the NAND chip\n",
+                       nand_interface_is_nvddr(chip->best_interface_config) ? "NV-DDR" : "SDR",
                        chip->best_interface_config->timings.mode);
-               ret = 0;
+               pr_debug("NAND chip would work in %s timing mode %d\n",
+                        tmode_param[0] & ONFI_DATA_INTERFACE_NVDDR ? "NV-DDR" : "SDR",
+                        (unsigned int)ONFI_TIMING_MODE_PARAM(tmode_param[0]));
                goto err_reset_chip;
        }
 
index a9677bf1e47e1cf61e0b856af279abd8db637262..a7376f9beddfd6de749f25583196548fda718f35 100644 (file)
@@ -11,6 +11,7 @@
 #define __LINUX_MTD_ONFI_H
 
 #include <linux/types.h>
+#include <linux/bitfield.h>
 
 /* ONFI version bits */
 #define ONFI_VERSION_1_0               BIT(1)
@@ -29,6 +30,9 @@
 #define ONFI_FEATURE_EXT_PARAM_PAGE    BIT(7)
 
 /* ONFI timing mode, used in both asynchronous and synchronous mode */
+#define ONFI_DATA_INTERFACE_SDR                0
+#define ONFI_DATA_INTERFACE_NVDDR      BIT(4)
+#define ONFI_DATA_INTERFACE_NVDDR2     BIT(5)
 #define ONFI_TIMING_MODE_0             BIT(0)
 #define ONFI_TIMING_MODE_1             BIT(1)
 #define ONFI_TIMING_MODE_2             BIT(2)
@@ -36,6 +40,7 @@
 #define ONFI_TIMING_MODE_4             BIT(4)
 #define ONFI_TIMING_MODE_5             BIT(5)
 #define ONFI_TIMING_MODE_UNKNOWN       BIT(6)
+#define ONFI_TIMING_MODE_PARAM(x)      FIELD_GET(GENMASK(3, 0), (x))
 
 /* ONFI feature number/address */
 #define ONFI_FEATURE_NUMBER            256