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)
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];
spinand->ssdr_op_templates.update_cache = op;
+ ret = spinand_support_vendor_ops(spinand, info);
+ if (ret)
+ return ret;
+
return 0;
}
* @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
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);
.update_cache = __update, \
}
+#define SPINAND_INFO_VENDOR_OPS(__ops) \
+ .vendor_ops = __ops
+
#define SPINAND_ECCINFO(__ooblayout, __get_status) \
.eccinfo = { \
.ooblayout = __ooblayout, \