drivers/rtc/rtc-snvs: add clock support
[cascardo/linux.git] / drivers / rtc / rtc-snvs.c
index fa384fe..d4a6512 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/rtc.h>
+#include <linux/clk.h>
 
 /* These register offsets are relative to LP (Low Power) range */
 #define SNVS_LPCR              0x04
@@ -39,6 +40,7 @@ struct snvs_rtc_data {
        void __iomem *ioaddr;
        int irq;
        spinlock_t lock;
+       struct clk *clk;
 };
 
 static u32 rtc_read_lp_counter(void __iomem *ioaddr)
@@ -260,6 +262,18 @@ static int snvs_rtc_probe(struct platform_device *pdev)
        if (data->irq < 0)
                return data->irq;
 
+       data->clk = devm_clk_get(&pdev->dev, "snvs-rtc");
+       if (IS_ERR(data->clk)) {
+               data->clk = NULL;
+       } else {
+               ret = clk_prepare_enable(data->clk);
+               if (ret) {
+                       dev_err(&pdev->dev,
+                               "Could not prepare or enable the snvs clock\n");
+                       return ret;
+               }
+       }
+
        platform_set_drvdata(pdev, data);
 
        spin_lock_init(&data->lock);
@@ -280,7 +294,7 @@ static int snvs_rtc_probe(struct platform_device *pdev)
        if (ret) {
                dev_err(&pdev->dev, "failed to request irq %d: %d\n",
                        data->irq, ret);
-               return ret;
+               goto error_rtc_device_register;
        }
 
        data->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
@@ -288,10 +302,16 @@ static int snvs_rtc_probe(struct platform_device *pdev)
        if (IS_ERR(data->rtc)) {
                ret = PTR_ERR(data->rtc);
                dev_err(&pdev->dev, "failed to register rtc: %d\n", ret);
-               return ret;
+               goto error_rtc_device_register;
        }
 
        return 0;
+
+error_rtc_device_register:
+       if (data->clk)
+               clk_disable_unprepare(data->clk);
+
+       return ret;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -302,16 +322,26 @@ static int snvs_rtc_suspend(struct device *dev)
        if (device_may_wakeup(dev))
                enable_irq_wake(data->irq);
 
+       if (data->clk)
+               clk_disable_unprepare(data->clk);
+
        return 0;
 }
 
 static int snvs_rtc_resume(struct device *dev)
 {
        struct snvs_rtc_data *data = dev_get_drvdata(dev);
+       int ret;
 
        if (device_may_wakeup(dev))
                disable_irq_wake(data->irq);
 
+       if (data->clk) {
+               ret = clk_prepare_enable(data->clk);
+               if (ret)
+                       return ret;
+       }
+
        return 0;
 }
 #endif