The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: Alexandre Belloni <alexandre.belloni@bootlin.com>
To: Markus Probst <markus.probst@posteo.de>
Cc: "Rob Herring" <robh@kernel.org>,
	"Krzysztof Kozlowski" <krzk+dt@kernel.org>,
	"Conor Dooley" <conor+dt@kernel.org>,
	"Uwe Kleine-König" <uwe@kleine-koenig.org>,
	"Andrew Lunn" <andrew@lunn.ch>,
	"Gregory Clement" <gregory.clement@bootlin.com>,
	"Sebastian Hesselbarth" <sebastian.hesselbarth@gmail.com>,
	"Michael Langer" <michael.brainbug.langer@googlemail.com>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"Linus Walleij" <linusw@kernel.org>,
	linux-arm-kernel@lists.infradead.org, linux-rtc@vger.kernel.org,
	devicetree@vger.kernel.org, linux-gpio@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH v5 4/6] rtc: s35390a: force 24-hour mode
Date: Thu, 20 Aug 2026 17:25:56 +0200	[thread overview]
Message-ID: <20260820152556c6da4fce@mail.local> (raw)
In-Reply-To: <20260819232634fd70f621@mail.local>

On 20/08/2026 01:26:34+0200, Alexandre Belloni wrote:
> On 19/08/2026 22:57:13+0000, Markus Probst wrote:
> > On Thu, 2026-08-20 at 00:20 +0200, Alexandre Belloni wrote:
> > > On 19/08/2026 22:05:56+0000, Markus Probst wrote:
> > > > Instead of trying to remember the current 12/24-hour mode, which could
> > > > result in time corruption if out of sync, we force the use of the 24-hour
> > > > mode. Set to 24-hour mode if in 12-hour mode on startup and assume
> > > > 24-hour mode. The 24-hour mode is already forced on reset.
> > > > 
> > > > Signed-off-by: Markus Probst <markus.probst@posteo.de>
> > > > ---
> > > >  drivers/rtc/rtc-s35390a.c | 67 +++++++++++++++++++++--------------------------
> > > >  1 file changed, 30 insertions(+), 37 deletions(-)
> > > > 
> > > > diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c
> > > > index 575bb256eb25..b34a3f7e8476 100644
> > > > --- a/drivers/rtc/rtc-s35390a.c
> > > > +++ b/drivers/rtc/rtc-s35390a.c
> > > > @@ -64,7 +64,6 @@ MODULE_DEVICE_TABLE(of, s35390a_of_match);
> > > >  
> > > >  struct s35390a {
> > > >  	struct i2c_client *client[8];
> > > > -	int twentyfourhour;
> > > >  };
> > > >  
> > > >  static int s35390a_set_reg(struct s35390a *s35390a, int reg, u8  *buf, int len)
> > > > @@ -181,31 +180,6 @@ static int s35390a_disable_test_mode(struct s35390a *s35390a)
> > > >  	return s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, buf, sizeof(buf));
> > > >  }
> > > >  
> > > > -static char s35390a_hr2reg(struct s35390a *s35390a, int hour)
> > > > -{
> > > > -	if (s35390a->twentyfourhour)
> > > > -		return bin2bcd(hour);
> > > > -
> > > > -	if (hour < 12)
> > > > -		return bin2bcd(hour);
> > > > -
> > > > -	return 0x40 | bin2bcd(hour - 12);
> > > > -}
> > > > -
> > > > -static int s35390a_reg2hr(struct s35390a *s35390a, char reg)
> > > > -{
> > > > -	unsigned hour;
> > > > -
> > > > -	if (s35390a->twentyfourhour)
> > > > -		return bcd2bin(reg & 0x3f);
> > > > -
> > > > -	hour = bcd2bin(reg & 0x3f);
> > > > -	if (reg & 0x40)
> > > > -		hour += 12;
> > > > -
> > > > -	return hour;
> > > > -}
> > > > -
> > > >  static int s35390a_rtc_set_time(struct device *dev, struct rtc_time *tm)
> > > >  {
> > > >  	struct i2c_client *client = to_i2c_client(dev);
> > > > @@ -225,7 +199,7 @@ static int s35390a_rtc_set_time(struct device *dev, struct rtc_time *tm)
> > > >  	buf[S35390A_BYTE_MONTH] = bin2bcd(tm->tm_mon + 1);
> > > >  	buf[S35390A_BYTE_DAY] = bin2bcd(tm->tm_mday);
> > > >  	buf[S35390A_BYTE_WDAY] = bin2bcd(tm->tm_wday);
> > > > -	buf[S35390A_BYTE_HOURS] = s35390a_hr2reg(s35390a, tm->tm_hour);
> > > > +	buf[S35390A_BYTE_HOURS] = bin2bcd(tm->tm_hour);
> > > >  	buf[S35390A_BYTE_MINS] = bin2bcd(tm->tm_min);
> > > >  	buf[S35390A_BYTE_SECS] = bin2bcd(tm->tm_sec);
> > > >  
> > > > @@ -256,7 +230,7 @@ static int s35390a_rtc_read_time(struct device *dev, struct rtc_time *tm)
> > > >  
> > > >  	tm->tm_sec = bcd2bin(buf[S35390A_BYTE_SECS]);
> > > >  	tm->tm_min = bcd2bin(buf[S35390A_BYTE_MINS]);
> > > > -	tm->tm_hour = s35390a_reg2hr(s35390a, buf[S35390A_BYTE_HOURS]);
> > > > +	tm->tm_hour = bcd2bin(buf[S35390A_BYTE_HOURS] & 0x3f);
> > > >  	tm->tm_wday = bcd2bin(buf[S35390A_BYTE_WDAY]);
> > > >  	tm->tm_mday = bcd2bin(buf[S35390A_BYTE_DAY]);
> > > >  	tm->tm_mon = bcd2bin(buf[S35390A_BYTE_MONTH]) - 1;
> > > > @@ -325,8 +299,7 @@ static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
> > > >  	else
> > > >  		buf[S35390A_ALRM_BYTE_WDAY] = 0;
> > > >  
> > > > -	buf[S35390A_ALRM_BYTE_HOURS] = s35390a_hr2reg(s35390a,
> > > > -			alm->time.tm_hour) | 0x80;
> > > > +	buf[S35390A_ALRM_BYTE_HOURS] = bin2bcd(alm->time.tm_hour) | 0x80;
> > > >  	buf[S35390A_ALRM_BYTE_MINS] = bin2bcd(alm->time.tm_min) | 0x80;
> > > >  
> > > >  	if (alm->time.tm_hour >= 12)
> > > > @@ -381,8 +354,7 @@ static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
> > > >  
> > > >  	if (buf[S35390A_ALRM_BYTE_HOURS] & 0x80)
> > > >  		alm->time.tm_hour =
> > > > -			s35390a_reg2hr(s35390a,
> > > > -				       buf[S35390A_ALRM_BYTE_HOURS] & ~0x80);
> > > > +			bcd2bin(buf[S35390A_ALRM_BYTE_HOURS] & 0x3f);
> > > >  
> > > >  	if (buf[S35390A_ALRM_BYTE_MINS] & 0x80)
> > > >  		alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS] & ~0x80);
> > > > @@ -459,7 +431,7 @@ static int s35390a_probe(struct i2c_client *client)
> > > >  	unsigned int i;
> > > >  	struct s35390a *s35390a;
> > > >  	struct rtc_device *rtc;
> > > > -	u8 buf, status1;
> > > > +	u8 buf, status1, time[7];
> > > >  	struct device *dev = &client->dev;
> > > >  	struct nvmem_config nvmem_cfg = {
> > > >  		.name = "s35390a_nvram",
> > > > @@ -503,10 +475,31 @@ static int s35390a_probe(struct i2c_client *client)
> > > >  		return err_read;
> > > >  	}
> > > >  
> > > > -	if (status1 & S35390A_FLAG_24H)
> > > > -		s35390a->twentyfourhour = 1;
> > > > -	else
> > > > -		s35390a->twentyfourhour = 0;
> > > > +	if (!(status1 & S35390A_FLAG_24H) && err_read != 1) {
> > > > +		unsigned int hour;
> > > > +
> > > > +		status1 |= S35390A_FLAG_24H;
> > > > +
> > > > +		err = s35390a_get_reg(s35390a, S35390A_CMD_TIME1, time, sizeof(time));
> > > > +		if (err < 0)
> > > > +			return dev_err_probe(dev, err, "reading 12-hour time failed\n");
> > > > +
> > > > +		/* converting to 24-hour time */
> > > > +		time[S35390A_BYTE_HOURS] = bitrev8(time[S35390A_BYTE_HOURS]);
> > > > +		hour = bcd2bin(time[S35390A_BYTE_HOURS] & 0x3f);
> > > > +		if (time[S35390A_BYTE_HOURS] & 0x40)
> > > > +			hour += 12;
> > > > +
> > > > +		time[S35390A_BYTE_HOURS] = bitrev8(bin2bcd(hour));
> > > > +
> > > > +		err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, &status1, sizeof(status1));
> > > > +		if (err < 0)
> > > > +			return dev_err_probe(dev, err, "setting 24-hour mode failed\n");
> > > > +
> > > > +		err = s35390a_set_reg(s35390a, S35390A_CMD_TIME1, time, sizeof(time));
> > > > +		if (err < 0)
> > > > +			return dev_err_probe(dev, err, "setting 24-hour time failed\n");
> > > 
> > > No, don't do this, this will break existing users as your conversion may
> > > happen after a minute rollover. The only function in which you are
> > > allowed to change the time registers is set_time. You definitively need
> > > to be able to read 12H mode time but you are allowed to only support
> > > writing 24h time.
> > > 
> > > Also, this is super verbose, adding strings to the kernel makes it
> > > bloated.
> > > 
> > > To avoid any desync, simply test for the S35390A_FLAG_24H bit in status
> > > in s35390a_rtc_read_time as the register is already read anyway.
> > > 
> > I think that would defeat the whole point of the patch, that the rtc is
> > always in 24-hour mode. If this driver was always used with the rtc, it
> > already should be in 24-hour mode, as thats the mode this driver does
> > initialize the rtc.
> 
> This assumption may not be true, the RTC may have been initialized by a
> bootloader or a different system in the factory.
> 
> > Your idea would work for the time, but not in combination with alarms.
> > If the rtc could be in 12-hour mode, then this would need to be
> > considered in setting and reading alarm. Also setting 24-hour mode
> > inside set_time would then also require to convert the alarm time.
> > Effectively making it less maintainable than before.
> 
> Note that while setting the time when an alarm has been set is not
> forbidden, it is never guaranteed to work anyway. I guess something we
> could do in the core is that whenever the time is set we go over the
> timerqueue and set the alarm again.

