Loading drivers/spi/spi-mem.c +30 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading include/linux/spi/spi-mem.h +1 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading
drivers/spi/spi-mem.c +30 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading
include/linux/spi/spi-mem.h +1 −0 Original line number Diff line number Diff line Loading @@ -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); Loading