When using the SCMP mode instead of SUBU, this RTC can also support other input frequencies than 32768Hz. Also, upcoming SoCs will only support SCMP. Signed-off-by: Wolfram Sang <wsa+renesas@xxxxxxxxxxxxxxxxxxxx> --- drivers/rtc/rtc-rzn1.c | 43 ++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/drivers/rtc/rtc-rzn1.c b/drivers/rtc/rtc-rzn1.c index e3733534d409..f8c9308817ae 100644 --- a/drivers/rtc/rtc-rzn1.c +++ b/drivers/rtc/rtc-rzn1.c @@ -12,6 +12,7 @@ */ #include <linux/bcd.h> +#include <linux/clk.h> #include <linux/init.h> #include <linux/iopoll.h> #include <linux/module.h> @@ -22,7 +23,6 @@ #include <linux/spinlock.h> #define RZN1_RTC_CTL0 0x00 -#define RZN1_RTC_CTL0_SLSB_SUBU 0 #define RZN1_RTC_CTL0_SLSB_SCMP BIT(4) #define RZN1_RTC_CTL0_AMPM BIT(5) #define RZN1_RTC_CTL0_CE BIT(7) @@ -49,6 +49,8 @@ #define RZN1_RTC_SUBU_DEV BIT(7) #define RZN1_RTC_SUBU_DECR BIT(6) +#define RZN1_RTC_SCMP 0x3c + #define RZN1_RTC_ALM 0x40 #define RZN1_RTC_ALH 0x44 #define RZN1_RTC_ALW 0x48 @@ -356,19 +358,20 @@ static int rzn1_rtc_set_offset(struct device *dev, long offset) return 0; } -static const struct rtc_class_ops rzn1_rtc_ops = { +static struct rtc_class_ops rzn1_rtc_ops = { .read_time = rzn1_rtc_read_time, .set_time = rzn1_rtc_set_time, .read_alarm = rzn1_rtc_read_alarm, .set_alarm = rzn1_rtc_set_alarm, .alarm_irq_enable = rzn1_rtc_alarm_irq_enable, - .read_offset = rzn1_rtc_read_offset, - .set_offset = rzn1_rtc_set_offset, }; static int rzn1_rtc_probe(struct platform_device *pdev) { struct rzn1_rtc *rtc; + struct clk *xtal; + unsigned long rate; + u32 use_scmp = 0; int irq; int ret; @@ -402,12 +405,32 @@ static int rzn1_rtc_probe(struct platform_device *pdev) if (ret < 0) return ret; - /* - * Ensure the clock counter is enabled. - * Set 24-hour mode and possible oscillator offset compensation in SUBU mode. - */ - writel(RZN1_RTC_CTL0_CE | RZN1_RTC_CTL0_AMPM | RZN1_RTC_CTL0_SLSB_SUBU, - rtc->base + RZN1_RTC_CTL0); + /* Only switch to scmp if we have an xtal clock with a valid rate and != 32768 */ + xtal = devm_clk_get_optional(&pdev->dev, "xtal"); + if (IS_ERR(xtal)) { + ret = PTR_ERR(xtal); + goto dis_runtime_pm; + } else if (xtal) { + rate = clk_get_rate(xtal); + + if (rate < 32000 || rate > BIT(22)) { + ret = -EOPNOTSUPP; + goto dis_runtime_pm; + } + + if (rate != 32768) + use_scmp = RZN1_RTC_CTL0_SLSB_SCMP; + } + + if (use_scmp) { + writel(rate - 1, rtc->base + RZN1_RTC_SCMP); + } else { + rzn1_rtc_ops.read_offset = rzn1_rtc_read_offset; + rzn1_rtc_ops.set_offset = rzn1_rtc_set_offset; + } + + /* Ensure clock counter is enabled. Set 24-hour mode and SUBU or SCMP mode */ + writel(RZN1_RTC_CTL0_CE | RZN1_RTC_CTL0_AMPM | use_scmp, rtc->base + RZN1_RTC_CTL0); /* Disable all interrupts */ writel(0, rtc->base + RZN1_RTC_CTL1); -- 2.47.2