Commit ce3b9338 authored by David Mosberger-Tang's avatar David Mosberger-Tang Committed by Kalle Valo

wilc1000: Check for errors at end of DMA write

After a DMA write to the WILC chip, check for and report any errors.

This is based on code from the wilc driver in the linux-at91
repository.
Signed-off-by: default avatarDavid Mosberger-Tang <davidm@egauge.net>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20210227172818.1711071-3-davidm@egauge.net
parent 5ee2d9dd
......@@ -47,6 +47,17 @@ static const struct wilc_hif_func wilc_hif_spi;
#define SPI_ENABLE_VMM_RETRY_LIMIT 2
/* SPI response fields (section 11.1.2 in ATWILC1000 User Guide): */
#define RSP_START_FIELD GENMASK(7, 4)
#define RSP_TYPE_FIELD GENMASK(3, 0)
/* SPI response values for the response fields: */
#define RSP_START_TAG 0xc
#define RSP_TYPE_FIRST_PACKET 0x1
#define RSP_TYPE_INNER_PACKET 0x2
#define RSP_TYPE_LAST_PACKET 0x3
#define RSP_STATE_NO_ERROR 0x00
#define PROTOCOL_REG_PKT_SZ_MASK GENMASK(6, 4)
#define PROTOCOL_REG_CRC16_MASK GENMASK(3, 3)
#define PROTOCOL_REG_CRC7_MASK GENMASK(2, 2)
......@@ -750,6 +761,52 @@ static int wilc_spi_write_reg(struct wilc *wilc, u32 addr, u32 data)
return 0;
}
static int spi_data_rsp(struct wilc *wilc, u8 cmd)
{
struct spi_device *spi = to_spi_device(wilc->dev);
int result, i;
u8 rsp[4];
/*
* The response to data packets is two bytes long. For
* efficiency's sake, wilc_spi_write() wisely ignores the
* responses for all packets but the final one. The downside
* of that optimization is that when the final data packet is
* short, we may receive (part of) the response to the
* second-to-last packet before the one for the final packet.
* To handle this, we always read 4 bytes and then search for
* the last byte that contains the "Response Start" code (0xc
* in the top 4 bits). We then know that this byte is the
* first response byte of the final data packet.
*/
result = wilc_spi_rx(wilc, rsp, sizeof(rsp));
if (result) {
dev_err(&spi->dev, "Failed bus error...\n");
return result;
}
for (i = sizeof(rsp) - 2; i >= 0; --i)
if (FIELD_GET(RSP_START_FIELD, rsp[i]) == RSP_START_TAG)
break;
if (i < 0) {
dev_err(&spi->dev,
"Data packet response missing (%02x %02x %02x %02x)\n",
rsp[0], rsp[1], rsp[2], rsp[3]);
return -1;
}
/* rsp[i] is the last response start byte */
if (FIELD_GET(RSP_TYPE_FIELD, rsp[i]) != RSP_TYPE_LAST_PACKET
|| rsp[i + 1] != RSP_STATE_NO_ERROR) {
dev_err(&spi->dev, "Data response error (%02x %02x)\n",
rsp[i], rsp[i + 1]);
return -1;
}
return 0;
}
static int wilc_spi_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
{
struct spi_device *spi = to_spi_device(wilc->dev);
......@@ -777,7 +834,10 @@ static int wilc_spi_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
return result;
}
return 0;
/*
* Data response
*/
return spi_data_rsp(wilc, CMD_DMA_EXT_WRITE);
}
/********************************************
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment