[RFC PATCH v2 02/12] spi: spi-mem: add controller tuning support
Santhosh Kumar K
s-k6 at ti.com
Tue Jan 13 06:16:07 PST 2026
High-speed SPI memory controllers often require timing calibration
to operate reliably at maximum frequencies. Parameters such as
sampling points and delays need to be tuned based on the specific
hardware configuration and operating conditions.
Add spi_mem_execute_tuning() to allow SPI memory drivers to request
controller-specific tuning. The function takes a mandatory read
operation template and an optional write template, as most tuning
procedures are based on read operations and calls the corresponding
execute_tuning callback to spi_controller_mem_ops to allow controller
drivers to implement their tuning procedures.
Signed-off-by: Santhosh Kumar K <s-k6 at ti.com>
---
drivers/spi/spi-mem.c | 34 ++++++++++++++++++++++++++++++++++
include/linux/spi/spi-mem.h | 5 +++++
2 files changed, 39 insertions(+)
diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
index c8b2add2640e..2d34469323ea 100644
--- a/drivers/spi/spi-mem.c
+++ b/drivers/spi/spi-mem.c
@@ -633,6 +633,40 @@ u64 spi_mem_calc_op_duration(struct spi_mem *mem, struct spi_mem_op *op)
}
EXPORT_SYMBOL_GPL(spi_mem_calc_op_duration);
+/**
+ * spi_mem_execute_tuning() - Execute controller tuning procedure
+ * @mem: the SPI memory device
+ * @read_op: read operation template (mandatory)
+ * @write_op: write operation template (optional, may be NULL)
+ *
+ * Requests the controller to perform tuning to optimize timing parameters
+ * for high-speed operation. Controllers use the provided operation templates
+ * to construct their tuning sequences.
+ *
+ * Return: 0 on success, -EINVAL if @mem or @read_op is NULL,
+ * -EOPNOTSUPP if controller doesn't support tuning,
+ * or a controller-specific error code on failure.
+ */
+int spi_mem_execute_tuning(struct spi_mem *mem, struct spi_mem_op *read_op,
+ struct spi_mem_op *write_op)
+{
+ struct spi_controller *ctlr;
+
+ if (!mem || !read_op)
+ return -EINVAL;
+
+ ctlr = mem->spi->controller;
+ if (!ctlr->mem_ops || !ctlr->mem_ops->execute_tuning)
+ return -EOPNOTSUPP;
+
+ spi_mem_adjust_op_freq(mem, read_op);
+ if (write_op)
+ spi_mem_adjust_op_freq(mem, write_op);
+
+ return ctlr->mem_ops->execute_tuning(mem, read_op, write_op);
+}
+EXPORT_SYMBOL_GPL(spi_mem_execute_tuning);
+
static ssize_t spi_mem_no_dirmap_read(struct spi_mem_dirmap_desc *desc,
u64 offs, size_t len, void *buf)
{
diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h
index 82390712794c..871e46297517 100644
--- a/include/linux/spi/spi-mem.h
+++ b/include/linux/spi/spi-mem.h
@@ -344,6 +344,8 @@ struct spi_controller_mem_ops {
unsigned long initial_delay_us,
unsigned long polling_rate_us,
unsigned long timeout_ms);
+ int (*execute_tuning)(struct spi_mem *mem, struct spi_mem_op *read_op,
+ struct spi_mem_op *write_op);
};
/**
@@ -426,6 +428,9 @@ int spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op);
void spi_mem_adjust_op_freq(struct spi_mem *mem, struct spi_mem_op *op);
u64 spi_mem_calc_op_duration(struct spi_mem *mem, struct spi_mem_op *op);
+int spi_mem_execute_tuning(struct spi_mem *mem, struct spi_mem_op *read_op,
+ struct spi_mem_op *write_op);
+
bool spi_mem_supports_op(struct spi_mem *mem,
const struct spi_mem_op *op);
--
2.34.1
More information about the linux-mtd
mailing list