diff options
Diffstat (limited to 'drivers/rtc/rtc-snvs.c')
-rw-r--r-- | drivers/rtc/rtc-snvs.c | 51 |
1 files changed, 45 insertions, 6 deletions
diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c index fa384fe28988..0479e807a776 100644 --- a/drivers/rtc/rtc-snvs.c +++ b/drivers/rtc/rtc-snvs.c @@ -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,21 +322,41 @@ 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 -static SIMPLE_DEV_PM_OPS(snvs_rtc_pm_ops, snvs_rtc_suspend, snvs_rtc_resume); +static const struct dev_pm_ops snvs_rtc_pm_ops = { + .suspend_noirq = snvs_rtc_suspend, + .resume_noirq = snvs_rtc_resume, +}; + +#define SNVS_RTC_PM_OPS (&snvs_rtc_pm_ops) + +#else + +#define SNVS_RTC_PM_OPS NULL + +#endif static const struct of_device_id snvs_dt_ids[] = { { .compatible = "fsl,sec-v4.0-mon-rtc-lp", }, @@ -327,8 +367,7 @@ MODULE_DEVICE_TABLE(of, snvs_dt_ids); static struct platform_driver snvs_rtc_driver = { .driver = { .name = "snvs_rtc", - .owner = THIS_MODULE, - .pm = &snvs_rtc_pm_ops, + .pm = SNVS_RTC_PM_OPS, .of_match_table = snvs_dt_ids, }, .probe = snvs_rtc_probe, |