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

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
......@@ -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);
......
......@@ -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;
......
......@@ -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;
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);
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);
while (!(clk_status_reg & WILC_SDIO_CLK_STATUS_BIT)) {
usleep_range(2000, 2500);
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;
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));
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;
}
if (wilc->chip_ps_state == WILC_CHIP_SLEEPING_MANUAL) {
if (wilc_get_chipid(wilc, false) < WILC_1000_BASE_ID_2B) {
u32 val32;
/* indicate host wakeup */
ret = hif_func->hif_write_reg(wilc, from_host_to_fw_reg,
from_host_to_fw_bit);
if (ret)
return;
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);
/* Set wake-up bit */
ret = hif_func->hif_write_reg(wilc, wakeup_reg,
wakeup_bit);
if (ret)
return;
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);
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;
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);
......
......@@ -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)
......
......@@ -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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment