All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexandre Belloni <alexandre.belloni@bootlin.com>
To: Miquel Raynal <miquel.raynal@bootlin.com>
Cc: Alessandro Zummo <a.zummo@towertech.it>,
	Rob Herring <robh+dt@kernel.org>,
	devicetree@vger.kernel.org,
	Krzysztof Kozlowski <krzk+dt@kernel.org>,
	linux-renesas-soc@vger.kernel.org,
	Magnus Damm <magnus.damm@gmail.com>,
	Gareth Williams <gareth.williams.jx@renesas.com>,
	Phil Edworthy <phil.edworthy@renesas.com>,
	Geert Uytterhoeven <geert@linux-m68k.org>,
	Stephen Boyd <sboyd@kernel.org>,
	Michael Turquette <mturquette@baylibre.com>,
	linux-clk@vger.kernel.org,
	Milan Stevanovic <milan.stevanovic@se.com>,
	Jimmy Lalande <jimmy.lalande@se.com>,
	Pascal Eberhard <pascal.eberhard@se.com>,
	Thomas Petazzoni <thomas.petazzoni@bootlin.com>,
	Herve Codina <herve.codina@bootlin.com>,
	Clement Leger <clement.leger@bootlin.com>,
	linux-rtc@vger.kernel.org
Subject: Re: [PATCH 4/7] rtc: rzn1: Add alarm support
Date: Wed, 6 Apr 2022 11:10:17 +0200	[thread overview]
Message-ID: <Yk1Y+eaDkk1FFiLZ@mail.local> (raw)
In-Reply-To: <20220405184716.1578385-5-miquel.raynal@bootlin.com>

On 05/04/2022 20:47:13+0200, Miquel Raynal wrote:
> The RZN1 RTC can trigger an interrupt when reaching a particular date up
> to 7 days ahead. Bring support for this alarm.
> 
> One drawback though, the granularity is about a minute.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/rtc/rtc-rzn1.c | 108 +++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 108 insertions(+)
> 
> diff --git a/drivers/rtc/rtc-rzn1.c b/drivers/rtc/rtc-rzn1.c
> index 15c533333930..85c5a68944a0 100644
> --- a/drivers/rtc/rtc-rzn1.c
> +++ b/drivers/rtc/rtc-rzn1.c
> @@ -154,14 +154,110 @@ static int rzn1_rtc_set_time(struct device *dev, struct rtc_time *tm)
>  	return ret;
>  }
>  
> +static irqreturn_t rzn1_rtc_alarm_irq(int irq, void *dev_id)
> +{
> +	struct rzn1_rtc *rtc = dev_id;
> +
> +	rtc_update_irq(rtc->rtcdev, 1, RTC_AF | RTC_IRQF);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int rzn1_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
> +{
> +	struct rzn1_rtc *rtc = dev_get_drvdata(dev);
> +	u32 ctl1 = readl(rtc->base + RZN1_RTC_CTL1);
> +
> +	if (enable)
> +		ctl1 |= RZN1_RTC_CTL1_ALME;
> +	else
> +		ctl1 &= ~RZN1_RTC_CTL1_ALME;
> +
> +	writel(ctl1, rtc->base + RZN1_RTC_CTL1);
> +
> +	return 0;
> +}
> +
> +static int rzn1_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> +{
> +	struct rzn1_rtc *rtc = dev_get_drvdata(dev);
> +	struct rtc_time *tm = &alrm->time;
> +	unsigned int min, hour, wday, delta_days;
> +	u32 ctl1;
> +	int ret;
> +
> +	ret = rzn1_rtc_read_time(dev, tm);
> +	if (ret)
> +		return ret;
> +
> +	min = readl(rtc->base + RZN1_RTC_ALM);
> +	hour = readl(rtc->base + RZN1_RTC_ALH);
> +	wday = readl(rtc->base + RZN1_RTC_ALW);
> +
> +	tm->tm_sec = 0;
> +	tm->tm_min = bcd2bin(min);
> +	tm->tm_hour = bcd2bin(hour);
> +	delta_days = ((fls(wday) - 1) - tm->tm_wday + 7) % 7;
> +	tm->tm_wday = fls(wday) - 1;
> +	tm->tm_mday += delta_days;
> +	if (delta_days > rtc_month_days(tm->tm_mon, tm->tm_year)) {
> +		tm->tm_mday %= rtc_month_days(tm->tm_mon, tm->tm_year);
> +		tm->tm_mon++;
> +	}
> +	if (tm->tm_mon > 12) {
> +		tm->tm_mon %= 12;
> +		tm->tm_year++;
> +	}

I guess you could avoid having to handle rollover by making the
calculations on a time64_t and then convert back to a tm. I don't think
this would be much worse in terms of processing.

> +
> +	ctl1 = readl(rtc->base + RZN1_RTC_CTL1);
> +	alrm->enabled = !!(ctl1 & RZN1_RTC_CTL1_ALME);
> +
> +	return 0;
> +}
> +
> +static int rzn1_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> +{
> +	struct rzn1_rtc *rtc = dev_get_drvdata(dev);
> +	struct rtc_time *tm = &alrm->time, tm_now;
> +	unsigned long alarm, farest;
> +	unsigned int days_ahead, wday;
> +	int ret;
> +
> +	ret = rzn1_rtc_read_time(dev, &tm_now);
> +	if (ret)
> +		return ret;
> +
> +	/* We cannot set alarms more than one week ahead */
> +	farest = rtc_tm_to_time64(&tm_now) + (7 * 86400);
> +	alarm = rtc_tm_to_time64(tm);
> +	if (time_after(alarm, farest))
> +		return -EOPNOTSUPP;
> +

I would return -ERANGE

> +	/* Convert alarm day into week day */
> +	days_ahead = tm->tm_mday - tm_now.tm_mday;
> +	wday = (tm_now.tm_wday + days_ahead) % 7;
> +
> +	writel(bin2bcd(tm->tm_min), rtc->base + RZN1_RTC_ALM);
> +	writel(bin2bcd(tm->tm_hour), rtc->base + RZN1_RTC_ALH);
> +	writel(BIT(wday), rtc->base + RZN1_RTC_ALW);
> +
> +	rzn1_rtc_alarm_irq_enable(dev, alrm->enabled);
> +
> +	return 0;
> +}
> +
>  static const 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,
>  };
>  
>  static int rzn1_rtc_probe(struct platform_device *pdev)
>  {
>  	struct rzn1_rtc *rtc;
> +	int alarm_irq;
>  	int ret;
>  
>  	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
> @@ -178,12 +274,17 @@ static int rzn1_rtc_probe(struct platform_device *pdev)
>  	if (IS_ERR(rtc->base))
>  		return dev_err_probe(&pdev->dev, PTR_ERR(rtc->base), "Missing reg\n");
>  
> +	alarm_irq = platform_get_irq(pdev, 0);
> +	if (alarm_irq < 0)
> +		return dev_err_probe(&pdev->dev, alarm_irq, "Missing timer IRQ\n");
> +
>  	rtc->rtcdev = devm_rtc_allocate_device(&pdev->dev);
>  	if (IS_ERR(rtc->rtcdev))
>  		return PTR_ERR(rtc);
>  
>  	rtc->rtcdev->range_max = 3178591199UL; /* 100 years */
>  	rtc->rtcdev->ops = &rzn1_rtc_ops;
> +	set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->rtcdev->features);

