canfd:ipms:add canfd runtime PM ops
authorWilliam Qiu <william.qiu@starfivetech.com>
Fri, 21 Oct 2022 02:13:13 +0000 (10:13 +0800)
committermason.huo <mason.huo@starfivetech.com>
Thu, 27 Oct 2022 05:56:39 +0000 (13:56 +0800)
add canfd runtime PM ops.

Signed-off-by: William Qiu <william.qiu@starfivetech.com>
drivers/net/can/ipms_canfd.c

index 6e0a816..7f12bed 100644 (file)
@@ -697,6 +697,8 @@ static int canfd_driver_close(struct net_device *ndev)
        free_irq(ndev->irq, ndev);
        close_candev(ndev);
 
+       pm_runtime_put(priv->dev);
+
        return 0;
 }
 
@@ -955,6 +957,12 @@ static int canfd_driver_open(struct net_device *ndev)
        struct ipms_canfd_priv *priv = netdev_priv(ndev);
        int ret;
 
+       ret = pm_runtime_get_sync(priv->dev);
+       if (ret < 0) {
+               dev_err(priv->dev, " %s: pm_runtime_get failed\n", __func__);
+               goto err;
+       }
+
        /* Set chip into reset mode */
        ret = set_reset_mode(ndev);
        if (ret) {
@@ -987,6 +995,8 @@ static int canfd_driver_open(struct net_device *ndev)
 
 exit_can_start:
        free_irq(ndev->irq, ndev);
+err:
+       pm_runtime_put(priv->dev);
 exit_irq:
        close_candev(ndev);
        return ret;
@@ -1101,6 +1111,9 @@ static int canfd_driver_probe(struct platform_device *pdev)
        priv->reg_base = addr;
        priv->write_reg = canfd_write_reg_le;
        priv->read_reg = canfd_read_reg_le;
+
+       pm_runtime_enable(&pdev->dev);
+
        priv->can_clk = devm_clk_get(&pdev->dev, "core_clk");
        if (IS_ERR(priv->can_clk)) {
                dev_err(&pdev->dev, "Device clock not found.\n");
@@ -1150,6 +1163,7 @@ static int canfd_driver_remove(struct platform_device *pdev)
 
        reset_control_assert(priv->resets);
        clk_bulk_disable_unprepare(priv->nr_clks, priv->clks);
+       pm_runtime_disable(&pdev->dev);
 
        unregister_candev(ndev);
        netif_napi_del(&priv->napi);
@@ -1158,6 +1172,41 @@ static int canfd_driver_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int canfd_runtime_suspend(struct device *dev)
+{
+       struct ipms_canfd_priv *priv = dev_get_drvdata(dev);
+
+       reset_control_assert(priv->resets);
+       clk_bulk_disable_unprepare(priv->nr_clks, priv->clks);
+
+       return 0;
+}
+
+static int canfd_runtime_resume(struct device *dev)
+{
+       struct ipms_canfd_priv *priv = dev_get_drvdata(dev);
+       int ret;
+
+       ret = clk_bulk_prepare_enable(priv->nr_clks, priv->clks);
+       if (ret) {
+               dev_err(dev, "Failed to  prepare_enable clk\n");
+               return ret;
+       }
+
+       ret = reset_control_deassert(priv->resets);
+       if (ret) {
+               dev_err(dev, "Failed to deassert reset\n");
+               return ret;
+       }
+
+       return 0;
+}
+#endif
+
+static UNIVERSAL_DEV_PM_OPS(canfd_pm_ops, canfd_runtime_suspend,
+                           canfd_runtime_resume, NULL);
+
 static const struct of_device_id canfd_of_match[] = {
        { .compatible = "ipms,can" },
        { }
@@ -1169,6 +1218,7 @@ static struct platform_driver can_driver = {
        .remove         = canfd_driver_remove,
        .driver = {
                .name  = DRIVER_NAME,
+               .pm    = &canfd_pm_ops,
                .of_match_table = canfd_of_match,
        },
 };