diff options
author | Ajay Singh <ajay.kathat@microchip.com> | 2021-09-16 16:49:19 +0000 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2021-09-21 18:08:16 +0300 |
commit | 1bcc0879c963770c90bc07d9aa5d0d50dda925f3 (patch) | |
tree | 12e8c415d2771138f3b539937bea35437ae156cf /drivers/net/wireless/microchip | |
parent | 5bb9de8bcb18c38ea089a287b77944ef8ee71abd (diff) | |
download | linux-1bcc0879c963770c90bc07d9aa5d0d50dda925f3.tar.bz2 |
wilc1000: add reset/terminate/repeat command support for SPI bus
Add reset/terminate/repeat command for SPI module. In case of SPI commands
failure, the host should issue a RESET command to WILC chip to recover
from any temporary bus error.
For now, the new command support is added and later the SPI read/write
API's would be modified to make use of these commands for retry mechanism
Signed-off-by: Ajay Singh <ajay.kathat@microchip.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20210916164902.74629-6-ajay.kathat@microchip.com
Diffstat (limited to 'drivers/net/wireless/microchip')
-rw-r--r-- | drivers/net/wireless/microchip/wilc1000/spi.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/drivers/net/wireless/microchip/wilc1000/spi.c b/drivers/net/wireless/microchip/wilc1000/spi.c index dd481dc0b5ce..602316f4367c 100644 --- a/drivers/net/wireless/microchip/wilc1000/spi.c +++ b/drivers/net/wireless/microchip/wilc1000/spi.c @@ -144,6 +144,12 @@ struct wilc_spi_rsp_data { u8 data[]; } __packed; +struct wilc_spi_special_cmd_rsp { + u8 skip_byte; + u8 rsp_cmd_type; + u8 status; +} __packed; + static int wilc_bus_probe(struct spi_device *spi) { int ret; @@ -709,6 +715,61 @@ static int wilc_spi_dma_rw(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz) return 0; } +static int wilc_spi_special_cmd(struct wilc *wilc, u8 cmd) +{ + 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 = 0; + struct wilc_spi_cmd *c; + struct wilc_spi_special_cmd_rsp *r; + + if (cmd != CMD_TERMINATE && cmd != CMD_REPEAT && cmd != CMD_RESET) + return -EINVAL; + + memset(wb, 0x0, sizeof(wb)); + memset(rb, 0x0, sizeof(rb)); + c = (struct wilc_spi_cmd *)wb; + c->cmd_type = cmd; + + if (cmd == CMD_RESET) + memset(c->u.simple_cmd.addr, 0xFF, 3); + + cmd_len = offsetof(struct wilc_spi_cmd, u.simple_cmd.crc); + resp_len = sizeof(*r); + + if (spi_priv->crc7_enabled) { + c->u.simple_cmd.crc[0] = wilc_get_crc7(wb, cmd_len); + cmd_len += 1; + } + if (cmd_len + resp_len > ARRAY_SIZE(wb)) { + dev_err(&spi->dev, "spi buffer size too small (%d) (%d) (%zu)\n", + cmd_len, resp_len, ARRAY_SIZE(wb)); + return -EINVAL; + } + + if (wilc_spi_tx_rx(wilc, wb, rb, cmd_len + resp_len)) { + dev_err(&spi->dev, "Failed cmd write, bus error...\n"); + return -EINVAL; + } + + r = (struct wilc_spi_special_cmd_rsp *)&rb[cmd_len]; + if (r->rsp_cmd_type != cmd) { + if (!spi_priv->probing_crc) + dev_err(&spi->dev, + "Failed cmd response, cmd (%02x), resp (%02x)\n", + cmd, r->rsp_cmd_type); + return -EINVAL; + } + + if (r->status != WILC_SPI_COMMAND_STAT_SUCCESS) { + dev_err(&spi->dev, "Failed cmd state response state (%02x)\n", + r->status); + return -EINVAL; + } + return 0; +} + static int wilc_spi_read_reg(struct wilc *wilc, u32 addr, u32 *data) { struct spi_device *spi = to_spi_device(wilc->dev); |