Skip to content

Commit fbc7538

Browse files
committed
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>
1 parent 6ec7ace commit fbc7538

2 files changed

Lines changed: 31 additions & 0 deletions

File tree

drivers/mtd/nand/spi/core.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1424,6 +1424,27 @@ static void spinand_init_ssdr_templates(struct spinand_device *spinand)
14241424
spinand->op_templates = &spinand->ssdr_op_templates;
14251425
}
14261426

1427+
static int spinand_support_vendor_ops(struct spinand_device *spinand,
1428+
const struct spinand_info *info)
1429+
{
1430+
int i;
1431+
1432+
/*
1433+
* The vendor ops array is only used in order to verify this chip and all its memory
1434+
* operations are supported. If we see patterns emerging, we could ideally name these
1435+
* operations and define them at the SPI NAND core level instead.
1436+
* For now, this only serves as a sanity check.
1437+
*/
1438+
for (i = 0; i < info->vendor_ops->nops; i++) {
1439+
const struct spi_mem_op *op = &info->vendor_ops->ops[i];
1440+
1441+
if (!spi_mem_supports_op(spinand->spimem, op))
1442+
return -EOPNOTSUPP;
1443+
}
1444+
1445+
return 0;
1446+
}
1447+
14271448
static const struct spi_mem_op *
14281449
spinand_select_op_variant(struct spinand_device *spinand,
14291450
const struct spinand_op_variants *variants)
@@ -1490,6 +1511,7 @@ int spinand_match_and_init(struct spinand_device *spinand,
14901511
u8 *id = spinand->id.data;
14911512
struct nand_device *nand = spinand_to_nand(spinand);
14921513
unsigned int i;
1514+
int ret;
14931515

14941516
for (i = 0; i < table_size; i++) {
14951517
const struct spinand_info *info = &table[i];
@@ -1535,6 +1557,10 @@ int spinand_match_and_init(struct spinand_device *spinand,
15351557

15361558
spinand->ssdr_op_templates.update_cache = op;
15371559

1560+
ret = spinand_support_vendor_ops(spinand, info);
1561+
if (ret)
1562+
return ret;
1563+
15381564
return 0;
15391565
}
15401566

include/linux/mtd/spinand.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,7 @@ struct spinand_user_otp {
494494
* @op_variants.read_cache: variants of the read-cache operation
495495
* @op_variants.write_cache: variants of the write-cache operation
496496
* @op_variants.update_cache: variants of the update-cache operation
497+
* @vendor_ops: vendor specific operations
497498
* @select_target: function used to select a target/die. Required only for
498499
* multi-die chips
499500
* @configure_chip: Align the chip configuration with the core settings
@@ -518,6 +519,7 @@ struct spinand_info {
518519
const struct spinand_op_variants *write_cache;
519520
const struct spinand_op_variants *update_cache;
520521
} op_variants;
522+
const struct spinand_op_variants *vendor_ops;
521523
int (*select_target)(struct spinand_device *spinand,
522524
unsigned int target);
523525
int (*configure_chip)(struct spinand_device *spinand);
@@ -544,6 +546,9 @@ struct spinand_info {
544546
.update_cache = __update, \
545547
}
546548

549+
#define SPINAND_INFO_VENDOR_OPS(__ops) \
550+
.vendor_ops = __ops
551+
547552
#define SPINAND_ECCINFO(__ooblayout, __get_status) \
548553
.eccinfo = { \
549554
.ooblayout = __ooblayout, \

0 commit comments

Comments
 (0)