Skip to content

Commit 62df72a

Browse files
committed
spi: spi-mem: Use picoseconds for calculating the op durations
spi_mem_calc_op_duration() is deriving the duration of a specific op, by multiplying the number of cycles with the time a cycle will last. This time was measured in nanoseconds, which means at high frequencies the delta between two frequencies might not be properly catch due to roundings. For instance, the Winbond driver has a changing number of dummy cycles depending on the speed, adding +8 dummy cycles when running at 166MHz compared to 162MHz. Both frequencies would lead to using a 6ns delay per cycle for the op duration computation, whereas in practice there is a small difference which actually offsets the number of extra dummy cycles on a normal page read. Augmenting the precision of the calculation by using picoseconds prevents selecting a lower frequency if we can do slightly better with another frequency involving more cycles. As a result, the above situation leads to comparing cycles of 6024 and 6172 picoseconds which leads to picking the most efficient variant. Reviewed-by: Mark Brown <[email protected]> Signed-off-by: Miquel Raynal <[email protected]>
1 parent f552a7c commit 62df72a

File tree

1 file changed

+10
-3
lines changed

1 file changed

+10
-3
lines changed

drivers/spi/spi-mem.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -591,9 +591,11 @@ EXPORT_SYMBOL_GPL(spi_mem_adjust_op_freq);
591591
u64 spi_mem_calc_op_duration(struct spi_mem_op *op)
592592
{
593593
u64 ncycles = 0;
594-
u32 ns_per_cycles;
594+
u64 ps_per_cycles, duration;
595+
596+
ps_per_cycles = 1000000000000ULL;
597+
do_div(ps_per_cycles, op->max_freq);
595598

596-
ns_per_cycles = 1000000000 / op->max_freq;
597599
ncycles += ((op->cmd.nbytes * 8) / op->cmd.buswidth) / (op->cmd.dtr ? 2 : 1);
598600
ncycles += ((op->addr.nbytes * 8) / op->addr.buswidth) / (op->addr.dtr ? 2 : 1);
599601

@@ -603,7 +605,12 @@ u64 spi_mem_calc_op_duration(struct spi_mem_op *op)
603605

604606
ncycles += ((op->data.nbytes * 8) / op->data.buswidth) / (op->data.dtr ? 2 : 1);
605607

606-
return ncycles * ns_per_cycles;
608+
/* Derive the duration in ps */
609+
duration = ncycles * ps_per_cycles;
610+
/* Convert into ns */
611+
do_div(duration, 1000);
612+
613+
return duration;
607614
}
608615
EXPORT_SYMBOL_GPL(spi_mem_calc_op_duration);
609616

0 commit comments

Comments
 (0)