napi_schedule(&ar->napi);
 }
 
+static int ath10k_sdio_read_rtc_state(struct ath10k_sdio *ar_sdio, unsigned char *state)
+{
+       struct ath10k *ar = ar_sdio->ar;
+       unsigned char rtc_state = 0;
+       int ret = 0;
+
+       rtc_state = sdio_f0_readb(ar_sdio->func, ATH10K_CIS_RTC_STATE_ADDR, &ret);
+       if (ret) {
+               ath10k_warn(ar, "failed to read rtc state: %d\n", ret);
+               return ret;
+       }
+
+       *state = rtc_state & 0x3;
+
+       return ret;
+}
+
+static int ath10k_sdio_hif_set_mbox_sleep(struct ath10k *ar, bool enable_sleep)
+{
+       struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+       u32 val;
+       int retry = ATH10K_CIS_READ_RETRY, ret = 0;
+       unsigned char rtc_state = 0;
+
+       sdio_claim_host(ar_sdio->func);
+
+       ret = ath10k_sdio_read32(ar, ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL, &val);
+       if (ret) {
+               ath10k_warn(ar, "failed to read fifo/chip control register: %d\n",
+                           ret);
+               goto release;
+       }
+
+       if (enable_sleep) {
+               val &= ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_OFF;
+               ar_sdio->mbox_state = SDIO_MBOX_SLEEP_STATE;
+       } else {
+               val |= ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_ON;
+               ar_sdio->mbox_state = SDIO_MBOX_AWAKE_STATE;
+       }
+
+       ret = ath10k_sdio_write32(ar, ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL, val);
+       if (ret) {
+               ath10k_warn(ar, "failed to write to FIFO_TIMEOUT_AND_CHIP_CONTROL: %d",
+                           ret);
+       }
+
+       if (!enable_sleep) {
+               do {
+                       udelay(ATH10K_CIS_READ_WAIT_4_RTC_CYCLE_IN_US);
+                       ret = ath10k_sdio_read_rtc_state(ar_sdio, &rtc_state);
+
+                       if (ret) {
+                               ath10k_warn(ar, "failed to disable mbox sleep: %d", ret);
+                               break;
+                       }
+
+                       ath10k_dbg(ar, ATH10K_DBG_SDIO, "sdio read rtc state: %d\n",
+                                  rtc_state);
+
+                       if (rtc_state == ATH10K_CIS_RTC_STATE_ON)
+                               break;
+
+                       udelay(ATH10K_CIS_XTAL_SETTLE_DURATION_IN_US);
+                       retry--;
+               } while (retry > 0);
+       }
+
+release:
+       sdio_release_host(ar_sdio->func);
+
+       return ret;
+}
+
+static void ath10k_sdio_sleep_timer_handler(struct timer_list *t)
+{
+       struct ath10k_sdio *ar_sdio = from_timer(ar_sdio, t, sleep_timer);
+
+       ar_sdio->mbox_state = SDIO_MBOX_REQUEST_TO_SLEEP_STATE;
+       queue_work(ar_sdio->workqueue, &ar_sdio->wr_async_work);
+}
+
 static void ath10k_sdio_write_async_work(struct work_struct *work)
 {
        struct ath10k_sdio *ar_sdio = container_of(work, struct ath10k_sdio,
                                                   wr_async_work);
        struct ath10k *ar = ar_sdio->ar;
        struct ath10k_sdio_bus_request *req, *tmp_req;
+       struct ath10k_mbox_info *mbox_info = &ar_sdio->mbox_info;
 
        spin_lock_bh(&ar_sdio->wr_async_lock);
 
        list_for_each_entry_safe(req, tmp_req, &ar_sdio->wr_asyncq, list) {
                list_del(&req->list);
                spin_unlock_bh(&ar_sdio->wr_async_lock);
+
+               if (req->address >= mbox_info->htc_addr &&
+                   ar_sdio->mbox_state == SDIO_MBOX_SLEEP_STATE) {
+                       ath10k_sdio_hif_set_mbox_sleep(ar, false);
+                       mod_timer(&ar_sdio->sleep_timer, jiffies +
+                                 msecs_to_jiffies(ATH10K_MIN_SLEEP_INACTIVITY_TIME_MS));
+               }
+
                __ath10k_sdio_write_async(ar, req);
                spin_lock_bh(&ar_sdio->wr_async_lock);
        }
 
        spin_unlock_bh(&ar_sdio->wr_async_lock);
+
+       if (ar_sdio->mbox_state == SDIO_MBOX_REQUEST_TO_SLEEP_STATE)
+               ath10k_sdio_hif_set_mbox_sleep(ar, true);
 }
 
 static int ath10k_sdio_prep_async_req(struct ath10k *ar, u32 addr,
 
        ath10k_dbg(ar, ATH10K_DBG_BOOT, "sdio power off\n");
 
+       del_timer_sync(&ar_sdio->sleep_timer);
+       ath10k_sdio_hif_set_mbox_sleep(ar, true);
+
        /* Disable the card */
        sdio_claim_host(ar_sdio->func);
 
        return ret;
 }
 
