aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-snvs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc/rtc-snvs.c')
-rw-r--r--drivers/rtc/rtc-snvs.c39
1 files changed, 36 insertions, 3 deletions
diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c
index fa384fe28988..2cd8ffe5c698 100644
--- a/drivers/rtc/rtc-snvs.c
+++ b/drivers/rtc/rtc-snvs.c
@@ -17,6 +17,7 @@
17#include <linux/of_device.h> 17#include <linux/of_device.h>
18#include <linux/platform_device.h> 18#include <linux/platform_device.h>
19#include <linux/rtc.h> 19#include <linux/rtc.h>
20#include <linux/clk.h>
20 21
21/* These register offsets are relative to LP (Low Power) range */ 22/* These register offsets are relative to LP (Low Power) range */
22#define SNVS_LPCR 0x04 23#define SNVS_LPCR 0x04
@@ -39,6 +40,7 @@ struct snvs_rtc_data {
39 void __iomem *ioaddr; 40 void __iomem *ioaddr;
40 int irq; 41 int irq;
41 spinlock_t lock; 42 spinlock_t lock;
43 struct clk *clk;
42}; 44};
43 45
44static u32 rtc_read_lp_counter(void __iomem *ioaddr) 46static u32 rtc_read_lp_counter(void __iomem *ioaddr)
@@ -260,6 +262,18 @@ static int snvs_rtc_probe(struct platform_device *pdev)
260 if (data->irq < 0) 262 if (data->irq < 0)
261 return data->irq; 263 return data->irq;
262 264
265 data->clk = devm_clk_get(&pdev->dev, "snvs-rtc");
266 if (IS_ERR(data->clk)) {
267 data->clk = NULL;
268 } else {
269 ret = clk_prepare_enable(data->clk);
270 if (ret) {
271 dev_err(&pdev->dev,
272 "Could not prepare or enable the snvs clock\n");
273 return ret;
274 }
275 }
276
263 platform_set_drvdata(pdev, data); 277 platform_set_drvdata(pdev, data);
264 278
265 spin_lock_init(&data->lock); 279 spin_lock_init(&data->lock);
@@ -280,7 +294,7 @@ static int snvs_rtc_probe(struct platform_device *pdev)
280 if (ret) { 294 if (ret) {
281 dev_err(&pdev->dev, "failed to request irq %d: %d\n", 295 dev_err(&pdev->dev, "failed to request irq %d: %d\n",
282 data->irq, ret); 296 data->irq, ret);
283 return ret; 297 goto error_rtc_device_register;
284 } 298 }
285 299
286 data->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, 300 data->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
@@ -288,10 +302,16 @@ static int snvs_rtc_probe(struct platform_device *pdev)
288 if (IS_ERR(data->rtc)) { 302 if (IS_ERR(data->rtc)) {
289 ret = PTR_ERR(data->rtc); 303 ret = PTR_ERR(data->rtc);
290 dev_err(&pdev->dev, "failed to register rtc: %d\n", ret); 304 dev_err(&pdev->dev, "failed to register rtc: %d\n", ret);
291 return ret; 305 goto error_rtc_device_register;
292 } 306 }
293 307
294 return 0; 308 return 0;
309
310error_rtc_device_register:
311 if (data->clk)
312 clk_disable_unprepare(data->clk);
313
314 return ret;
295} 315}
296 316
297#ifdef CONFIG_PM_SLEEP 317#ifdef CONFIG_PM_SLEEP
@@ -302,21 +322,34 @@ static int snvs_rtc_suspend(struct device *dev)
302 if (device_may_wakeup(dev)) 322 if (device_may_wakeup(dev))
303 enable_irq_wake(data->irq); 323 enable_irq_wake(data->irq);
304 324
325 if (data->clk)
326 clk_disable_unprepare(data->clk);
327
305 return 0; 328 return 0;
306} 329}
307 330
308static int snvs_rtc_resume(struct device *dev) 331static int snvs_rtc_resume(struct device *dev)
309{ 332{
310 struct snvs_rtc_data *data = dev_get_drvdata(dev); 333 struct snvs_rtc_data *data = dev_get_drvdata(dev);
334 int ret;
311 335
312 if (device_may_wakeup(dev)) 336 if (device_may_wakeup(dev))
313 disable_irq_wake(data->irq); 337 disable_irq_wake(data->irq);
314 338
339 if (data->clk) {
340 ret = clk_prepare_enable(data->clk);
341 if (ret)
342 return ret;
343 }
344
315 return 0; 345 return 0;
316} 346}
317#endif 347#endif
318 348
319static SIMPLE_DEV_PM_OPS(snvs_rtc_pm_ops, snvs_rtc_suspend, snvs_rtc_resume); 349static const struct dev_pm_ops snvs_rtc_pm_ops = {
350 .suspend_noirq = snvs_rtc_suspend,
351 .resume_noirq = snvs_rtc_resume,
352};
320 353
321static const struct of_device_id snvs_dt_ids[] = { 354static const struct of_device_id snvs_dt_ids[] = {
322 { .compatible = "fsl,sec-v4.0-mon-rtc-lp", }, 355 { .compatible = "fsl,sec-v4.0-mon-rtc-lp", },