summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorMiquel Raynal <miquel.raynal@bootlin.com>2026-01-09 18:18:12 +0100
committerMiquel Raynal <miquel.raynal@bootlin.com>2026-01-29 20:21:41 +0100
commitfbc7538782f8e7df4737dcec7d854cf4d53bfc67 (patch)
treefe6dac88264cedc5b6904561d9b4b81cd4f722d8 /drivers
parent6ec7ace0127077d1caab6ca1fb0129da8eb5c1de (diff)
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@bootlin.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/nand/spi/core.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 7146eec51afa..cdf45d054082 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -1424,6 +1424,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)
@@ -1490,6 +1511,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];
@@ -1535,6 +1557,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;
}