Commit a975f47f authored by Boris BREZILLON's avatar Boris BREZILLON Committed by Nicolas Ferre

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: default avatarBoris BREZILLON <boris.brezillon@free-electrons.com>
Acked-by: default avatarAlexandre Belloni <alexandre.belloni@free-electrons.com>
Acked-by: default avatarJohan Hovold <johan@kernel.org>
Acked-by: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarNicolas Ferre <nicolas.ferre@atmel.com>
parent a9825021
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/clk.h>
/* /*
* This driver uses two configurable hardware resources that live in the * This driver uses two configurable hardware resources that live in the
...@@ -61,8 +62,6 @@ ...@@ -61,8 +62,6 @@
#define AT91_RTT_ALMS (1 << 0) /* Real-time Alarm Status */ #define AT91_RTT_ALMS (1 << 0) /* Real-time Alarm Status */
#define AT91_RTT_RTTINC (1 << 1) /* Real-time Timer Increment */ #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. * We store ALARM_DISABLED in ALMV to record that no alarm is set.
* It's also the reset value for that field. * It's also the reset value for that field.
...@@ -77,6 +76,7 @@ struct sam9_rtc { ...@@ -77,6 +76,7 @@ struct sam9_rtc {
struct regmap *gpbr; struct regmap *gpbr;
unsigned int gpbr_offset; unsigned int gpbr_offset;
int irq; int irq;
struct clk *sclk;
}; };
#define rtt_readl(rtc, field) \ #define rtt_readl(rtc, field) \
...@@ -328,6 +328,7 @@ static int at91_rtc_probe(struct platform_device *pdev) ...@@ -328,6 +328,7 @@ static int at91_rtc_probe(struct platform_device *pdev)
struct sam9_rtc *rtc; struct sam9_rtc *rtc;
int ret, irq; int ret, irq;
u32 mr; u32 mr;
unsigned int sclk_rate;
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (irq < 0) {
...@@ -385,11 +386,27 @@ static int at91_rtc_probe(struct platform_device *pdev) ...@@ -385,11 +386,27 @@ static int at91_rtc_probe(struct platform_device *pdev)
return -ENOMEM; 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); mr = rtt_readl(rtc, MR);
/* unless RTT is counting at 1 Hz, re-initialize it */ /* unless RTT is counting at 1 Hz, re-initialize it */
if ((mr & AT91_RTT_RTPRES) != AT91_SLOW_CLOCK) { if ((mr & AT91_RTT_RTPRES) != sclk_rate) {
mr = AT91_RTT_RTTRST | (AT91_SLOW_CLOCK & AT91_RTT_RTPRES); mr = AT91_RTT_RTTRST | (sclk_rate & AT91_RTT_RTPRES);
gpbr_writel(rtc, 0); gpbr_writel(rtc, 0);
} }
...@@ -434,6 +451,9 @@ static int at91_rtc_remove(struct platform_device *pdev) ...@@ -434,6 +451,9 @@ static int at91_rtc_remove(struct platform_device *pdev)
/* disable all interrupts */ /* disable all interrupts */
rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN)); rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN));
if (!IS_ERR(rtc->sclk))
clk_disable_unprepare(rtc->sclk);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment