Commit 6d9eecd4 authored by Lars-Peter Clausen's avatar Lars-Peter Clausen Committed by Jonathan Cameron
Browse files

spi: Add helper functions for setting up transfers



Quite often the pattern used for setting up and transferring a synchronous SPI
transaction looks very much like the following:

	struct spi_message msg;
	struct spi_transfer xfers[] = {
		...
	};

	spi_message_init(&msg);
	spi_message_add_tail(&xfers[0], &msg);
	...
	spi_message_add_tail(&xfers[ARRAY_SIZE(xfers) - 1], &msg);

	ret = spi_sync(&msg);

This patch adds two new helper functions for handling this case. The first
helper function spi_message_init_with_transfers() takes a spi_message and an
array of spi_transfers. It will initialize the message and then call
spi_message_add_tail() for each transfer in the array. E.g. the following

	spi_message_init(&msg);
	spi_message_add_tail(&xfers[0], &msg);
	...
	spi_message_add_tail(&xfers[ARRAY_SIZE(xfers) - 1], &msg);

can be rewritten as

	spi_message_init_with_transfers(&msg, xfers, ARRAY_SIZE(xfers));

The second function spi_sync_transfer() takes a SPI device and an array of
spi_transfers. It will allocate a new spi_message (on the stack) and add all
transfers in the array to the message. Finally it will call spi_sync() on the
message.

E.g. the follwing

	struct spi_message msg;
	struct spi_transfer xfers[] = {
		...
	};

	spi_message_init(&msg);
	spi_message_add_tail(&xfers[0], &msg);
	...
	spi_message_add_tail(&xfers[ARRAY_SIZE(xfers) - 1], &msg);

	ret = spi_sync(spi, &msg);

can be rewritten as

	struct spi_transfer xfers[] = {
		...
	};

	ret = spi_sync_transfer(spi, xfers, ARRAY_SIZE(xfers));

A coccinelle script to find such instances will follow.

Signed-off-by: default avatarLars-Peter Clausen <lars@metafoo.de>
Reviewed-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: default avatarJonathan Cameron <jic23@kernel.org>
parent ad76fda7
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
@@ -591,6 +591,26 @@ spi_transfer_del(struct spi_transfer *t)
	list_del(&t->transfer_list);
}

/**
 * spi_message_init_with_transfers - Initialize spi_message and append transfers
 * @m: spi_message to be initialized
 * @xfers: An array of spi transfers
 * @num_xfers: Number of items in the xfer array
 *
 * This function initializes the given spi_message and adds each spi_transfer in
 * the given array to the message.
 */
static inline void
spi_message_init_with_transfers(struct spi_message *m,
struct spi_transfer *xfers, unsigned int num_xfers)
{
	unsigned int i;

	spi_message_init(m);
	for (i = 0; i < num_xfers; ++i)
		spi_message_add_tail(&xfers[i], m);
}

/* It's fine to embed message and transaction structures in other data
 * structures so long as you don't free them while they're in use.
 */
@@ -683,6 +703,30 @@ spi_read(struct spi_device *spi, void *buf, size_t len)
	return spi_sync(spi, &m);
}

/**
 * spi_sync_transfer - synchronous SPI data transfer
 * @spi: device with which data will be exchanged
 * @xfers: An array of spi_transfers
 * @num_xfers: Number of items in the xfer array
 * Context: can sleep
 *
 * Does a synchronous SPI data transfer of the given spi_transfer array.
 *
 * For more specific semantics see spi_sync().
 *
 * It returns zero on success, else a negative error code.
 */
static inline int
spi_sync_transfer(struct spi_device *spi, struct spi_transfer *xfers,
	unsigned int num_xfers)
{
	struct spi_message msg;

	spi_message_init_with_transfers(&msg, xfers, num_xfers);

	return spi_sync(spi, &msg);
}

/* this copies txbuf and rxbuf data; for small transfers only! */
extern int spi_write_then_read(struct spi_device *spi,
		const void *txbuf, unsigned n_tx,