diff options
author | Alexandre Belloni <alexandre.belloni@free-electrons.com> | 2015-07-31 05:39:51 -0400 |
---|---|---|
committer | Alexandre Belloni <alexandre.belloni@free-electrons.com> | 2015-09-05 07:19:09 -0400 |
commit | 11f67a8bbf65872c3e9edc70242420a8c314a860 (patch) | |
tree | f0966bbef87cadd2292f4ae6bba0e05a531960eb /drivers/rtc | |
parent | 202cc98acf96de1c3897194e1ed5ae1c80c8b0f3 (diff) |
rtc: at91rm9200: get and use slow clock
Commit dca1a4b5ff6e ("clk: at91: keep slow clk enabled to prevent system
hang") added a workaround for the slow clock as it is not properly handled
by its users.
Get and use the slow clock as it is necessary for the at91rm9200 rtc.
Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/rtc-at91rm9200.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index c4062d9f1bdd..cb62e214b52a 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c | |||
@@ -19,6 +19,7 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/bcd.h> | 21 | #include <linux/bcd.h> |
22 | #include <linux/clk.h> | ||
22 | #include <linux/completion.h> | 23 | #include <linux/completion.h> |
23 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
24 | #include <linux/ioctl.h> | 25 | #include <linux/ioctl.h> |
@@ -59,6 +60,7 @@ static bool suspended; | |||
59 | static DEFINE_SPINLOCK(suspended_lock); | 60 | static DEFINE_SPINLOCK(suspended_lock); |
60 | static unsigned long cached_events; | 61 | static unsigned long cached_events; |
61 | static u32 at91_rtc_imr; | 62 | static u32 at91_rtc_imr; |
63 | static struct clk *sclk; | ||
62 | 64 | ||
63 | static void at91_rtc_write_ier(u32 mask) | 65 | static void at91_rtc_write_ier(u32 mask) |
64 | { | 66 | { |
@@ -407,6 +409,16 @@ static int __init at91_rtc_probe(struct platform_device *pdev) | |||
407 | return -ENOMEM; | 409 | return -ENOMEM; |
408 | } | 410 | } |
409 | 411 | ||
412 | sclk = devm_clk_get(&pdev->dev, NULL); | ||
413 | if (IS_ERR(sclk)) | ||
414 | return PTR_ERR(sclk); | ||
415 | |||
416 | ret = clk_prepare_enable(sclk); | ||
417 | if (ret) { | ||
418 | dev_err(&pdev->dev, "Could not enable slow clock\n"); | ||
419 | return ret; | ||
420 | } | ||
421 | |||
410 | at91_rtc_write(AT91_RTC_CR, 0); | 422 | at91_rtc_write(AT91_RTC_CR, 0); |
411 | at91_rtc_write(AT91_RTC_MR, 0); /* 24 hour mode */ | 423 | at91_rtc_write(AT91_RTC_MR, 0); /* 24 hour mode */ |
412 | 424 | ||
@@ -420,7 +432,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev) | |||
420 | "at91_rtc", pdev); | 432 | "at91_rtc", pdev); |
421 | if (ret) { | 433 | if (ret) { |
422 | dev_err(&pdev->dev, "IRQ %d already in use.\n", irq); | 434 | dev_err(&pdev->dev, "IRQ %d already in use.\n", irq); |
423 | return ret; | 435 | goto err_clk; |
424 | } | 436 | } |
425 | 437 | ||
426 | /* cpu init code should really have flagged this device as | 438 | /* cpu init code should really have flagged this device as |
@@ -431,8 +443,10 @@ static int __init at91_rtc_probe(struct platform_device *pdev) | |||
431 | 443 | ||
432 | rtc = devm_rtc_device_register(&pdev->dev, pdev->name, | 444 | rtc = devm_rtc_device_register(&pdev->dev, pdev->name, |
433 | &at91_rtc_ops, THIS_MODULE); | 445 | &at91_rtc_ops, THIS_MODULE); |
434 | if (IS_ERR(rtc)) | 446 | if (IS_ERR(rtc)) { |
435 | return PTR_ERR(rtc); | 447 | ret = PTR_ERR(rtc); |
448 | goto err_clk; | ||
449 | } | ||
436 | platform_set_drvdata(pdev, rtc); | 450 | platform_set_drvdata(pdev, rtc); |
437 | 451 | ||
438 | /* enable SECEV interrupt in order to initialize at91_rtc_upd_rdy | 452 | /* enable SECEV interrupt in order to initialize at91_rtc_upd_rdy |
@@ -442,6 +456,11 @@ static int __init at91_rtc_probe(struct platform_device *pdev) | |||
442 | 456 | ||
443 | dev_info(&pdev->dev, "AT91 Real Time Clock driver.\n"); | 457 | dev_info(&pdev->dev, "AT91 Real Time Clock driver.\n"); |
444 | return 0; | 458 | return 0; |
459 | |||
460 | err_clk: | ||
461 | clk_disable_unprepare(sclk); | ||
462 | |||
463 | return ret; | ||
445 | } | 464 | } |
446 | 465 | ||
447 | /* | 466 | /* |
@@ -454,6 +473,8 @@ static int __exit at91_rtc_remove(struct platform_device *pdev) | |||
454 | AT91_RTC_SECEV | AT91_RTC_TIMEV | | 473 | AT91_RTC_SECEV | AT91_RTC_TIMEV | |
455 | AT91_RTC_CALEV); | 474 | AT91_RTC_CALEV); |
456 | 475 | ||
476 | clk_disable_unprepare(sclk); | ||
477 | |||
457 | return 0; | 478 | return 0; |
458 | } | 479 | } |
459 | 480 | ||