Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Boris BREZILLON and committed by
Nicolas Ferre
a975f47f a9825021

+24 -4
+24 -4
drivers/rtc/rtc-at91sam9.c
··· 23 23 #include <linux/io.h> 24 24 #include <linux/mfd/syscon.h> 25 25 #include <linux/regmap.h> 26 + #include <linux/clk.h> 26 27 27 28 /* 28 29 * This driver uses two configurable hardware resources that live in the ··· 62 61 #define AT91_RTT_ALMS (1 << 0) /* Real-time Alarm Status */ 63 62 #define AT91_RTT_RTTINC (1 << 1) /* Real-time Timer Increment */ 64 63 65 - #define AT91_SLOW_CLOCK 32768 66 - 67 64 /* 68 65 * We store ALARM_DISABLED in ALMV to record that no alarm is set. 69 66 * It's also the reset value for that field. ··· 76 77 struct regmap *gpbr; 77 78 unsigned int gpbr_offset; 78 79 int irq; 80 + struct clk *sclk; 79 81 }; 80 82 81 83 #define rtt_readl(rtc, field) \ ··· 328 328 struct sam9_rtc *rtc; 329 329 int ret, irq; 330 330 u32 mr; 331 + unsigned int sclk_rate; 331 332 332 333 irq = platform_get_irq(pdev, 0); 333 334 if (irq < 0) { ··· 386 385 return -ENOMEM; 387 386 } 388 387 388 + rtc->sclk = devm_clk_get(&pdev->dev, NULL); 389 + if (IS_ERR(rtc->sclk)) 390 + return PTR_ERR(rtc->sclk); 391 + 392 + sclk_rate = clk_get_rate(rtc->sclk); 393 + if (!sclk_rate || sclk_rate > AT91_RTT_RTPRES) { 394 + dev_err(&pdev->dev, "Invalid slow clock rate\n"); 395 + return -EINVAL; 396 + } 397 + 398 + ret = clk_prepare_enable(rtc->sclk); 399 + if (ret) { 400 + dev_err(&pdev->dev, "Could not enable slow clock\n"); 401 + return ret; 402 + } 403 + 389 404 mr = rtt_readl(rtc, MR); 390 405 391 406 /* unless RTT is counting at 1 Hz, re-initialize it */ 392 - if ((mr & AT91_RTT_RTPRES) != AT91_SLOW_CLOCK) { 393 - mr = AT91_RTT_RTTRST | (AT91_SLOW_CLOCK & AT91_RTT_RTPRES); 407 + if ((mr & AT91_RTT_RTPRES) != sclk_rate) { 408 + mr = AT91_RTT_RTTRST | (sclk_rate & AT91_RTT_RTPRES); 394 409 gpbr_writel(rtc, 0); 395 410 } 396 411 ··· 450 433 451 434 /* disable all interrupts */ 452 435 rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN)); 436 + 437 + if (!IS_ERR(rtc->sclk)) 438 + clk_disable_unprepare(rtc->sclk); 453 439 454 440 return 0; 455 441 }