summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris BREZILLON <boris.brezillon@free-electrons.com>2014-09-23 16:41:07 +0200
committerNicolas Ferre <nicolas.ferre@atmel.com>2014-11-13 16:08:01 +0100
commita975f47f6e9a4e9762c81973cf2305003aa5b7dc (patch)
tree3087c457ca561f407dd86baa915f19b56643d134
parenta98250217997f3b8d47d21ffaedd39b32d1798eb (diff)
rtc: at91sam9: use clk API instead of relying on AT91_SLOW_CLOCK
The RTT block is using the slow clock which is accessible through the clk API. Use the clk API to retrieve, enable and get the slow clk rate instead of the AT91_SLOW_CLOCK macro (which hardcodes the slow clk rate). Doing this allows us to reference the clk thus preventing the CCF from disabling it during the "disable unused" phase. Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com> Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com> Acked-by: Johan Hovold <johan@kernel.org> Acked-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-rw-r--r--drivers/rtc/rtc-at91sam9.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index be9c28b9d057..abac38abd38e 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -23,6 +23,7 @@
#include <linux/io.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
+#include <linux/clk.h>
/*
* This driver uses two configurable hardware resources that live in the
@@ -61,8 +62,6 @@
#define AT91_RTT_ALMS (1 << 0) /* Real-time Alarm Status */
#define AT91_RTT_RTTINC (1 << 1) /* Real-time Timer Increment */
-#define AT91_SLOW_CLOCK 32768
-
/*
* We store ALARM_DISABLED in ALMV to record that no alarm is set.
* It's also the reset value for that field.
@@ -77,6 +76,7 @@ struct sam9_rtc {
struct regmap *gpbr;
unsigned int gpbr_offset;
int irq;
+ struct clk *sclk;
};
#define rtt_readl(rtc, field) \
@@ -328,6 +328,7 @@ static int at91_rtc_probe(struct platform_device *pdev)
struct sam9_rtc *rtc;
int ret, irq;
u32 mr;
+ unsigned int sclk_rate;
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
@@ -385,11 +386,27 @@ static int at91_rtc_probe(struct platform_device *pdev)
return -ENOMEM;
}
+ rtc->sclk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(rtc->sclk))
+ return PTR_ERR(rtc->sclk);
+
+ sclk_rate = clk_get_rate(rtc->sclk);
+ if (!sclk_rate || sclk_rate > AT91_RTT_RTPRES) {
+ dev_err(&pdev->dev, "Invalid slow clock rate\n");
+ return -EINVAL;
+ }
+
+ ret = clk_prepare_enable(rtc->sclk);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not enable slow clock\n");
+ return ret;
+ }
+
mr = rtt_readl(rtc, MR);
/* unless RTT is counting at 1 Hz, re-initialize it */
- if ((mr & AT91_RTT_RTPRES) != AT91_SLOW_CLOCK) {
- mr = AT91_RTT_RTTRST | (AT91_SLOW_CLOCK & AT91_RTT_RTPRES);
+ if ((mr & AT91_RTT_RTPRES) != sclk_rate) {
+ mr = AT91_RTT_RTTRST | (sclk_rate & AT91_RTT_RTPRES);
gpbr_writel(rtc, 0);
}
@@ -434,6 +451,9 @@ static int at91_rtc_remove(struct platform_device *pdev)
/* disable all interrupts */
rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN));
+ if (!IS_ERR(rtc->sclk))
+ clk_disable_unprepare(rtc->sclk);
+
return 0;
}