You should probably clear RTC_FEATURE_UPDATE_INTERRUPT too.

>  
>  	ret = r9a06g032_sysctrl_enable_rtc(true);
>  	if (ret)
> @@ -206,6 +307,13 @@ static int rzn1_rtc_probe(struct platform_device *pdev)
>  	/* Enable counter operation */
>  	writel(0, rtc->base + RZN1_RTC_CTL2);
>  
> +	ret = devm_request_irq(&pdev->dev, alarm_irq, rzn1_rtc_alarm_irq, 0,
> +			       dev_name(&pdev->dev), rtc);
> +	if (ret) {
> +		dev_err(&pdev->dev, "RTC timer interrupt not available\n");
> +		goto disable_clk;
> +	}
> +
>  	ret = devm_rtc_register_device(rtc->rtcdev);
>  	if (ret) {
>  		dev_err(&pdev->dev, "Failed to register RTC\n");
> -- 
> 2.27.0
> 

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

  reply	other threads:[~2022-04-06 13:56 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-05 18:47 [PATCH 0/7] RZN1 RTC support Miquel Raynal
2022-04-05 18:47 ` [PATCH 1/7] dt-bindings: rtc: rzn1: Describe the RZN1 RTC Miquel Raynal
2022-04-07  7:37   ` Krzysztof Kozlowski
2022-04-07  9:21     ` Miquel Raynal
2022-04-05 18:47 ` [PATCH 2/7] soc: renesas: rzn1-sysc: Export a function to enable/disable the RTC Miquel Raynal
2022-04-06  7:00   ` Thomas Petazzoni
2022-04-06  7:43     ` Miquel Raynal
2022-04-06  8:32   ` Alexandre Belloni
2022-04-05 18:47 ` [PATCH 3/7] rtc: rzn1: Add new RTC driver Miquel Raynal
2022-04-06  8:50   ` Alexandre Belloni
2022-04-13 15:23     ` Miquel Raynal
2022-04-13 15:48       ` Alexandre Belloni
2022-04-14 11:19         ` Miquel Raynal
2022-04-05 18:47 ` [PATCH 4/7] rtc: rzn1: Add alarm support Miquel Raynal
2022-04-06  9:10   ` Alexandre Belloni [this message]
2022-04-05 18:47 ` [PATCH 5/7] rtc: rzn1: Add oscillator offset support Miquel Raynal
2022-04-05 18:47 ` [PATCH 6/7] MAINTAINERS: Add myself as maintainer of the RZN1 RTC driver Miquel Raynal
2022-04-11 15:22   ` Geert Uytterhoeven
2022-04-05 18:47 ` [PATCH 7/7] ARM: dts: r9a06g032: Describe the RTC Miquel Raynal
2022-04-11 15:32   ` Geert Uytterhoeven

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Yk1Y+eaDkk1FFiLZ@mail.local \
    --to=alexandre.belloni@bootlin.com \
    --cc=a.zummo@towertech.it \
    --cc=clement.leger@bootlin.com \
    --cc=devicetree@vger.kernel.org \
    --cc=gareth.williams.jx@renesas.com \
    --cc=geert@linux-m68k.org \
    --cc=herve.codina@bootlin.com \
    --cc=jimmy.lalande@se.com \
    --cc=krzk+dt@kernel.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-renesas-soc@vger.kernel.org \
    --cc=linux-rtc@vger.kernel.org \
    --cc=magnus.damm@gmail.com \
    --cc=milan.stevanovic@se.com \
    --cc=miquel.raynal@bootlin.com \
    --cc=mturquette@baylibre.com \
    --cc=pascal.eberhard@se.com \
    --cc=phil.edworthy@renesas.com \
    --cc=robh+dt@kernel.org \
    --cc=sboyd@kernel.org \
    --cc=thomas.petazzoni@bootlin.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.