+#ifdef CONFIG_PM
+/* This implementation assumes the devices remains powered on its VDDVARIO
+ * pins during suspend. */
+
+/* TODO: implement freeze/thaw callbacks for hibernation.*/
+
+static int smsc911x_suspend(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct smsc911x_data *pdata = netdev_priv(ndev);
+
+ /* enable wake on LAN, energy detection and the external PME
+ * signal. */
+ smsc911x_reg_write(pdata, PMT_CTRL,
+ PMT_CTRL_PM_MODE_D1_ | PMT_CTRL_WOL_EN_ |
+ PMT_CTRL_ED_EN_ | PMT_CTRL_PME_EN_);
+
+ return 0;
+}
+
+static int smsc911x_resume(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct smsc911x_data *pdata = netdev_priv(ndev);
+ unsigned int to = 100;
+
+ /* Note 3.11 from the datasheet:
+ * "When the LAN9220 is in a power saving state, a write of any
+ * data to the BYTE_TEST register will wake-up the device."
+ */
+ smsc911x_reg_write(pdata, BYTE_TEST, 0);
+
+ /* poll the READY bit in PMT_CTRL. Any other access to the device is
+ * forbidden while this bit isn't set. Try for 100ms and return -EIO
+ * if it failed. */
+ while (!(smsc911x_reg_read(pdata, PMT_CTRL) & PMT_CTRL_READY_) && --to)
+ udelay(1000);
+
+ return (to == 0) ? -EIO : 0;
+}
+
+static const struct dev_pm_ops smsc911x_pm_ops = {
+ .suspend = smsc911x_suspend,
+ .resume = smsc911x_resume,
+};
+
+#define SMSC911X_PM_OPS (&smsc911x_pm_ops)
+
+#else
+#define SMSC911X_PM_OPS NULL
+#endif
+