};
 MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids);
 
+#ifdef CONFIG_PM
+
+static int wil6210_suspend(struct device *dev, bool is_runtime)
+{
+       int rc = 0;
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct wil6210_priv *wil = pci_get_drvdata(pdev);
+
+       wil_dbg_pm(wil, "%s(%s)\n", __func__,
+                  is_runtime ? "runtime" : "system");
+
+       rc = wil_can_suspend(wil, is_runtime);
+       if (rc)
+               goto out;
+
+       rc = wil_suspend(wil, is_runtime);
+       if (rc)
+               goto out;
+
+       /* TODO: how do I bring card in low power state? */
+
+       /* disable bus mastering */
+       pci_clear_master(pdev);
+       /* PCI will call pci_save_state(pdev) and pci_prepare_to_sleep(pdev) */
+
+out:
+       return rc;
+}
+
+static int wil6210_resume(struct device *dev, bool is_runtime)
+{
+       int rc = 0;
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct wil6210_priv *wil = pci_get_drvdata(pdev);
+
+       wil_dbg_pm(wil, "%s(%s)\n", __func__,
+                  is_runtime ? "runtime" : "system");
+
+       /* allow master */
+       pci_set_master(pdev);
+
+       rc = wil_resume(wil, is_runtime);
+       if (rc)
+               pci_clear_master(pdev);
+
+       return rc;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int wil6210_pm_suspend(struct device *dev)
+{
+       return wil6210_suspend(dev, false);
+}
+
+static int wil6210_pm_resume(struct device *dev)
+{
+       return wil6210_resume(dev, false);
+}
+#endif /* CONFIG_PM_SLEEP */
+
+#endif /* CONFIG_PM */
+
+static const struct dev_pm_ops wil6210_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(wil6210_pm_suspend, wil6210_pm_resume)
+};
+
 static struct pci_driver wil6210_driver = {
        .probe          = wil_pcie_probe,
        .remove         = wil_pcie_remove,
        .id_table       = wil6210_pcie_ids,
        .name           = WIL_NAME,
+       .driver         = {
+               .pm = &wil6210_pm_ops,
+       },
 };
 
 static int __init wil6210_driver_init(void)
 
--- /dev/null
+/*
+ * Copyright (c) 2014 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "wil6210.h"
+
+int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime)
+{
+       int rc = 0;
+       struct wireless_dev *wdev = wil->wdev;
+
+       wil_dbg_pm(wil, "%s(%s)\n", __func__,
+                  is_runtime ? "runtime" : "system");
+
+       switch (wdev->iftype) {
+       case NL80211_IFTYPE_MONITOR:
+       case NL80211_IFTYPE_STATION:
+       case NL80211_IFTYPE_P2P_CLIENT:
+               break;
+       /* AP-like interface - can't suspend */
+       default:
+               wil_dbg_pm(wil, "AP-like interface\n");
+               rc = -EBUSY;
+               break;
+       }
+
+       wil_dbg_pm(wil, "%s(%s) => %s (%d)\n", __func__,
+                  is_runtime ? "runtime" : "system", rc ? "No" : "Yes", rc);
+
+       return rc;
+}
+
+int wil_suspend(struct wil6210_priv *wil, bool is_runtime)
+{
+       int rc = 0;
+       struct net_device *ndev = wil_to_ndev(wil);
+
+       wil_dbg_pm(wil, "%s(%s)\n", __func__,
+                  is_runtime ? "runtime" : "system");
+
+       /* if netif up, hardware is alive, shut it down */
+       if (ndev->flags & IFF_UP) {
+               rc = wil_down(wil);
+               if (rc) {
+                       wil_err(wil, "wil_down : %d\n", rc);
+                       goto out;
+               }
+       }
+
+       if (wil->platform_ops.suspend)
+               rc = wil->platform_ops.suspend(wil->platform_handle);
+
+out:
+       wil_dbg_pm(wil, "%s(%s) => %d\n", __func__,
+                  is_runtime ? "runtime" : "system", rc);
+       return rc;
+}
+
+int wil_resume(struct wil6210_priv *wil, bool is_runtime)
+{
+       int rc = 0;
+       struct net_device *ndev = wil_to_ndev(wil);
+
+       wil_dbg_pm(wil, "%s(%s)\n", __func__,
+                  is_runtime ? "runtime" : "system");
+
+       if (wil->platform_ops.resume) {
+               rc = wil->platform_ops.resume(wil->platform_handle);
+               if (rc) {
+                       wil_err(wil, "platform_ops.resume : %d\n", rc);
+                       goto out;
+               }
+       }
+
+       /* if netif up, bring hardware up
+        * During open(), IFF_UP set after actual device method
+        * invocation. This prevent recursive call to wil_up()
+        */
+       if (ndev->flags & IFF_UP)
+               rc = wil_up(wil);
+
+out:
+       wil_dbg_pm(wil, "%s(%s) => %d\n", __func__,
+                  is_runtime ? "runtime" : "system", rc);
+       return rc;
+}
 
 #define wil_dbg_txrx(wil, fmt, arg...) wil_dbg(wil, "DBG[TXRX]" fmt, ##arg)
 #define wil_dbg_wmi(wil, fmt, arg...) wil_dbg(wil, "DBG[ WMI]" fmt, ##arg)
 #define wil_dbg_misc(wil, fmt, arg...) wil_dbg(wil, "DBG[MISC]" fmt, ##arg)
+#define wil_dbg_pm(wil, fmt, arg...) wil_dbg(wil, "DBG[ PM ]" fmt, ##arg)
 
 /* target operations */
 /* register read */
 int wil_ioctl(struct wil6210_priv *wil, void __user *data, int cmd);
 int wil_request_firmware(struct wil6210_priv *wil, const char *name);
 
+int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime);
+int wil_suspend(struct wil6210_priv *wil, bool is_runtime);
+int wil_resume(struct wil6210_priv *wil, bool is_runtime);
+
 #endif /* __WIL6210_H__ */