2021-02-24 07:19:51

by David Mosberger-Tang

[permalink] [raw]
Subject: [PATCH] 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 <[email protected]>
---
.../net/wireless/microchip/wilc1000/wlan.c | 56 +++++++++++++++++--
.../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, &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, &reg);
+ /* Clear bit 1 */
+ ret = hif_func->hif_read_reg(wilc, wakeup_reg, &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, &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)

--
2.25.1


2021-02-24 09:57:17

by Ajay Singh

[permalink] [raw]
Subject: Re: [PATCH] wilc1000: Support chip sleep over SPI


On 24/02/21 9:03 am, David Mosberger-Tang wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>
> 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.
>

Thanks David. The patch looks good to me.

Acked-by: Ajay Singh <[email protected]>

I will work on the wakeup sequence patch and try to submit it soon.

> Signed-off-by: David Mosberger-Tang <[email protected]>
> ---
> .../net/wireless/microchip/wilc1000/wlan.c | 56 +++++++++++++++++--
> .../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, &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, &reg);
> + /* Clear bit 1 */
> + ret = hif_func->hif_read_reg(wilc, wakeup_reg, &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, &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)
>
> --
> 2.25.1
>

2021-03-15 08:27:52

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH] wilc1000: Support chip sleep over SPI

David Mosberger-Tang <[email protected]> wrote:

> 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 <[email protected]>
> Acked-by: Ajay Singh <[email protected]>

Patch applied to wireless-drivers-next.git, thanks.

f135a1571a05 wilc1000: Support chip sleep over SPI

--
https://patchwork.kernel.org/project/linux-wireless/patch/[email protected]/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches