Unverified Commit fd85b6b7 authored by Mark Brown's avatar Mark Brown
Browse files

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
parents 89b37e49 226d6cb3
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -562,6 +562,36 @@ void spi_mem_adjust_op_freq(struct spi_mem *mem, struct spi_mem_op *op)
}
EXPORT_SYMBOL_GPL(spi_mem_adjust_op_freq);

/**
 * spi_mem_calc_op_duration() - Derives the theoretical length (in ns) of an
 *			        operation. This helps finding the best variant
 *			        among a list of possible choices.
 * @op: the operation to benchmark
 *
 * Some chips have per-op frequency limitations, PCBs usually have their own
 * limitations as well, and controllers can support dual, quad or even octal
 * modes, sometimes in DTR. All these combinations make it impossible to
 * statically list the best combination for all situations. If we want something
 * 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.
 */
u64 spi_mem_calc_op_duration(struct spi_mem_op *op)
{
	u64 ncycles = 0;
	u32 ns_per_cycles;

	ns_per_cycles = 1000000000 / op->max_freq;
	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);
	ncycles += ((op->dummy.nbytes * 8) / op->dummy.buswidth) / (op->dummy.dtr ? 2 : 1);
	ncycles += ((op->data.nbytes * 8) / op->data.buswidth) / (op->data.dtr ? 2 : 1);

	return ncycles * ns_per_cycles;
}
EXPORT_SYMBOL_GPL(spi_mem_calc_op_duration);

static ssize_t spi_mem_no_dirmap_read(struct spi_mem_dirmap_desc *desc,
				      u64 offs, size_t len, void *buf)
{
+1 −0
Original line number Diff line number Diff line
@@ -424,6 +424,7 @@ bool spi_mem_default_supports_op(struct spi_mem *mem,

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_op *op);

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