|
@@ -880,6 +880,7 @@ static struct rsi_host_intf_ops sdio_host_intf_ops = {
|
|
.master_reg_read = rsi_sdio_master_reg_read,
|
|
.master_reg_read = rsi_sdio_master_reg_read,
|
|
.master_reg_write = rsi_sdio_master_reg_write,
|
|
.master_reg_write = rsi_sdio_master_reg_write,
|
|
.load_data_master_write = rsi_sdio_load_data_master_write,
|
|
.load_data_master_write = rsi_sdio_load_data_master_write,
|
|
|
|
+ .reinit_device = rsi_sdio_reinit_device,
|
|
};
|
|
};
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -936,6 +937,8 @@ static int rsi_probe(struct sdio_func *pfunction,
|
|
return -EIO;
|
|
return -EIO;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ adapter->priv->hibernate_resume = false;
|
|
|
|
+ adapter->priv->reinit_hw = false;
|
|
return 0;
|
|
return 0;
|
|
fail:
|
|
fail:
|
|
rsi_91x_deinit(adapter);
|
|
rsi_91x_deinit(adapter);
|
|
@@ -1198,9 +1201,117 @@ static int rsi_resume(struct device *dev)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int rsi_freeze(struct device *dev)
|
|
|
|
+{
|
|
|
|
+ int ret;
|
|
|
|
+ struct sdio_func *pfunction = dev_to_sdio_func(dev);
|
|
|
|
+ struct rsi_hw *adapter = sdio_get_drvdata(pfunction);
|
|
|
|
+ struct rsi_common *common;
|
|
|
|
+ struct rsi_91x_sdiodev *sdev;
|
|
|
|
+
|
|
|
|
+ rsi_dbg(INFO_ZONE, "SDIO Bus freeze ===>\n");
|
|
|
|
+
|
|
|
|
+ if (!adapter) {
|
|
|
|
+ rsi_dbg(ERR_ZONE, "Device is not ready\n");
|
|
|
|
+ return -ENODEV;
|
|
|
|
+ }
|
|
|
|
+ common = adapter->priv;
|
|
|
|
+ sdev = (struct rsi_91x_sdiodev *)adapter->rsi_dev;
|
|
|
|
+
|
|
|
|
+#ifdef CONFIG_RSI_WOW
|
|
|
|
+ if ((common->wow_flags & RSI_WOW_ENABLED) &&
|
|
|
|
+ (common->wow_flags & RSI_WOW_NO_CONNECTION))
|
|
|
|
+ rsi_dbg(ERR_ZONE,
|
|
|
|
+ "##### Device can not wake up through WLAN\n");
|
|
|
|
+#endif
|
|
|
|
+ ret = rsi_sdio_disable_interrupts(pfunction);
|
|
|
|
+
|
|
|
|
+ if (sdev->write_fail)
|
|
|
|
+ rsi_dbg(INFO_ZONE, "###### Device is not ready #######\n");
|
|
|
|
+
|
|
|
|
+ ret = rsi_set_sdio_pm_caps(adapter);
|
|
|
|
+ if (ret)
|
|
|
|
+ rsi_dbg(INFO_ZONE, "Setting power management caps failed\n");
|
|
|
|
+
|
|
|
|
+ rsi_dbg(INFO_ZONE, "***** RSI module freezed *****\n");
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int rsi_thaw(struct device *dev)
|
|
|
|
+{
|
|
|
|
+ struct sdio_func *pfunction = dev_to_sdio_func(dev);
|
|
|
|
+ struct rsi_hw *adapter = sdio_get_drvdata(pfunction);
|
|
|
|
+ struct rsi_common *common = adapter->priv;
|
|
|
|
+
|
|
|
|
+ rsi_dbg(ERR_ZONE, "SDIO Bus thaw =====>\n");
|
|
|
|
+
|
|
|
|
+ common->hibernate_resume = true;
|
|
|
|
+ common->fsm_state = FSM_CARD_NOT_READY;
|
|
|
|
+ common->iface_down = true;
|
|
|
|
+
|
|
|
|
+ rsi_sdio_enable_interrupts(pfunction);
|
|
|
|
+
|
|
|
|
+ rsi_dbg(INFO_ZONE, "***** RSI module thaw done *****\n");
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int rsi_sdio_reinit_device(struct rsi_hw *adapter)
|
|
|
|
+{
|
|
|
|
+ struct rsi_91x_sdiodev *sdev = adapter->rsi_dev;
|
|
|
|
+ struct sdio_func *pfunction = sdev->pfunction;
|
|
|
|
+ int ii;
|
|
|
|
+
|
|
|
|
+ for (ii = 0; ii < NUM_SOFT_QUEUES; ii++)
|
|
|
|
+ skb_queue_purge(&adapter->priv->tx_queue[ii]);
|
|
|
|
+
|
|
|
|
+ /* Initialize device again */
|
|
|
|
+ sdio_claim_host(pfunction);
|
|
|
|
+
|
|
|
|
+ sdio_release_irq(pfunction);
|
|
|
|
+ rsi_reset_card(pfunction);
|
|
|
|
+
|
|
|
|
+ sdio_enable_func(pfunction);
|
|
|
|
+ rsi_setupcard(adapter);
|
|
|
|
+ rsi_init_sdio_slave_regs(adapter);
|
|
|
|
+ sdio_claim_irq(pfunction, rsi_handle_interrupt);
|
|
|
|
+ rsi_hal_device_init(adapter);
|
|
|
|
+
|
|
|
|
+ sdio_release_host(pfunction);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int rsi_restore(struct device *dev)
|
|
|
|
+{
|
|
|
|
+ struct sdio_func *pfunction = dev_to_sdio_func(dev);
|
|
|
|
+ struct rsi_hw *adapter = sdio_get_drvdata(pfunction);
|
|
|
|
+ struct rsi_common *common = adapter->priv;
|
|
|
|
+
|
|
|
|
+ rsi_dbg(INFO_ZONE, "SDIO Bus restore ======>\n");
|
|
|
|
+ common->hibernate_resume = true;
|
|
|
|
+ common->fsm_state = FSM_FW_NOT_LOADED;
|
|
|
|
+ common->iface_down = true;
|
|
|
|
+
|
|
|
|
+ adapter->sc_nvifs = 0;
|
|
|
|
+ ieee80211_restart_hw(adapter->hw);
|
|
|
|
+
|
|
|
|
+#ifdef CONFIG_RSI_WOW
|
|
|
|
+ common->wow_flags = 0;
|
|
|
|
+#endif
|
|
|
|
+ common->iface_down = false;
|
|
|
|
+
|
|
|
|
+ rsi_dbg(INFO_ZONE, "RSI module restored\n");
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
static const struct dev_pm_ops rsi_pm_ops = {
|
|
static const struct dev_pm_ops rsi_pm_ops = {
|
|
.suspend = rsi_suspend,
|
|
.suspend = rsi_suspend,
|
|
.resume = rsi_resume,
|
|
.resume = rsi_resume,
|
|
|
|
+ .freeze = rsi_freeze,
|
|
|
|
+ .thaw = rsi_thaw,
|
|
|
|
+ .restore = rsi_restore,
|
|
};
|
|
};
|
|
#endif
|
|
#endif
|
|
|
|
|