[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20251031-winbond-v6-17-rc1-oddr-v1-15-be42de23ebf1@bootlin.com>
Date: Fri, 31 Oct 2025 18:26:59 +0100
From: Miquel Raynal <miquel.raynal@...tlin.com>
To: Mark Brown <broonie@...nel.org>, Richard Weinberger <richard@....at>,
Vignesh Raghavendra <vigneshr@...com>
Cc: Tudor Ambarus <tudor.ambarus@...aro.org>,
Pratyush Yadav <pratyush@...nel.org>,
Thomas Petazzoni <thomas.petazzoni@...tlin.com>,
Steam Lin <STLin2@...bond.com>, Santhosh Kumar K <s-k6@...com>,
linux-spi@...r.kernel.org, linux-kernel@...r.kernel.org,
linux-mtd@...ts.infradead.org, Miquel Raynal <miquel.raynal@...tlin.com>
Subject: [PATCH 15/28] mtd: spinand: List vendor specific operations and
make sure they are supported
It is probably safe to expect that all SPI controller drivers will ever
support all the most basic SPI NAND operations, such as write enable,
register reads, page program, block erases, etc. However, what about
vendor specific operations? So far nobody complained about it, but as we
are about to introduce octal DTR support, and as none of the SPI NAND
instruction set is defined in any standard, we must remain careful about
these extra operations.
One way to make sure we do not blindly get ourselves in strange
situations with vendor commands failing silently is to make the check
once for all, while probing the chip. However at this stage we have no
such list, so let's add the necessary infrastructure to allow:
- registering vendor operations,
- checking they are actually supported when appropriate.
Signed-off-by: Miquel Raynal <miquel.raynal@...tlin.com>
---
drivers/mtd/nand/spi/core.c | 26 ++++++++++++++++++++++++++
include/linux/mtd/spinand.h | 5 +++++
2 files changed, 31 insertions(+)
diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index d4f46a17f77e15ac0ab26397e88d37119636b003..7c01516c6b6acb41d2cc080d6fbaaa5ace661602 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -1338,6 +1338,27 @@ static void spinand_init_ssdr_templates(struct spinand_device *spinand)
spinand->op_templates = &spinand->ssdr_op_templates;
}
+static int spinand_support_vendor_ops(struct spinand_device *spinand,
+ const struct spinand_info *info)
+{
+ int i;
+
+ /*
+ * The vendor ops array is only used in order to verify this chip and all its memory
+ * operations are supported. If we see patterns emerging, we could ideally name these
+ * operations and define them at the SPI NAND core level instead.
+ * For now, this only serves as a sanity check.
+ */
+ for (i = 0; i < info->vendor_ops->nops; i++) {
+ const struct spi_mem_op *op = &info->vendor_ops->ops[i];
+
+ if (!spi_mem_supports_op(spinand->spimem, op))
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
static const struct spi_mem_op *
spinand_select_op_variant(struct spinand_device *spinand,
const struct spinand_op_variants *variants)
@@ -1407,6 +1428,7 @@ int spinand_match_and_init(struct spinand_device *spinand,
u8 *id = spinand->id.data;
struct nand_device *nand = spinand_to_nand(spinand);
unsigned int i;
+ int ret;
for (i = 0; i < table_size; i++) {
const struct spinand_info *info = &table[i];
@@ -1452,6 +1474,10 @@ int spinand_match_and_init(struct spinand_device *spinand,
spinand->ssdr_op_templates.update_cache = op;
+ ret = spinand_support_vendor_ops(spinand, info);
+ if (ret)
+ return ret;
+
return 0;
}
diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
index a8fd04a67cfa9925bd68c57539d86e0816b76274..0565cdeb3f7b652699d420a8c05c3fe53fcc2253 100644
--- a/include/linux/mtd/spinand.h
+++ b/include/linux/mtd/spinand.h
@@ -492,6 +492,7 @@ struct spinand_user_otp {
* @op_variants.read_cache: variants of the read-cache operation
* @op_variants.write_cache: variants of the write-cache operation
* @op_variants.update_cache: variants of the update-cache operation
+ * @vendor_ops: vendor specific operations
* @select_target: function used to select a target/die. Required only for
* multi-die chips
* @configure_chip: Align the chip configuration with the core settings
@@ -516,6 +517,7 @@ struct spinand_info {
const struct spinand_op_variants *write_cache;
const struct spinand_op_variants *update_cache;
} op_variants;
+ const struct spinand_op_variants *vendor_ops;
int (*select_target)(struct spinand_device *spinand,
unsigned int target);
int (*configure_chip)(struct spinand_device *spinand);
@@ -542,6 +544,9 @@ struct spinand_info {
.update_cache = __update, \
}
+#define SPINAND_INFO_VENDOR_OPS(__ops) \
+ .vendor_ops = __ops
+
#define SPINAND_ECCINFO(__ooblayout, __get_status) \
.eccinfo = { \
.ooblayout = __ooblayout, \
--
2.51.0
Powered by blists - more mailing lists