#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
+#include <linux/pm_runtime.h>
 
 /* Register offsets for the I2C device. */
 #define CDNS_I2C_CR_OFFSET             0x00 /* Control Register, RW */
                                         CDNS_I2C_IXR_COMP)
 
 #define CDNS_I2C_TIMEOUT               msecs_to_jiffies(1000)
+/* timeout for pm runtime autosuspend */
+#define CNDS_I2C_PM_TIMEOUT            1000    /* ms */
 
 #define CDNS_I2C_FIFO_DEPTH            16
 /* FIFO depth at which the DATA interrupt occurs */
  * @quirks:            flag for broken hold bit usage in r1p10
  */
 struct cdns_i2c {
+       struct device           *dev;
        void __iomem *membase;
        struct i2c_adapter adap;
        struct i2c_msg *p_msg;
        struct cdns_i2c *id = adap->algo_data;
        bool hold_quirk;
 
+       ret = pm_runtime_get_sync(id->dev);
+       if (ret < 0)
+               return ret;
        /* Check if the bus is free */
-       if (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) & CDNS_I2C_SR_BA)
-               return -EAGAIN;
+       if (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) & CDNS_I2C_SR_BA) {
+               ret = -EAGAIN;
+               goto out;
+       }
 
        hold_quirk = !!(id->quirks & CDNS_I2C_BROKEN_HOLD_BIT);
        /*
                        if (msgs[count].flags & I2C_M_RD) {
                                dev_warn(adap->dev.parent,
                                         "Can't do repeated start after a receive message\n");
-                               return -EOPNOTSUPP;
+                               ret = -EOPNOTSUPP;
+                               goto out;
                        }
                }
                id->bus_hold_flag = 1;
 
                ret = cdns_i2c_process_msg(id, msgs, adap);
                if (ret)
-                       return ret;
+                       goto out;
 
                /* Report the other error interrupts to application */
                if (id->err_status) {
                        cdns_i2c_master_reset(adap);
 
-                       if (id->err_status & CDNS_I2C_IXR_NACK)
-                               return -ENXIO;
-
-                       return -EIO;
+                       if (id->err_status & CDNS_I2C_IXR_NACK) {
+                               ret = -ENXIO;
+                               goto out;
+                       }
+                       ret = -EIO;
+                       goto out;
                }
        }
 
-       return num;
+       ret = num;
+out:
+       pm_runtime_mark_last_busy(id->dev);
+       pm_runtime_put_autosuspend(id->dev);
+       return ret;
 }
 
 /**
  *
  * Return: 0 always
  */
-static int __maybe_unused cdns_i2c_suspend(struct device *_dev)
+static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev)
 {
-       struct platform_device *pdev = container_of(_dev,
-                       struct platform_device, dev);
+       struct platform_device *pdev = to_platform_device(dev);
        struct cdns_i2c *xi2c = platform_get_drvdata(pdev);
 
        clk_disable(xi2c->clk);
  *
  * Return: 0 on success and error value on error
  */
-static int __maybe_unused cdns_i2c_resume(struct device *_dev)
+static int __maybe_unused cdns_i2c_runtime_resume(struct device *dev)
 {
-       struct platform_device *pdev = container_of(_dev,
-                       struct platform_device, dev);
+       struct platform_device *pdev = to_platform_device(dev);
        struct cdns_i2c *xi2c = platform_get_drvdata(pdev);
        int ret;
 
        ret = clk_enable(xi2c->clk);
        if (ret) {
-               dev_err(_dev, "Cannot enable clock.\n");
+               dev_err(dev, "Cannot enable clock.\n");
                return ret;
        }
 
        return 0;
 }
 
-static SIMPLE_DEV_PM_OPS(cdns_i2c_dev_pm_ops, cdns_i2c_suspend,
-                        cdns_i2c_resume);
+static const struct dev_pm_ops cdns_i2c_dev_pm_ops = {
+       SET_RUNTIME_PM_OPS(cdns_i2c_runtime_suspend,
+                          cdns_i2c_runtime_resume, NULL)
+};
 
 static const struct cdns_platform_data r1p10_i2c_def = {
        .quirks = CDNS_I2C_BROKEN_HOLD_BIT,
        if (!id)
                return -ENOMEM;
 
+       id->dev = &pdev->dev;
        platform_set_drvdata(pdev, id);
 
        match = of_match_node(cdns_i2c_of_match, pdev->dev.of_node);
                return PTR_ERR(id->clk);
        }
        ret = clk_prepare_enable(id->clk);
-       if (ret) {
+       if (ret)
                dev_err(&pdev->dev, "Unable to enable clock.\n");
-               return ret;
-       }
+
+       pm_runtime_enable(id->dev);
+       pm_runtime_set_autosuspend_delay(id->dev, CNDS_I2C_PM_TIMEOUT);
+       pm_runtime_use_autosuspend(id->dev);
+       pm_runtime_set_active(id->dev);
+
        id->clk_rate_change_nb.notifier_call = cdns_i2c_clk_notifier_cb;
        if (clk_notifier_register(id->clk, &id->clk_rate_change_nb))
                dev_warn(&pdev->dev, "Unable to register clock notifier.\n");
 
 err_clk_dis:
        clk_disable_unprepare(id->clk);
+       pm_runtime_set_suspended(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
        return ret;
 }
 
        i2c_del_adapter(&id->adap);
        clk_notifier_unregister(id->clk, &id->clk_rate_change_nb);
        clk_disable_unprepare(id->clk);
+       pm_runtime_disable(&pdev->dev);
 
        return 0;
 }