Actually this is already what we do so this is not an issue.


>This would allow to remove the UIE
> disabling/enabling dance.
> 
> > 
> > Currently s35390a_init does initialize the rtc in 24-hour mode, while
> > not updating s35390a->twentyfourhour. So some change needs to be made.
> > Just setting s35390a->twentyfourhour inside s35390a_init might now be
> > the simplest solution here.
> 
> Or maybe simply stop caching the value.
> 
> -- 
> Alexandre Belloni, co-owner and COO, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com
> 

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

  reply	other threads:[~2026-08-20 15:26 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-19 22:05 [PATCH v5 0/6] rtc: s35390a: Allow use of output pin for interrupt signal 1 for wakealarm Markus Probst
2026-08-19 22:05 ` [PATCH v5 1/6] dt-bindings: rtc: Add pinctrl for S35390A Markus Probst
2026-08-19 22:05 ` [PATCH v5 2/6] rtc: s35390a: Add missing newline to dev_err Markus Probst
2026-08-19 22:05 ` [PATCH v5 3/6] rtc: s35390a: Fix alarm not disabling Markus Probst
2026-08-19 22:25   ` Alexandre Belloni
2026-08-19 22:29     ` Markus Probst
2026-08-19 22:05 ` [PATCH v5 4/6] rtc: s35390a: force 24-hour mode Markus Probst
2026-08-19 22:20   ` Alexandre Belloni
2026-08-19 22:57     ` Markus Probst
2026-08-19 23:26       ` Alexandre Belloni
2026-08-20 15:25         ` Alexandre Belloni [this message]
2026-08-19 22:05 ` [PATCH v5 5/6] rtc: s35390a: Add pinctrl Markus Probst
2026-08-19 22:05 ` [PATCH v5 6/6] rtc: s35390a: Add synology quirk Markus Probst

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=20260820152556c6da4fce@mail.local \
    --to=alexandre.belloni@bootlin.com \
    --cc=akpm@linux-foundation.org \
    --cc=andrew@lunn.ch \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=gregory.clement@bootlin.com \
    --cc=krzk+dt@kernel.org \
    --cc=linusw@kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-gpio@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-rtc@vger.kernel.org \
    --cc=markus.probst@posteo.de \
    --cc=michael.brainbug.langer@googlemail.com \
    --cc=robh@kernel.org \
    --cc=sebastian.hesselbarth@gmail.com \
    --cc=uwe@kleine-koenig.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox