From: Alexandre Belloni <alexandre.belloni@free-electrons.com>
To: Mark Salyzyn <salyzyn@android.com>
Cc: linux-kernel@vger.kernel.org,
Alessandro Zummo <a.zummo@towertech.it>,
rtc-linux@googlegroups.com
Subject: [rtc-linux] Re: rtc-palmas: correct for bcd year
Date: Mon, 4 Jan 2016 17:18:53 +0100 [thread overview]
Message-ID: <20160104161853.GC32724@piout.net> (raw)
In-Reply-To: <1451508726-31769-1-git-send-email-salyzyn@android.com>
Hi,
On 30/12/2015 at 12:51:45 -0800, Mark Salyzyn wrote :
> Replace bcd2bin and bin2bcd with one that maps years 1970 to 2129
> in a pattern that works with the underlying hardware.
>
> The only transition that does not work correctly for this rtc clock
> is the transition from 2099 to 2100, it proceeds to 2000. The rtc
> clock retains and transitions the year correctly in all other
> circumstances.
>
If that transition doesn't work, it is not useful to try to support
dates after 2099. Also, I'm concerned about the leap year handling in
the other case. What is done right now is probably the best however, I
couldn't find the datasheet to confirm.
> Signed-off-by: Mark Salyzyn <salyzyn@android.com>
> ---
> drivers/rtc/rtc-palmas.c | 44 ++++++++++++++++++++++++++++++++++++++++----
> 1 file changed, 40 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/rtc/rtc-palmas.c b/drivers/rtc/rtc-palmas.c
> index 7ea2c47..3e9663d 100644
> --- a/drivers/rtc/rtc-palmas.c
> +++ b/drivers/rtc/rtc-palmas.c
> @@ -45,6 +45,42 @@ struct palmas_rtc {
> /* Total number of RTC registers needed to set time*/
> #define PALMAS_NUM_TIME_REGS (PALMAS_YEARS_REG - PALMAS_SECONDS_REG + 1)
>
> +/*
> + * Special bin2bcd mapping to deal with bcd storage of year.
> + *
> + * 0-69 -> 0xD0
> + * 70-99 (1970 - 1999) -> 0xD0 - 0xF9 (correctly rolls to 0x00)
> + * 100-199 (2000 - 2099) -> 0x00 - 0x99 (does not roll to 0xA0 :-( )
> + * 200-229 (2100 - 2129) -> 0xA0 - 0xC9 (really for completeness)
> + * 230- -> 0xC9
> + *
> + * Confirmed: the only transition that does not work correctly for this rtc
> + * clock is the transition from 2099 to 2100, it proceeds to 2000. We will
> + * accept this issue since the clock retains and transitions the year correctly
> + * in all other conditions.
> + */
> +static unsigned char year_bin2bcd(int val)
> +{
> + if (val < 70)
> + return 0xD0;
> + if (val < 100)
> + return bin2bcd(val - 20) | 0x80; /* KISS leverage of bin2bcd */
> + if (val >= 230)
> + return 0xC9;
> + if (val >= 200)
> + return bin2bcd(val - 180) | 0x80;
> + return bin2bcd(val - 100);
> +}
> +
> +static int year_bcd2bin(unsigned char val)
> +{
> + if (val >= 0xD0)
> + return bcd2bin(val & 0x7F) + 20;
> + if (val >= 0xA0)
> + return bcd2bin(val & 0x7F) + 180;
> + return bcd2bin(val) + 100;
> +}
> +
> static int palmas_rtc_read_time(struct device *dev, struct rtc_time *tm)
> {
> unsigned char rtc_data[PALMAS_NUM_TIME_REGS];
> @@ -71,7 +107,7 @@ static int palmas_rtc_read_time(struct device *dev, struct rtc_time *tm)
> tm->tm_hour = bcd2bin(rtc_data[2]);
> tm->tm_mday = bcd2bin(rtc_data[3]);
> tm->tm_mon = bcd2bin(rtc_data[4]) - 1;
> - tm->tm_year = bcd2bin(rtc_data[5]) + 100;
> + tm->tm_year = year_bcd2bin(rtc_data[5]);
>
> return ret;
> }
> @@ -87,7 +123,7 @@ static int palmas_rtc_set_time(struct device *dev, struct rtc_time *tm)
> rtc_data[2] = bin2bcd(tm->tm_hour);
> rtc_data[3] = bin2bcd(tm->tm_mday);
> rtc_data[4] = bin2bcd(tm->tm_mon + 1);
> - rtc_data[5] = bin2bcd(tm->tm_year - 100);
> + rtc_data[5] = year_bin2bcd(tm->tm_year);
>
> /* Stop RTC while updating the RTC time registers */
> ret = palmas_update_bits(palmas, PALMAS_RTC_BASE, PALMAS_RTC_CTRL_REG,
> @@ -142,7 +178,7 @@ static int palmas_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
> alm->time.tm_hour = bcd2bin(alarm_data[2]);
> alm->time.tm_mday = bcd2bin(alarm_data[3]);
> alm->time.tm_mon = bcd2bin(alarm_data[4]) - 1;
> - alm->time.tm_year = bcd2bin(alarm_data[5]) + 100;
> + alm->time.tm_year = year_bcd2bin(alarm_data[5]);
>
> ret = palmas_read(palmas, PALMAS_RTC_BASE, PALMAS_RTC_INTERRUPTS_REG,
> &int_val);
> @@ -173,7 +209,7 @@ static int palmas_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
> alarm_data[2] = bin2bcd(alm->time.tm_hour);
> alarm_data[3] = bin2bcd(alm->time.tm_mday);
> alarm_data[4] = bin2bcd(alm->time.tm_mon + 1);
> - alarm_data[5] = bin2bcd(alm->time.tm_year - 100);
> + alarm_data[5] = year_bin2bcd(alm->time.tm_year);
>
> ret = palmas_bulk_write(palmas, PALMAS_RTC_BASE,
> PALMAS_ALARM_SECONDS_REG, alarm_data, PALMAS_NUM_TIME_REGS);
> --
> 2.6.0.rc2.230.g3dd15c0
>
--
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
WARNING: multiple messages have this Message-ID (diff)
From: Alexandre Belloni <alexandre.belloni@free-electrons.com>
To: Mark Salyzyn <salyzyn@android.com>
Cc: linux-kernel@vger.kernel.org,
Alessandro Zummo <a.zummo@towertech.it>,
rtc-linux@googlegroups.com
Subject: Re: rtc-palmas: correct for bcd year
Date: Mon, 4 Jan 2016 17:18:53 +0100 [thread overview]
Message-ID: <20160104161853.GC32724@piout.net> (raw)
In-Reply-To: <1451508726-31769-1-git-send-email-salyzyn@android.com>
Hi,
On 30/12/2015 at 12:51:45 -0800, Mark Salyzyn wrote :
> Replace bcd2bin and bin2bcd with one that maps years 1970 to 2129
> in a pattern that works with the underlying hardware.
>
> The only transition that does not work correctly for this rtc clock
> is the transition from 2099 to 2100, it proceeds to 2000. The rtc
> clock retains and transitions the year correctly in all other
> circumstances.
>
If that transition doesn't work, it is not useful to try to support
dates after 2099. Also, I'm concerned about the leap year handling in
the other case. What is done right now is probably the best however, I
couldn't find the datasheet to confirm.
> Signed-off-by: Mark Salyzyn <salyzyn@android.com>
> ---
> drivers/rtc/rtc-palmas.c | 44 ++++++++++++++++++++++++++++++++++++++++----
> 1 file changed, 40 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/rtc/rtc-palmas.c b/drivers/rtc/rtc-palmas.c
> index 7ea2c47..3e9663d 100644
> --- a/drivers/rtc/rtc-palmas.c
> +++ b/drivers/rtc/rtc-palmas.c
> @@ -45,6 +45,42 @@ struct palmas_rtc {
> /* Total number of RTC registers needed to set time*/
> #define PALMAS_NUM_TIME_REGS (PALMAS_YEARS_REG - PALMAS_SECONDS_REG + 1)
>
> +/*
> + * Special bin2bcd mapping to deal with bcd storage of year.
> + *
> + * 0-69 -> 0xD0
> + * 70-99 (1970 - 1999) -> 0xD0 - 0xF9 (correctly rolls to 0x00)
> + * 100-199 (2000 - 2099) -> 0x00 - 0x99 (does not roll to 0xA0 :-( )
> + * 200-229 (2100 - 2129) -> 0xA0 - 0xC9 (really for completeness)
> + * 230- -> 0xC9
> + *
> + * Confirmed: the only transition that does not work correctly for this rtc
> + * clock is the transition from 2099 to 2100, it proceeds to 2000. We will
> + * accept this issue since the clock retains and transitions the year correctly
> + * in all other conditions.
> + */
> +static unsigned char year_bin2bcd(int val)
> +{
> + if (val < 70)
> + return 0xD0;
> + if (val < 100)
> + return bin2bcd(val - 20) | 0x80; /* KISS leverage of bin2bcd */
> + if (val >= 230)
> + return 0xC9;
> + if (val >= 200)
> + return bin2bcd(val - 180) | 0x80;
> + return bin2bcd(val - 100);
> +}
> +
> +static int year_bcd2bin(unsigned char val)
> +{
> + if (val >= 0xD0)
> + return bcd2bin(val & 0x7F) + 20;
> + if (val >= 0xA0)
> + return bcd2bin(val & 0x7F) + 180;
> + return bcd2bin(val) + 100;
> +}
> +
> static int palmas_rtc_read_time(struct device *dev, struct rtc_time *tm)
> {
> unsigned char rtc_data[PALMAS_NUM_TIME_REGS];
> @@ -71,7 +107,7 @@ static int palmas_rtc_read_time(struct device *dev, struct rtc_time *tm)
> tm->tm_hour = bcd2bin(rtc_data[2]);
> tm->tm_mday = bcd2bin(rtc_data[3]);
> tm->tm_mon = bcd2bin(rtc_data[4]) - 1;
> - tm->tm_year = bcd2bin(rtc_data[5]) + 100;
> + tm->tm_year = year_bcd2bin(rtc_data[5]);
>
> return ret;
> }
> @@ -87,7 +123,7 @@ static int palmas_rtc_set_time(struct device *dev, struct rtc_time *tm)
> rtc_data[2] = bin2bcd(tm->tm_hour);
> rtc_data[3] = bin2bcd(tm->tm_mday);
> rtc_data[4] = bin2bcd(tm->tm_mon + 1);
> - rtc_data[5] = bin2bcd(tm->tm_year - 100);
> + rtc_data[5] = year_bin2bcd(tm->tm_year);
>
> /* Stop RTC while updating the RTC time registers */
> ret = palmas_update_bits(palmas, PALMAS_RTC_BASE, PALMAS_RTC_CTRL_REG,
> @@ -142,7 +178,7 @@ static int palmas_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
> alm->time.tm_hour = bcd2bin(alarm_data[2]);
> alm->time.tm_mday = bcd2bin(alarm_data[3]);
> alm->time.tm_mon = bcd2bin(alarm_data[4]) - 1;
> - alm->time.tm_year = bcd2bin(alarm_data[5]) + 100;
> + alm->time.tm_year = year_bcd2bin(alarm_data[5]);
>
> ret = palmas_read(palmas, PALMAS_RTC_BASE, PALMAS_RTC_INTERRUPTS_REG,
> &int_val);
> @@ -173,7 +209,7 @@ static int palmas_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
> alarm_data[2] = bin2bcd(alm->time.tm_hour);
> alarm_data[3] = bin2bcd(alm->time.tm_mday);
> alarm_data[4] = bin2bcd(alm->time.tm_mon + 1);
> - alarm_data[5] = bin2bcd(alm->time.tm_year - 100);
> + alarm_data[5] = year_bin2bcd(alm->time.tm_year);
>
> ret = palmas_bulk_write(palmas, PALMAS_RTC_BASE,
> PALMAS_ALARM_SECONDS_REG, alarm_data, PALMAS_NUM_TIME_REGS);
> --
> 2.6.0.rc2.230.g3dd15c0
>
--
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
next prev parent reply other threads:[~2016-01-04 16:19 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-12-30 20:51 [rtc-linux] rtc-palmas: correct for bcd year Mark Salyzyn
2015-12-30 20:51 ` Mark Salyzyn
2016-01-04 16:18 ` Alexandre Belloni [this message]
2016-01-04 16:18 ` Alexandre Belloni
2016-01-04 16:45 ` [rtc-linux] " Mark Salyzyn
2016-01-04 16:45 ` Mark Salyzyn
2016-01-05 0:00 ` [rtc-linux] " Alexandre Belloni
2016-01-05 0:00 ` Alexandre Belloni
2016-01-05 16:08 ` [rtc-linux] " Mark Salyzyn
2016-01-05 16:08 ` Mark Salyzyn
2016-07-08 14:10 ` [rtc-linux] " Alexandre Belloni
2016-07-08 14:10 ` Alexandre Belloni
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=20160104161853.GC32724@piout.net \
--to=alexandre.belloni@free-electrons.com \
--cc=a.zummo@towertech.it \
--cc=linux-kernel@vger.kernel.org \
--cc=rtc-linux@googlegroups.com \
--cc=salyzyn@android.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.