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

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
Loading
Loading
Loading
Loading
+61 −1
Original line number Diff line number Diff line
@@ -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);
}

/********************************************