Skip to content

Commit fd85b6b

Browse files
committed
spi: Add spi_mem_calc_op_duration() helper
Merge series from Miquel Raynal <miquel.raynal@bootlin.com>: Add a spi_mem_calc_op_duration() helper
2 parents 89b37e4 + 226d6cb commit fd85b6b

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

drivers/spi/spi-mem.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,36 @@ void spi_mem_adjust_op_freq(struct spi_mem *mem, struct spi_mem_op *op)
562562
}
563563
EXPORT_SYMBOL_GPL(spi_mem_adjust_op_freq);
564564

565+
/**
566+
* spi_mem_calc_op_duration() - Derives the theoretical length (in ns) of an
567+
* operation. This helps finding the best variant
568+
* among a list of possible choices.
569+
* @op: the operation to benchmark
570+
*
571+
* Some chips have per-op frequency limitations, PCBs usually have their own
572+
* limitations as well, and controllers can support dual, quad or even octal
573+
* modes, sometimes in DTR. All these combinations make it impossible to
574+
* statically list the best combination for all situations. If we want something
575+
* accurate, all these combinations should be rated (eg. with a time estimate)
576+
* and the best pick should be taken based on these calculations.
577+
*
578+
* Returns a ns estimate for the time this op would take.
579+
*/
580+
u64 spi_mem_calc_op_duration(struct spi_mem_op *op)
581+
{
582+
u64 ncycles = 0;
583+
u32 ns_per_cycles;
584+
585+
ns_per_cycles = 1000000000 / op->max_freq;
586+
ncycles += ((op->cmd.nbytes * 8) / op->cmd.buswidth) / (op->cmd.dtr ? 2 : 1);
587+
ncycles += ((op->addr.nbytes * 8) / op->addr.buswidth) / (op->addr.dtr ? 2 : 1);
588+
ncycles += ((op->dummy.nbytes * 8) / op->dummy.buswidth) / (op->dummy.dtr ? 2 : 1);
589+
ncycles += ((op->data.nbytes * 8) / op->data.buswidth) / (op->data.dtr ? 2 : 1);
590+
591+
return ncycles * ns_per_cycles;
592+
}
593+
EXPORT_SYMBOL_GPL(spi_mem_calc_op_duration);
594+
565595
static ssize_t spi_mem_no_dirmap_read(struct spi_mem_dirmap_desc *desc,
566596
u64 offs, size_t len, void *buf)
567597
{

include/linux/spi/spi-mem.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@ bool spi_mem_default_supports_op(struct spi_mem *mem,
424424

425425
int spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op);
426426
void spi_mem_adjust_op_freq(struct spi_mem *mem, struct spi_mem_op *op);
427+
u64 spi_mem_calc_op_duration(struct spi_mem_op *op);
427428

428429
bool spi_mem_supports_op(struct spi_mem *mem,
429430
const struct spi_mem_op *op);

0 commit comments

Comments
 (0)