wifi: wilc1000: fix incorrect power down sequence
authorAjay Singh <ajay.kathat@microchip.com>
Mon, 15 Jan 2024 14:56:33 +0000 (15:56 +0100)
committerKalle Valo <kvalo@kernel.org>
Thu, 18 Jan 2024 09:35:14 +0000 (11:35 +0200)
Use the correct register configuration when the WILC chip is down so the
successive interface up operation is successful. The modified registers
values during chip down helps to avoid the "FW not responding" debug
message which sometimes occurs because of temporary bus communication
failure during the next start. Also, make sure on first communication with
the chip that it is indeed woken up.

Reported-by: Michael Walle <mwalle@kernel.org>
Closes: https://lore.kernel.org/linux-wireless/20221026085415.6jgwrhq4sunqaypm@0002.3ffe.de/
Signed-off-by: Ajay Singh <ajay.kathat@microchip.com>
Signed-off-by: Alexis Lothoré <alexis.lothore@bootlin.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://msgid.link/20240115-wilc_1000_fixes-v1-4-54d29463a738@bootlin.com
drivers/net/wireless/microchip/wilc1000/wlan.c
drivers/net/wireless/microchip/wilc1000/wlan.h

index 9eb115c79c90aaae82a4f7b6a66a144cff1b6561..6b2f2269ddf82f3f789f13bcca0d53ec7b4f21cd 100644 (file)
@@ -1198,27 +1198,32 @@ int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif)
 
        acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
 
-       ret = wilc->hif_func->hif_read_reg(wilc, WILC_GP_REG_0, &reg);
-       if (ret) {
-               netdev_err(vif->ndev, "Error while reading reg\n");
+       ret = wilc->hif_func->hif_read_reg(wilc, GLOBAL_MODE_CONTROL, &reg);
+       if (ret)
                goto release;
-       }
 
-       ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_0,
-                                       (reg | WILC_ABORT_REQ_BIT));
-       if (ret) {
-               netdev_err(vif->ndev, "Error while writing reg\n");
+       reg &= ~WILC_GLOBAL_MODE_ENABLE_WIFI;
+       ret = wilc->hif_func->hif_write_reg(wilc, GLOBAL_MODE_CONTROL, reg);
+       if (ret)
+               goto release;
+
+       ret = wilc->hif_func->hif_read_reg(wilc, PWR_SEQ_MISC_CTRL, &reg);
+       if (ret)
+               goto release;
+
+       reg &= ~WILC_PWR_SEQ_ENABLE_WIFI_SLEEP;
+       ret = wilc->hif_func->hif_write_reg(wilc, PWR_SEQ_MISC_CTRL, reg);
+       if (ret)
                goto release;
-       }
 
-       ret = wilc->hif_func->hif_read_reg(wilc, WILC_FW_HOST_COMM, &reg);
+       ret = wilc->hif_func->hif_read_reg(wilc, WILC_GP_REG_0, &reg);
        if (ret) {
                netdev_err(vif->ndev, "Error while reading reg\n");
                goto release;
        }
-       reg = BIT(0);
 
-       ret = wilc->hif_func->hif_write_reg(wilc, WILC_FW_HOST_COMM, reg);
+       ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_0,
+                                       (reg | WILC_ABORT_REQ_BIT));
        if (ret) {
                netdev_err(vif->ndev, "Error while writing reg\n");
                goto release;
@@ -1410,7 +1415,7 @@ static int init_chip(struct net_device *dev)
        struct wilc_vif *vif = netdev_priv(dev);
        struct wilc *wilc = vif->wilc;
 
-       acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY);
+       acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
 
        chipid = wilc_get_chipid(wilc, true);
 
@@ -1440,7 +1445,7 @@ static int init_chip(struct net_device *dev)
        }
 
 release:
-       release_bus(wilc, WILC_BUS_RELEASE_ONLY);
+       release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
 
        return ret;
 }
index a72cd5cac81d5fb3eaf16ade51acd84f49a53814..f02775f7e41fe86c71a31364acf76b09b1fa19c3 100644 (file)
 #define WILC_GP_REG_0                  0x149c
 #define WILC_GP_REG_1                  0x14a0
 
+#define GLOBAL_MODE_CONTROL            0x1614
+#define PWR_SEQ_MISC_CTRL              0x3008
+
+#define WILC_GLOBAL_MODE_ENABLE_WIFI   BIT(0)
+#define WILC_PWR_SEQ_ENABLE_WIFI_SLEEP BIT(28)
+
 #define WILC_HAVE_SDIO_IRQ_GPIO                BIT(0)
 #define WILC_HAVE_USE_PMU              BIT(1)
 #define WILC_HAVE_SLEEP_CLK_SRC_RTC    BIT(2)