All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexandre Belloni <alexandre.belloni@bootlin.com>
To: "Daniel González Cabanelas" <dgcbueu@gmail.com>
Cc: a.zummo@towertech.it, linux-rtc@vger.kernel.org
Subject: Re: [PATCH 1/2] rtc: rs5c372: support alarms up to 1 week
Date: Tue, 12 Jan 2021 23:08:15 +0100	[thread overview]
Message-ID: <20210112220815.GK3654@piout.net> (raw)
In-Reply-To: <2876529.n6mMd1HPca@tool>

Hello,

On 23/11/2020 11:38:44+0100, Daniel González Cabanelas wrote:
> The Ricoh R2221x, R2223x, RS5C372, RV5C387A chips can handle 1 week
> alarms.
> 
> Read the "wday" alarm register and convert it to a date to support up 1
> week in our driver.
> 
> Signed-off-by: Daniel González Cabanelas <dgcbueu@gmail.com>
> ---
>  drivers/rtc/rtc-rs5c372.c | 48 ++++++++++++++++++++++++++++++++++-----
>  1 file changed, 42 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
> index 3bd6eaa0d..94b778c6e 100644
> --- a/drivers/rtc/rtc-rs5c372.c
> +++ b/drivers/rtc/rtc-rs5c372.c
> @@ -393,7 +393,9 @@ static int rs5c_read_alarm(struct device *dev, struct rtc_wkalrm *t)
>  {
>  	struct i2c_client	*client = to_i2c_client(dev);
>  	struct rs5c372		*rs5c = i2c_get_clientdata(client);
> -	int			status;
> +	int			status, wday_offs;
> +	struct rtc_time 	rtc;

You have a few spaces before tabs, please fix them.

> +	unsigned long 		alarm_secs;
>  
>  	status = rs5c_get_regs(rs5c);
>  	if (status < 0)
> @@ -403,6 +405,30 @@ static int rs5c_read_alarm(struct device *dev, struct rtc_wkalrm *t)
>  	t->time.tm_sec = 0;
>  	t->time.tm_min = bcd2bin(rs5c->regs[RS5C_REG_ALARM_A_MIN] & 0x7f);
>  	t->time.tm_hour = rs5c_reg2hr(rs5c, rs5c->regs[RS5C_REG_ALARM_A_HOURS]);
> +	t->time.tm_wday = ffs(rs5c->regs[RS5C_REG_ALARM_A_WDAY] & 0x7f) - 1;
> +
> +	/* determine the day, month and year based on alarm wday, taking as a
> +	 * reference the current time from the rtc
> +	 */
> +	status = rs5c372_rtc_read_time(dev, &rtc);
> +	if (status < 0)
> +		return status;
> +
> +	wday_offs = t->time.tm_wday - rtc.tm_wday;

Note that you can not rely on tm_wday being set correctly. The core will
not (currently) enforce that and most tools jut pass a bogus value or 0.
So you need to calculate wday in rs5c372_rtc_set_time.
I'm currently working on a way for the drivers to ask the core to ensure
wday is correct.

> +	alarm_secs = mktime64(rtc.tm_year + 1900,
> +			      rtc.tm_mon + 1,
> +			      rtc.tm_mday + wday_offs,
> +			      t->time.tm_hour,
> +			      t->time.tm_min,
> +			      t->time.tm_sec);
> +
> +	if (wday_offs < 0 || (wday_offs == 0 &&
> +			      (t->time.tm_hour < rtc.tm_hour ||
> +			       (t->time.tm_hour == rtc.tm_hour &&
> +				t->time.tm_min <= rtc.tm_min))))
> +		alarm_secs += 7 * 86400;
> +
> +	rtc_time64_to_tm(alarm_secs, &t->time);
>  
>  	/* ... and status */
>  	t->enabled = !!(rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE);
> @@ -417,12 +443,20 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t)
>  	struct rs5c372		*rs5c = i2c_get_clientdata(client);
>  	int			status, addr, i;
>  	unsigned char		buf[3];
> +	struct rtc_time 	rtc_tm;
> +	unsigned long 		rtc_secs, alarm_secs;
>  
> -	/* only handle up to 24 hours in the future, like RTC_ALM_SET */
> -	if (t->time.tm_mday != -1
> -			|| t->time.tm_mon != -1
> -			|| t->time.tm_year != -1)
> +	/* chip only can handle alarms up to one week in the future*/
> +	status = rs5c372_rtc_read_time(dev, &rtc_tm);
> +	if (status)
> +		return status;
> +	rtc_secs = rtc_tm_to_time64(&rtc_tm);
> +	alarm_secs = rtc_tm_to_time64(&t->time);
> +	if (alarm_secs >= rtc_secs + 7 * 86400) {
> +		dev_err(dev, "%s: alarm maximum is one week in the future (%d)\n",
> +			__func__, status);

Please avoid adding an error message. It will not be read anyway.

>  		return -EINVAL;

Maybe it is a good opportunity to change to -ERANGE?

> +	}
>  
>  	/* REVISIT: round up tm_sec */
>  
> @@ -443,7 +477,9 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t)
>  	/* set alarm */
>  	buf[0] = bin2bcd(t->time.tm_min);
>  	buf[1] = rs5c_hr2reg(rs5c, t->time.tm_hour);
> -	buf[2] = 0x7f;	/* any/all days */
> +	/* each bit is the day of the week, 0x7f means all days */
> +	buf[2] = (t->time.tm_wday >= 0 && t->time.tm_wday < 7) ?
> +		  BIT(t->time.tm_wday) : 0x7f;

Here, you also need to calculate buf[2] from t->time.tm_mday instead of
relying on t->time.tm_wday.


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

  reply	other threads:[~2021-01-12 22:08 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-23 10:38 [PATCH 1/2] rtc: rs5c372: support alarms up to 1 week Daniel González Cabanelas
2021-01-12 22:08 ` Alexandre Belloni [this message]
2021-03-08 10:58   ` Daniel González Cabanelas

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=20210112220815.GK3654@piout.net \
    --to=alexandre.belloni@bootlin.com \
    --cc=a.zummo@towertech.it \
    --cc=dgcbueu@gmail.com \
    --cc=linux-rtc@vger.kernel.org \
    /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.