aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-mem.c
diff options
context:
space:
mode:
authorMiquel Raynal <[email protected]>2025-06-04 13:52:19 +0000
committerMiquel Raynal <[email protected]>2025-07-30 09:32:05 +0000
commita11a51896572273d04a9f6011ad22738c52ba554 (patch)
treef371d843414c1d2d63353a120f76ee5d764ac595 /drivers/spi/spi-mem.c
parentspi: spi-mem: Use picoseconds for calculating the op durations (diff)
downloadkernel-a11a51896572273d04a9f6011ad22738c52ba554.tar.gz
kernel-a11a51896572273d04a9f6011ad22738c52ba554.zip
spi: spi-mem: Take into account the actual maximum frequency
In order to pick the best variant, the duration of each typical operation is derived and then compared. These durations are based on the maximum capabilities of the chips, which are commonly the limiting factors. However there are other possible limiting pieces, such as the hardware layout, EMC considerations and in some cases, the SPI controller itself. We need to take this into account to further refine our variant choice, so let's use the actual frequency that will be used for the operation instead of the theoretical maximum. Signed-off-by: Miquel Raynal <[email protected]> Reviewed-by: Mark Brown <[email protected]>
Diffstat (limited to 'drivers/spi/spi-mem.c')
-rw-r--r--drivers/spi/spi-mem.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
index c42c227eb2a2..d3b7e857b377 100644
--- a/drivers/spi/spi-mem.c
+++ b/drivers/spi/spi-mem.c
@@ -586,15 +586,25 @@ EXPORT_SYMBOL_GPL(spi_mem_adjust_op_freq);
* accurate, all these combinations should be rated (eg. with a time estimate)
* and the best pick should be taken based on these calculations.
*
- * Returns a ns estimate for the time this op would take.
+ * Returns a ns estimate for the time this op would take, except if no
+ * frequency limit has been set, in this case we return the number of
+ * cycles nevertheless to allow callers to distinguish which operation
+ * would be the fastest at iso-frequency.
*/
-u64 spi_mem_calc_op_duration(struct spi_mem_op *op)
+u64 spi_mem_calc_op_duration(struct spi_mem *mem, struct spi_mem_op *op)
{
u64 ncycles = 0;
u64 ps_per_cycles, duration;
- ps_per_cycles = 1000000000000ULL;
- do_div(ps_per_cycles, op->max_freq);
+ spi_mem_adjust_op_freq(mem, op);
+
+ if (op->max_freq) {
+ ps_per_cycles = 1000000000000ULL;
+ do_div(ps_per_cycles, op->max_freq);
+ } else {
+ /* In this case, the unit is no longer a time unit */
+ ps_per_cycles = 1;
+ }
ncycles += ((op->cmd.nbytes * 8) / op->cmd.buswidth) / (op->cmd.dtr ? 2 : 1);
ncycles += ((op->addr.nbytes * 8) / op->addr.buswidth) / (op->addr.dtr ? 2 : 1);