-static int ath10k_sdio_hif_set_mbox_sleep(struct ath10k *ar, bool enable_sleep)
-{
-       u32 val;
-       int ret;
-
-       ret = ath10k_sdio_read32(ar, ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL, &val);
-       if (ret) {
-               ath10k_warn(ar, "failed to read fifo/chip control register: %d\n",
-                           ret);
-               return ret;
-       }
-
-       if (enable_sleep)
-               val &= ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_OFF;
-       else
-               val |= ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_ON;
-
-       ret = ath10k_sdio_write32(ar, ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL, val);
-       if (ret) {
-               ath10k_warn(ar, "failed to write to FIFO_TIMEOUT_AND_CHIP_CONTROL: %d",
-                           ret);
-               return ret;
-       }
-
-       return 0;
-}
-
 /* HIF diagnostics */
 
 static int ath10k_sdio_hif_diag_read(struct ath10k *ar, u32 address, void *buf,
                ar_sdio->swap_mbox = false;
        }
 
+       ath10k_sdio_hif_set_mbox_sleep(ar, true);
+
        return 0;
 }
 
        if (!device_may_wakeup(ar->dev))
                return 0;
 
+       ath10k_sdio_hif_set_mbox_sleep(ar, true);
+
        pm_flag = MMC_PM_KEEP_POWER;
 
        ret = sdio_set_host_pm_flags(func, pm_flag);
                goto err_free_wq;
        }
 
+       timer_setup(&ar_sdio->sleep_timer, ath10k_sdio_sleep_timer_handler, 0);
+
        return 0;
 
 err_free_wq:
 
 #define ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_OFF 0xFFFEFFFF
 #define ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_ON 0x10000
 
+enum sdio_mbox_state {
+       SDIO_MBOX_UNKNOWN_STATE = 0,
+       SDIO_MBOX_REQUEST_TO_SLEEP_STATE = 1,
+       SDIO_MBOX_SLEEP_STATE = 2,
+       SDIO_MBOX_AWAKE_STATE = 3,
+};
+
+#define ATH10K_CIS_READ_WAIT_4_RTC_CYCLE_IN_US 125
+#define ATH10K_CIS_RTC_STATE_ADDR              0x1138
+#define ATH10K_CIS_RTC_STATE_ON                        0x01
+#define ATH10K_CIS_XTAL_SETTLE_DURATION_IN_US  1500
+#define ATH10K_CIS_READ_RETRY                  10
+#define ATH10K_MIN_SLEEP_INACTIVITY_TIME_MS    50
+
 /* TODO: remove this and use skb->cb instead, much cleaner approach */
 struct ath10k_sdio_bus_request {
        struct list_head list;
        spinlock_t wr_async_lock;
 
        struct work_struct async_work_rx;
+       struct timer_list sleep_timer;
+       enum sdio_mbox_state mbox_state;
 };
 
 static inline struct ath10k_sdio *ath10k_sdio_priv(struct ath10k *ar)