Commit 5bb9de8b authored by Ajay Singh's avatar Ajay Singh Committed by Kalle Valo
Browse files

wilc1000: configure registers to handle chip wakeup sequence



Use the correct sequence to configure clockless registers for chip wake-up.
The following sequence is expected from WILC chip for wakeup:
 - set wakeup bit in wakeup_reg register
 - after setting the wakeup bit, read back the clock status bit for wakeup
   complete.

For SDIO/SPI modules, the wakeup sequence is the same except uses different
register values so refactored the code to use common function for both
SDIO/SPI bus.

Signed-off-by: default avatarAjay Singh <ajay.kathat@microchip.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20210916164902.74629-5-ajay.kathat@microchip.com
parent 0ec5408c
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -1726,7 +1726,6 @@ int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type,
	*wilc = wl;
	wl->io_type = io_type;
	wl->hif_func = ops;
	wl->chip_ps_state = WILC_CHIP_WAKEDUP;

	for (i = 0; i < NQUEUES; i++)
		INIT_LIST_HEAD(&wl->txq[i].txq_head.list);
+0 −1
Original line number Diff line number Diff line
@@ -265,7 +265,6 @@ struct wilc {
	bool suspend_event;

	struct workqueue_struct *hif_workqueue;
	enum chip_ps_states chip_ps_state;
	struct wilc_cfg cfg;
	void *bus_data;
	struct net_device *monitor_dev;
+51 −47
Original line number Diff line number Diff line
@@ -10,6 +10,8 @@
#include "cfg80211.h"
#include "wlan_cfg.h"

#define WAKE_UP_TRIAL_RETRY		10000

static inline bool is_wilc1000(u32 id)
{
	return (id & (~WILC_CHIP_REV_FIELD)) == WILC_1000_BASE_ID;
@@ -611,60 +613,62 @@ EXPORT_SYMBOL_GPL(chip_allow_sleep);

void chip_wakeup(struct wilc *wilc)
{
	u32 reg, clk_status_reg;
	const struct wilc_hif_func *h = wilc->hif_func;
	u32 ret = 0;
	u32 clk_status_val = 0, trials = 0;
	u32 wakeup_reg, wakeup_bit;
	u32 clk_status_reg, clk_status_bit;
	u32 to_host_from_fw_reg, to_host_from_fw_bit;
	u32 from_host_to_fw_reg, from_host_to_fw_bit;
	const struct wilc_hif_func *hif_func = wilc->hif_func;

	if (wilc->io_type == WILC_HIF_SPI) {
		do {
			h->hif_read_reg(wilc, WILC_SPI_WAKEUP_REG, &reg);
			h->hif_write_reg(wilc, WILC_SPI_WAKEUP_REG,
					 reg | WILC_SPI_WAKEUP_BIT);
			h->hif_write_reg(wilc, WILC_SPI_WAKEUP_REG,
					 reg & ~WILC_SPI_WAKEUP_BIT);
	if (wilc->io_type == WILC_HIF_SDIO) {
		wakeup_reg = WILC_SDIO_WAKEUP_REG;
		wakeup_bit = WILC_SDIO_WAKEUP_BIT;
		clk_status_reg = WILC_SDIO_CLK_STATUS_REG;
		clk_status_bit = WILC_SDIO_CLK_STATUS_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;
		clk_status_reg = WILC_SPI_CLK_STATUS_REG;
		clk_status_bit = WILC_SPI_CLK_STATUS_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;
	}

			do {
				usleep_range(2000, 2500);
				wilc_get_chipid(wilc, true);
			} while (wilc_get_chipid(wilc, true) == 0);
		} while (wilc_get_chipid(wilc, true) == 0);
	} else if (wilc->io_type == WILC_HIF_SDIO) {
		h->hif_write_reg(wilc, WILC_SDIO_HOST_TO_FW_REG,
				 WILC_SDIO_HOST_TO_FW_BIT);
		usleep_range(200, 400);
		h->hif_read_reg(wilc, WILC_SDIO_WAKEUP_REG, &reg);
		do {
			h->hif_write_reg(wilc, WILC_SDIO_WAKEUP_REG,
					 reg | WILC_SDIO_WAKEUP_BIT);
			h->hif_read_reg(wilc, WILC_SDIO_CLK_STATUS_REG,
					&clk_status_reg);
	/* indicate host wakeup */
	ret = hif_func->hif_write_reg(wilc, from_host_to_fw_reg,
				      from_host_to_fw_bit);
	if (ret)
		return;

			while (!(clk_status_reg & WILC_SDIO_CLK_STATUS_BIT)) {
				usleep_range(2000, 2500);
	/* Set wake-up bit */
	ret = hif_func->hif_write_reg(wilc, wakeup_reg,
				      wakeup_bit);
	if (ret)
		return;

				h->hif_read_reg(wilc, WILC_SDIO_CLK_STATUS_REG,
						&clk_status_reg);
			}
			if (!(clk_status_reg & WILC_SDIO_CLK_STATUS_BIT)) {
				h->hif_write_reg(wilc, WILC_SDIO_WAKEUP_REG,
						 reg & ~WILC_SDIO_WAKEUP_BIT);
			}
		} while (!(clk_status_reg & WILC_SDIO_CLK_STATUS_BIT));
	while (trials < WAKE_UP_TRIAL_RETRY) {
		ret = hif_func->hif_read_reg(wilc, clk_status_reg,
					     &clk_status_val);
		if (ret) {
			pr_err("Bus error %d %x\n", ret, clk_status_val);
			return;
		}
		if (clk_status_val & clk_status_bit)
			break;

	if (wilc->chip_ps_state == WILC_CHIP_SLEEPING_MANUAL) {
		if (wilc_get_chipid(wilc, false) < WILC_1000_BASE_ID_2B) {
			u32 val32;

			h->hif_read_reg(wilc, WILC_REG_4_TO_1_RX, &val32);
			val32 |= BIT(6);
			h->hif_write_reg(wilc, WILC_REG_4_TO_1_RX, val32);

			h->hif_read_reg(wilc, WILC_REG_4_TO_1_TX_BANK0, &val32);
			val32 |= BIT(6);
			h->hif_write_reg(wilc, WILC_REG_4_TO_1_TX_BANK0, val32);
		trials++;
	}
	if (trials >= WAKE_UP_TRIAL_RETRY) {
		pr_err("Failed to wake-up the chip\n");
		return;
	}
	wilc->chip_ps_state = WILC_CHIP_WAKEDUP;
}
EXPORT_SYMBOL_GPL(chip_wakeup);

+2 −0
Original line number Diff line number Diff line
@@ -97,6 +97,8 @@
#define WILC_SPI_WAKEUP_REG		0x1
#define WILC_SPI_WAKEUP_BIT		BIT(1)

#define WILC_SPI_CLK_STATUS_REG        0x0f
#define WILC_SPI_CLK_STATUS_BIT        BIT(2)
#define WILC_SPI_HOST_TO_FW_REG		0x0b
#define WILC_SPI_HOST_TO_FW_BIT		BIT(0)

+0 −6
Original line number Diff line number Diff line
@@ -48,12 +48,6 @@ enum {
	WILC_FW_MAX_PSPOLL_PS = 4
};

enum chip_ps_states {
	WILC_CHIP_WAKEDUP = 0,
	WILC_CHIP_SLEEPING_AUTO = 1,
	WILC_CHIP_SLEEPING_MANUAL = 2
};

enum bus_acquire {
	WILC_BUS_ACQUIRE_ONLY = 0,
	WILC_BUS_ACQUIRE_AND_WAKEUP = 1,