diff options
author | David Mosberger-Tang <davidm@egauge.net> | 2021-02-24 03:33:23 +0000 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2021-03-15 10:23:53 +0200 |
commit | f135a1571a0579bebed625e3af0b1fcae6dff7c5 (patch) | |
tree | fcaa73c69127b9cc431655dc2f3c1b1229bd90eb /drivers | |
parent | 4a7ea94377c928355f778bd2f5cac73757935425 (diff) |
wilc1000: Support chip sleep over SPI
chip_allow_sleep() only supported wakeup via SDIO, which made the
driver unusable over SPI. This code is a straight forward port from
the driver in the linux-at91 repository.
Signed-off-by: David Mosberger-Tang <davidm@egauge.net>
Acked-by: Ajay Singh <ajay.kathat@microchip.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20210224033317.1507603-1-davidm@egauge.net
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/microchip/wilc1000/wlan.c | 56 | ||||
-rw-r--r-- | drivers/net/wireless/microchip/wilc1000/wlan.h | 6 |
2 files changed, 58 insertions, 4 deletions
diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.c b/drivers/net/wireless/microchip/wilc1000/wlan.c index 31d51385ba93..d4a90c490084 100644 --- a/drivers/net/wireless/microchip/wilc1000/wlan.c +++ b/drivers/net/wireless/microchip/wilc1000/wlan.c @@ -552,12 +552,60 @@ static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc) void chip_allow_sleep(struct wilc *wilc) { u32 reg = 0; + const struct wilc_hif_func *hif_func = wilc->hif_func; + u32 wakeup_reg, wakeup_bit; + u32 to_host_from_fw_reg, to_host_from_fw_bit; + u32 from_host_to_fw_reg, from_host_to_fw_bit; + u32 trials = 100; + int ret; + + if (wilc->io_type == WILC_HIF_SDIO) { + wakeup_reg = WILC_SDIO_WAKEUP_REG; + wakeup_bit = WILC_SDIO_WAKEUP_BIT; + from_host_to_fw_reg = WILC_SDIO_HOST_TO_FW_REG; + from_host_to_fw_bit = WILC_SDIO_HOST_TO_FW_BIT; + to_host_from_fw_reg = WILC_SDIO_FW_TO_HOST_REG; + to_host_from_fw_bit = WILC_SDIO_FW_TO_HOST_BIT; + } else { + wakeup_reg = WILC_SPI_WAKEUP_REG; + wakeup_bit = WILC_SPI_WAKEUP_BIT; + from_host_to_fw_reg = WILC_SPI_HOST_TO_FW_REG; + from_host_to_fw_bit = WILC_SPI_HOST_TO_FW_BIT; + to_host_from_fw_reg = WILC_SPI_FW_TO_HOST_REG; + to_host_from_fw_bit = WILC_SPI_FW_TO_HOST_BIT; + } + + while (trials--) { + ret = hif_func->hif_read_reg(wilc, to_host_from_fw_reg, ®); + if (ret) + return; + if ((reg & to_host_from_fw_bit) == 0) + break; + } + if (!trials) + pr_warn("FW not responding\n"); - wilc->hif_func->hif_read_reg(wilc, WILC_SDIO_WAKEUP_REG, ®); + /* Clear bit 1 */ + ret = hif_func->hif_read_reg(wilc, wakeup_reg, ®); + if (ret) + return; + if (reg & wakeup_bit) { + reg &= ~wakeup_bit; + ret = hif_func->hif_write_reg(wilc, wakeup_reg, reg); + if (ret) + return; + } - wilc->hif_func->hif_write_reg(wilc, WILC_SDIO_WAKEUP_REG, - reg & ~WILC_SDIO_WAKEUP_BIT); - wilc->hif_func->hif_write_reg(wilc, WILC_SDIO_HOST_TO_FW_REG, 0); + ret = hif_func->hif_read_reg(wilc, from_host_to_fw_reg, ®); + if (ret) + return; + if (reg & from_host_to_fw_bit) { + reg &= ~from_host_to_fw_bit; + ret = hif_func->hif_write_reg(wilc, from_host_to_fw_reg, reg); + if (ret) + return; + + } } EXPORT_SYMBOL_GPL(chip_allow_sleep); diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.h b/drivers/net/wireless/microchip/wilc1000/wlan.h index d55eb6b3a12a..6479acc12b95 100644 --- a/drivers/net/wireless/microchip/wilc1000/wlan.h +++ b/drivers/net/wireless/microchip/wilc1000/wlan.h @@ -97,6 +97,12 @@ #define WILC_SPI_WAKEUP_REG 0x1 #define WILC_SPI_WAKEUP_BIT BIT(1) +#define WILC_SPI_HOST_TO_FW_REG 0x0b +#define WILC_SPI_HOST_TO_FW_BIT BIT(0) + +#define WILC_SPI_FW_TO_HOST_REG 0x10 +#define WILC_SPI_FW_TO_HOST_BIT BIT(0) + #define WILC_SPI_PROTOCOL_OFFSET (WILC_SPI_PROTOCOL_CONFIG - \ WILC_SPI_REG_BASE) |