Add ctrl_ops_variants, which can be used by the manufacturers' codes to define their SPI control operation variants. Add a macro to easily define ctrl_ops_varinats. This can be used to list out all the supported ctrl ops with their respective protocols by the vendors. Add spinand_select_ctrl_ops_variant() helper function to search for a supported ctrl_ops variant with the required SPI protocol in a given list of variants. Signed-off-by: Apurva Nandan <a-nandan@xxxxxx> --- drivers/mtd/nand/spi/core.c | 36 ++++++++++++++++++++++++++++++++++++ include/linux/mtd/spinand.h | 17 +++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index 30e90527ee3c..9688fdfc174e 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -1031,6 +1031,42 @@ spinand_select_data_op_variant(struct spinand_device *spinand, return NULL; } +static const struct spinand_ctrl_ops * +spinand_select_ctrl_ops_variant(struct spinand_device *spinand, + const struct spinand_ctrl_ops_variants *variants, + const enum spinand_protocol protocol) +{ + unsigned int i; + + for (i = 0; i < variants->nvariants; i++) { + const struct spinand_ctrl_ops *ctrl_ops = + &variants->ctrl_ops_list[i]; + + if (ctrl_ops->protocol != protocol) + continue; + + if (!spi_mem_supports_op(spinand->spimem, + &ctrl_ops->ops.reset) || + !spi_mem_supports_op(spinand->spimem, + &ctrl_ops->ops.get_feature) || + !spi_mem_supports_op(spinand->spimem, + &ctrl_ops->ops.set_feature) || + !spi_mem_supports_op(spinand->spimem, + &ctrl_ops->ops.write_enable) || + !spi_mem_supports_op(spinand->spimem, + &ctrl_ops->ops.block_erase) || + !spi_mem_supports_op(spinand->spimem, + &ctrl_ops->ops.page_read) || + !spi_mem_supports_op(spinand->spimem, + &ctrl_ops->ops.program_execute)) + continue; + + return ctrl_ops; + } + + return NULL; +} + /** * spinand_match_and_init() - Try to find a match between a device ID and an * entry in a spinand_info table diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index e5df6220ec1e..5dae0649f2fb 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -385,6 +385,18 @@ struct spinand_ctrl_ops { .protocol = __protocol, \ } +struct spinand_ctrl_ops_variants { + const struct spinand_ctrl_ops *ctrl_ops_list; + unsigned int nvariants; +}; + +#define SPINAND_CTRL_OPS_VARIANTS(name, ...) \ + const struct spinand_ctrl_ops_variants name = { \ + .ctrl_ops_list = (struct spinand_ctrl_ops[]){ __VA_ARGS__ }, \ + .nvariants = sizeof((struct spinand_ctrl_ops[]){ __VA_ARGS__ })/\ + sizeof(struct spinand_ctrl_ops), \ + } + /** * spinand_ecc_info - description of the on-die ECC implemented by a SPI NAND * chip @@ -442,6 +454,8 @@ struct spinand_info { const struct spinand_op_variants *write_cache; const struct spinand_op_variants *update_cache; } data_ops_variants; + + const struct spinand_ctrl_ops_variants *ctrl_ops_variants; int (*select_target)(struct spinand_device *spinand, unsigned int target); }; @@ -460,6 +474,9 @@ struct spinand_info { .update_cache = __update, \ } +#define SPINAND_INFO_CTRL_OPS_VARIANTS(__ctrl_ops_variants) \ + .ctrl_ops_variants = __ctrl_ops_variants + #define SPINAND_ECCINFO(__ooblayout, __get_status) \ .eccinfo = { \ .ooblayout = __ooblayout, \ -- 2.25.1