Skip to content

Commit

Permalink
wilc1000: Make SPI transfers work at 48MHz
Browse files Browse the repository at this point in the history
For CMD_SINGLE_READ and CMD_INTERNAL_READ, WILC may insert one or more
zero bytes between the command response and the DATA Start tag (0xf3).
This behavior appears to be undocumented in "ATWILC1000 USER GUIDE"
(https://tinyurl.com/4hhshdts) but we have observed 1-4 zero bytes
when the SPI bus operates at 48MHz and none when it operates at 1MHz.

This code is derived from the equivalent code of the wilc driver in
the linux-at91 repository.

Signed-off-by: David Mosberger-Tang <davidm@egauge.net>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20210227172818.1711071-1-davidm@egauge.net
  • Loading branch information
David Mosberger-Tang authored and Kalle Valo committed Apr 17, 2021
1 parent d23a962 commit f2131fa
Showing 1 changed file with 29 additions and 13 deletions.
42 changes: 29 additions & 13 deletions drivers/net/wireless/microchip/wilc1000/spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@
#include "netdev.h"
#include "cfg80211.h"

/*
* For CMD_SINGLE_READ and CMD_INTERNAL_READ, WILC may insert one or
* more zero bytes between the command response and the DATA Start tag
* (0xf3). This behavior appears to be undocumented in "ATWILC1000
* USER GUIDE" (https://tinyurl.com/4hhshdts) but we have observed 1-4
* zero bytes when the SPI bus operates at 48MHz and none when it
* operates at 1MHz.
*/
#define WILC_SPI_RSP_HDR_EXTRA_DATA 8

struct wilc_spi {
int crc_off;
};
Expand Down Expand Up @@ -79,16 +89,15 @@ struct wilc_spi_cmd {
} __packed;

struct wilc_spi_read_rsp_data {
u8 rsp_cmd_type;
u8 status;
u8 resp_header;
u8 resp_data[4];
u8 header;
u8 data[4];
u8 crc[];
} __packed;

struct wilc_spi_rsp_data {
u8 rsp_cmd_type;
u8 status;
u8 data[];
} __packed;

static int wilc_bus_probe(struct spi_device *spi)
Expand Down Expand Up @@ -359,10 +368,11 @@ static int wilc_spi_single_read(struct wilc *wilc, u8 cmd, u32 adr, void *b,
struct spi_device *spi = to_spi_device(wilc->dev);
struct wilc_spi *spi_priv = wilc->bus_data;
u8 wb[32], rb[32];
int cmd_len, resp_len;
u8 crc[2];
int cmd_len, resp_len, i;
struct wilc_spi_cmd *c;
struct wilc_spi_read_rsp_data *r;
struct wilc_spi_read_rsp_data *r_data;
struct wilc_spi_rsp_data *r;

memset(wb, 0x0, sizeof(wb));
memset(rb, 0x0, sizeof(rb));
Expand All @@ -384,7 +394,8 @@ static int wilc_spi_single_read(struct wilc *wilc, u8 cmd, u32 adr, void *b,
}

cmd_len = offsetof(struct wilc_spi_cmd, u.simple_cmd.crc);
resp_len = sizeof(*r);
resp_len = sizeof(*r) + sizeof(*r_data) + WILC_SPI_RSP_HDR_EXTRA_DATA;

if (!spi_priv->crc_off) {
c->u.simple_cmd.crc[0] = wilc_get_crc7(wb, cmd_len);
cmd_len += 1;
Expand All @@ -403,7 +414,7 @@ static int wilc_spi_single_read(struct wilc *wilc, u8 cmd, u32 adr, void *b,
return -EINVAL;
}

r = (struct wilc_spi_read_rsp_data *)&rb[cmd_len];
r = (struct wilc_spi_rsp_data *)&rb[cmd_len];
if (r->rsp_cmd_type != cmd) {
dev_err(&spi->dev,
"Failed cmd response, cmd (%02x), resp (%02x)\n",
Expand All @@ -417,17 +428,22 @@ static int wilc_spi_single_read(struct wilc *wilc, u8 cmd, u32 adr, void *b,
return -EINVAL;
}

if (WILC_GET_RESP_HDR_START(r->resp_header) != 0xf) {
dev_err(&spi->dev, "Error, data read response (%02x)\n",
r->resp_header);
for (i = 0; i < WILC_SPI_RSP_HDR_EXTRA_DATA; ++i)
if (WILC_GET_RESP_HDR_START(r->data[i]) == 0xf)
break;

if (i >= WILC_SPI_RSP_HDR_EXTRA_DATA) {
dev_err(&spi->dev, "Error, data start missing\n");
return -EINVAL;
}

r_data = (struct wilc_spi_read_rsp_data *)&r->data[i];

if (b)
memcpy(b, r->resp_data, 4);
memcpy(b, r_data->data, 4);

if (!spi_priv->crc_off)
memcpy(crc, r->crc, 2);
memcpy(crc, r_data->crc, 2);

return 0;
}
Expand Down

0 comments on commit f2131fa

Please sign in to comment.