diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/staging/greybus/spi.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 0bae7f1..ce706ed 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -23,6 +23,7 @@ struct gb_spi { u32 rx_xfer_offset; u32 tx_xfer_offset; u32 last_xfer_size; + unsigned int op_timeout; u16 mode; u16 flags; u32 bits_per_word_mask; @@ -38,6 +39,8 @@ struct gb_spi { #define GB_SPI_STATE_OP_DONE ((void *)4) #define GB_SPI_STATE_MSG_ERROR ((void *)-1) +#define XFER_TIMEOUT_TOLERANCE 200 + static struct spi_master *get_master_from_spi(struct gb_spi *spi) { return gb_connection_get_data(spi->connection); @@ -95,6 +98,7 @@ static void clean_xfer_state(struct gb_spi *spi) spi->rx_xfer_offset = 0; spi->tx_xfer_offset = 0; spi->last_xfer_size = 0; + spi->op_timeout = 0; } static int setup_next_xfer(struct gb_spi *spi, struct spi_message *msg) @@ -112,6 +116,7 @@ static int setup_next_xfer(struct gb_spi *spi, struct spi_message *msg) (spi->rx_xfer_offset + spi->last_xfer_size == last_xfer->len)) { spi->tx_xfer_offset = 0; spi->rx_xfer_offset = 0; + spi->op_timeout = 0; if (last_xfer == list_last_entry(&msg->transfers, struct spi_transfer, transfer_list)) @@ -155,6 +160,7 @@ gb_spi_operation_create(struct gb_spi *spi, struct gb_connection *connection, u32 tx_size = 0, rx_size = 0, count = 0, xfer_len = 0, request_size; u32 tx_xfer_size = 0, rx_xfer_size = 0, len; u32 total_len = 0; + unsigned int xfer_timeout; size_t data_max; void *tx_data; @@ -234,6 +240,13 @@ gb_spi_operation_create(struct gb_spi *spi, struct gb_connection *connection, else xfer_len = xfer->len; + /* make sure we do not timeout in a slow transfer */ + xfer_timeout = xfer_len * 8 * MSEC_PER_SEC / xfer->speed_hz; + xfer_timeout += GB_OPERATION_TIMEOUT_DEFAULT; + + if (xfer_timeout > spi->op_timeout) + spi->op_timeout = xfer_timeout; + gb_xfer->speed_hz = cpu_to_le32(xfer->speed_hz); gb_xfer->len = cpu_to_le32(xfer_len); gb_xfer->delay_usecs = cpu_to_le16(xfer->delay_usecs); @@ -322,7 +335,8 @@ static int gb_spi_transfer_one_message(struct spi_master *master, continue; } - ret = gb_operation_request_send_sync(operation); + ret = gb_operation_request_send_sync_timeout(operation, + spi->op_timeout); if (!ret) { response = operation->response->payload; if (response) |