]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
staging: wilc1000: add sdio resume/suspend
authorGlen Lee <glen.lee@atmel.com>
Mon, 25 Jan 2016 07:35:08 +0000 (16:35 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 3 Feb 2016 23:25:40 +0000 (15:25 -0800)
This patch introduces sdio device suspend and resume functionality. sdio_reset
function is added to reset sdio. Remove static inline keyword from
chip_allow_sleep and chip_wakeup, and export symbols.

Signed-off-by: Glen Lee <glen.lee@atmel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/wilc1000/wilc_sdio.c
drivers/staging/wilc1000/wilc_wfi_netdevice.h
drivers/staging/wilc1000/wilc_wlan.c
drivers/staging/wilc1000/wilc_wlan.h

index caad876a8249d02c8715c7428a0e5e4f1222db02..f40a52730bc63082b97317fa918db4b1566d81ae 100644 (file)
@@ -42,6 +42,7 @@ static wilc_sdio_t g_sdio;
 
 static int sdio_write_reg(struct wilc *wilc, u32 addr, u32 data);
 static int sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data);
+static int sdio_init(struct wilc *wilc);
 
 static void wilc_sdio_interrupt(struct sdio_func *func)
 {
@@ -142,11 +143,82 @@ static void linux_sdio_remove(struct sdio_func *func)
        wilc_netdev_cleanup(sdio_get_drvdata(func));
 }
 
+static int sdio_reset(struct wilc *wilc)
+{
+       sdio_cmd52_t cmd;
+       int ret;
+       struct sdio_func *func = dev_to_sdio_func(wilc->dev);
+
+       cmd.read_write = 1;
+       cmd.function = 0;
+       cmd.raw = 0;
+       cmd.address = 0x6;
+       cmd.data = 0x8;
+       ret = wilc_sdio_cmd52(wilc, &cmd);
+       if (ret) {
+               dev_err(&func->dev, "Fail cmd 52, reset cmd ...\n");
+               return ret;
+       }
+       return 0;
+}
+
+static int wilc_sdio_suspend(struct device *dev)
+{
+       struct sdio_func *func = dev_to_sdio_func(dev);
+       struct wilc *wilc = sdio_get_drvdata(func);
+       int ret;
+
+       dev_info(dev, "sdio suspend\n");
+       chip_wakeup(wilc);
+
+       if (!wilc->suspend_event) {
+               wilc_chip_sleep_manually(wilc);
+       } else {
+               host_sleep_notify(wilc);
+               chip_allow_sleep(wilc);
+       }
+
+       ret = sdio_reset(wilc);
+       if (ret) {
+               dev_err(&func->dev, "Fail reset sdio\n");
+               return ret;
+       }
+       sdio_claim_host(func);
+
+       return 0;
+}
+
+static int wilc_sdio_resume(struct device *dev)
+{
+       struct sdio_func *func = dev_to_sdio_func(dev);
+       struct wilc *wilc = sdio_get_drvdata(func);
+
+       dev_info(dev, "sdio resume\n");
+       sdio_release_host(func);
+       chip_wakeup(wilc);
+       sdio_init(wilc);
+
+       if (wilc->suspend_event)
+               host_wakeup_notify(wilc);
+
+       chip_allow_sleep(wilc);
+
+       return 0;
+}
+
+static const struct dev_pm_ops wilc_sdio_pm_ops = {
+       .suspend = wilc_sdio_suspend,
+       .resume = wilc_sdio_resume,
+};
+
 static struct sdio_driver wilc1000_sdio_driver = {
        .name           = SDIO_MODALIAS,
        .id_table       = wilc_sdio_ids,
        .probe          = linux_sdio_probe,
        .remove         = linux_sdio_remove,
+       .drv = {
+               .pm = &wilc_sdio_pm_ops,
+       }
 };
 module_driver(wilc1000_sdio_driver,
              sdio_register_driver,
index 98ac8ed04a06cf43c844b48f0cd2fe9e9f8d7e81..cd3d21d61bed7047e61ba4dcb501a86462b121bd 100644 (file)
@@ -215,6 +215,7 @@ struct wilc {
        const struct firmware *firmware;
 
        struct device *dev;
+       bool suspend_event;
 };
 
 struct WILC_WFI_mon_priv {
index d824606a248b138a1a9bb16bb4ba75a1ad51f3e1..74e20879f8efb58d22aa77e482606ee127cf8c21 100644 (file)
@@ -3,8 +3,6 @@
 #include "wilc_wfi_netdevice.h"
 #include "wilc_wlan_cfg.h"
 
-static inline void chip_allow_sleep(struct wilc *wilc);
-static inline void chip_wakeup(struct wilc *wilc);
 static u32 dbgflag = N_INIT | N_ERR | N_INTR | N_TXQ | N_RXQ;
 
 /* FIXME: replace with dev_debug() */
@@ -515,7 +513,7 @@ static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc)
        return NULL;
 }
 
-static inline void chip_allow_sleep(struct wilc *wilc)
+void chip_allow_sleep(struct wilc *wilc)
 {
        u32 reg = 0;
 
@@ -524,8 +522,9 @@ static inline void chip_allow_sleep(struct wilc *wilc)
        wilc->hif_func->hif_write_reg(wilc, 0xf0, reg & ~BIT(0));
        wilc->hif_func->hif_write_reg(wilc, 0xfa, 0);
 }
+EXPORT_SYMBOL_GPL(chip_allow_sleep);
 
-static inline void chip_wakeup(struct wilc *wilc)
+void chip_wakeup(struct wilc *wilc)
 {
        u32 reg, clk_status_reg, trials = 0;
 
@@ -584,6 +583,7 @@ static inline void chip_wakeup(struct wilc *wilc)
        }
        chip_ps_state = CHIP_WAKEDUP;
 }
+EXPORT_SYMBOL_GPL(chip_wakeup);
 
 void wilc_chip_sleep_manually(struct wilc *wilc)
 {
@@ -597,6 +597,7 @@ void wilc_chip_sleep_manually(struct wilc *wilc)
        chip_ps_state = CHIP_SLEEPING_MANUAL;
        release_bus(wilc, RELEASE_ONLY);
 }
+EXPORT_SYMBOL_GPL(wilc_chip_sleep_manually);
 
 void host_wakeup_notify(struct wilc *wilc)
 {
@@ -604,6 +605,7 @@ void host_wakeup_notify(struct wilc *wilc)
        wilc->hif_func->hif_write_reg(wilc, 0x10b0, 1);
        release_bus(wilc, RELEASE_ONLY);
 }
+EXPORT_SYMBOL_GPL(host_wakeup_notify);
 
 void host_sleep_notify(struct wilc *wilc)
 {
@@ -611,6 +613,7 @@ void host_sleep_notify(struct wilc *wilc)
        wilc->hif_func->hif_write_reg(wilc, 0x10ac, 1);
        release_bus(wilc, RELEASE_ONLY);
 }
+EXPORT_SYMBOL_GPL(host_sleep_notify);
 
 int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
 {
index dd5abc52dfd93c9131cd083fc0f48cc462634943..53e56ff4d401a7ad5208ca77477b6b381d762191 100644 (file)
@@ -298,5 +298,6 @@ void WILC_WFI_p2p_rx(struct net_device *dev, u8 *buff, u32 size);
 void host_wakeup_notify(struct wilc *wilc);
 void host_sleep_notify(struct wilc *wilc);
 extern bool wilc_enable_ps;
-
+void chip_allow_sleep(struct wilc *wilc);
+void chip_wakeup(struct wilc *wilc);
 #endif