Patchwork RTC: Fix time range difference between linux and RTC chip

login
register
mail settings
Submitter Xulei
Date Jan. 28, 2011, 6:19 a.m.
Message ID <1296195559-5439-1-git-send-email-B33228@freescale.com>
Download mbox | patch
Permalink /patch/80772/
State New
Headers show

Comments

Xulei - Jan. 28, 2011, 6:19 a.m.
In linux rtc_time struct, tm_mon range is 0~11, tm_wday range is 0~6,
while in RTC HW REG, month range is 1~12, day of the week range is 1~7,
this patch adjusts difference of them.

Signed-off-by: Lei Xu <B33228@freescale.com>
---
 drivers/rtc/rtc-ds3232.c |   14 +++++++++-----
 1 files changed, 9 insertions(+), 5 deletions(-)
Xulei - Feb. 14, 2011, 2:37 a.m.
Hi,
	Any comments about this patch? Thanks.

On 五, 2011-01-28 at 14:19 +0800, Lei Xu wrote:
> In linux rtc_time struct, tm_mon range is 0~11, tm_wday range is 0~6,
> while in RTC HW REG, month range is 1~12, day of the week range is 1~7,
> this patch adjusts difference of them.
> 
> Signed-off-by: Lei Xu <B33228@freescale.com>
> ---
>  drivers/rtc/rtc-ds3232.c |   14 +++++++++-----
>  1 files changed, 9 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c
> index 23a9ee1..9507354 100644
> --- a/drivers/rtc/rtc-ds3232.c
> +++ b/drivers/rtc/rtc-ds3232.c
> @@ -1,7 +1,7 @@
>  /*
>   * RTC client/driver for the Maxim/Dallas DS3232 Real-Time Clock over I2C
>   *
> - * Copyright (C) 2009-2010 Freescale Semiconductor.
> + * Copyright (C) 2009-2011 Freescale Semiconductor.
>   * Author: Jack Lan <jack.lan@freescale.com>
>   *
>   * This program is free software; you can redistribute  it and/or modify it
> @@ -141,9 +141,11 @@ static int ds3232_read_time(struct device *dev, struct rtc_time *time)
>  		time->tm_hour = bcd2bin(hour);
>  	}
>  
> -	time->tm_wday = bcd2bin(week);
> +	/* Day of the week in linux range is 0~6 while 1~7 in RTC chip */
> +	time->tm_wday = bcd2bin(week) - 1;
>  	time->tm_mday = bcd2bin(day);
> -	time->tm_mon = bcd2bin(month & 0x7F);
> +	/* linux tm_mon range:0~11, while month range is 1~12 in RTC chip */
> +	time->tm_mon = bcd2bin(month & 0x7F) - 1;
>  	if (century)
>  		add_century = 100;
>  
> @@ -162,9 +164,11 @@ static int ds3232_set_time(struct device *dev, struct rtc_time *time)
>  	buf[0] = bin2bcd(time->tm_sec);
>  	buf[1] = bin2bcd(time->tm_min);
>  	buf[2] = bin2bcd(time->tm_hour);
> -	buf[3] = bin2bcd(time->tm_wday); /* Day of the week */
> +	/* Day of the week in linux range is 0~6 while 1~7 in RTC chip */
> +	buf[3] = bin2bcd(time->tm_wday + 1);
>  	buf[4] = bin2bcd(time->tm_mday); /* Date */
> -	buf[5] = bin2bcd(time->tm_mon);
> +	/* linux tm_mon range:0~11, while month range is 1~12 in RTC chip */
> +	buf[5] = bin2bcd(time->tm_mon + 1);
>  	if (time->tm_year >= 100) {
>  		buf[5] |= 0x80;
>  		buf[6] = bin2bcd(time->tm_year - 100);
Xulei - Feb. 17, 2011, 6:11 a.m.
Hi,
	Any comments? Thanks.

	patch link: http://patchwork.ozlabs.org/patch/80772/

On Fri, 2011-01-28 at 14:19 +0800, Lei Xu wrote:
> In linux rtc_time struct, tm_mon range is 0~11, tm_wday range is 0~6,
> while in RTC HW REG, month range is 1~12, day of the week range is 1~7,
> this patch adjusts difference of them.
> 
> Signed-off-by: Lei Xu <B33228@freescale.com>
> ---
>  drivers/rtc/rtc-ds3232.c |   14 +++++++++-----
>  1 files changed, 9 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c
> index 23a9ee1..9507354 100644
> --- a/drivers/rtc/rtc-ds3232.c
> +++ b/drivers/rtc/rtc-ds3232.c
> @@ -1,7 +1,7 @@
>  /*
>   * RTC client/driver for the Maxim/Dallas DS3232 Real-Time Clock over I2C
>   *
> - * Copyright (C) 2009-2010 Freescale Semiconductor.
> + * Copyright (C) 2009-2011 Freescale Semiconductor.
>   * Author: Jack Lan <jack.lan@freescale.com>
>   *
>   * This program is free software; you can redistribute  it and/or modify it
> @@ -141,9 +141,11 @@ static int ds3232_read_time(struct device *dev, struct rtc_time *time)
>  		time->tm_hour = bcd2bin(hour);
>  	}
>  
> -	time->tm_wday = bcd2bin(week);
> +	/* Day of the week in linux range is 0~6 while 1~7 in RTC chip */
> +	time->tm_wday = bcd2bin(week) - 1;
>  	time->tm_mday = bcd2bin(day);
> -	time->tm_mon = bcd2bin(month & 0x7F);
> +	/* linux tm_mon range:0~11, while month range is 1~12 in RTC chip */
> +	time->tm_mon = bcd2bin(month & 0x7F) - 1;
>  	if (century)
>  		add_century = 100;
>  
> @@ -162,9 +164,11 @@ static int ds3232_set_time(struct device *dev, struct rtc_time *time)
>  	buf[0] = bin2bcd(time->tm_sec);
>  	buf[1] = bin2bcd(time->tm_min);
>  	buf[2] = bin2bcd(time->tm_hour);
> -	buf[3] = bin2bcd(time->tm_wday); /* Day of the week */
> +	/* Day of the week in linux range is 0~6 while 1~7 in RTC chip */
> +	buf[3] = bin2bcd(time->tm_wday + 1);
>  	buf[4] = bin2bcd(time->tm_mday); /* Date */
> -	buf[5] = bin2bcd(time->tm_mon);
> +	/* linux tm_mon range:0~11, while month range is 1~12 in RTC chip */
> +	buf[5] = bin2bcd(time->tm_mon + 1);
>  	if (time->tm_year >= 100) {
>  		buf[5] |= 0x80;
>  		buf[6] = bin2bcd(time->tm_year - 100);
Andrew Morton - Feb. 17, 2011, 11:10 p.m.
On Fri, 28 Jan 2011 14:19:19 +0800
Lei Xu <B33228@freescale.com> wrote:

> In linux rtc_time struct, tm_mon range is 0~11, tm_wday range is 0~6,
> while in RTC HW REG, month range is 1~12, day of the week range is 1~7,
> this patch adjusts difference of them.
> 
> Signed-off-by: Lei Xu <B33228@freescale.com>
> ---
>  drivers/rtc/rtc-ds3232.c |   14 +++++++++-----
>  1 files changed, 9 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c
> index 23a9ee1..9507354 100644
> --- a/drivers/rtc/rtc-ds3232.c
> +++ b/drivers/rtc/rtc-ds3232.c
> @@ -1,7 +1,7 @@
>  /*
>   * RTC client/driver for the Maxim/Dallas DS3232 Real-Time Clock over I2C
>   *
> - * Copyright (C) 2009-2010 Freescale Semiconductor.
> + * Copyright (C) 2009-2011 Freescale Semiconductor.
>   * Author: Jack Lan <jack.lan@freescale.com>
>   *
>   * This program is free software; you can redistribute  it and/or modify it
> @@ -141,9 +141,11 @@ static int ds3232_read_time(struct device *dev, struct rtc_time *time)
>  		time->tm_hour = bcd2bin(hour);
>  	}
>  
> -	time->tm_wday = bcd2bin(week);
> +	/* Day of the week in linux range is 0~6 while 1~7 in RTC chip */
> +	time->tm_wday = bcd2bin(week) - 1;
>  	time->tm_mday = bcd2bin(day);
> -	time->tm_mon = bcd2bin(month & 0x7F);
> +	/* linux tm_mon range:0~11, while month range is 1~12 in RTC chip */
> +	time->tm_mon = bcd2bin(month & 0x7F) - 1;
>  	if (century)
>  		add_century = 100;
>  
> @@ -162,9 +164,11 @@ static int ds3232_set_time(struct device *dev, struct rtc_time *time)
>  	buf[0] = bin2bcd(time->tm_sec);
>  	buf[1] = bin2bcd(time->tm_min);
>  	buf[2] = bin2bcd(time->tm_hour);
> -	buf[3] = bin2bcd(time->tm_wday); /* Day of the week */
> +	/* Day of the week in linux range is 0~6 while 1~7 in RTC chip */
> +	buf[3] = bin2bcd(time->tm_wday + 1);
>  	buf[4] = bin2bcd(time->tm_mday); /* Date */
> -	buf[5] = bin2bcd(time->tm_mon);
> +	/* linux tm_mon range:0~11, while month range is 1~12 in RTC chip */
> +	buf[5] = bin2bcd(time->tm_mon + 1);
>  	if (time->tm_year >= 100) {
>  		buf[5] |= 0x80;
>  		buf[6] = bin2bcd(time->tm_year - 100);

What were the user-visible effects of this bug?  Please always include
this information when fixing bugs!

I assume that over short time periods, the hardware appeared to work
correctly but it wold do weird things at the end of the month?
Xulei - Feb. 18, 2011, 10:05 a.m.
On 四, 2011-02-17 at 15:10 -0800, Andrew Morton wrote:
> On Fri, 28 Jan 2011 14:19:19 +0800
> Lei Xu <B33228@freescale.com> wrote:
> 
> > In linux rtc_time struct, tm_mon range is 0~11, tm_wday range is 0~6,
> > while in RTC HW REG, month range is 1~12, day of the week range is 1~7,
> > this patch adjusts difference of them.
> > 
> > Signed-off-by: Lei Xu <B33228@freescale.com>
> > ---
> >  drivers/rtc/rtc-ds3232.c |   14 +++++++++-----
> >  1 files changed, 9 insertions(+), 5 deletions(-)
> > 
> > diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c
> > index 23a9ee1..9507354 100644
> > --- a/drivers/rtc/rtc-ds3232.c
> > +++ b/drivers/rtc/rtc-ds3232.c
> > @@ -1,7 +1,7 @@
> >  /*
> >   * RTC client/driver for the Maxim/Dallas DS3232 Real-Time Clock over I2C
> >   *
> > - * Copyright (C) 2009-2010 Freescale Semiconductor.
> > + * Copyright (C) 2009-2011 Freescale Semiconductor.
> >   * Author: Jack Lan <jack.lan@freescale.com>
> >   *
> >   * This program is free software; you can redistribute  it and/or modify it
> > @@ -141,9 +141,11 @@ static int ds3232_read_time(struct device *dev, struct rtc_time *time)
> >  		time->tm_hour = bcd2bin(hour);
> >  	}
> >  
> > -	time->tm_wday = bcd2bin(week);
> > +	/* Day of the week in linux range is 0~6 while 1~7 in RTC chip */
> > +	time->tm_wday = bcd2bin(week) - 1;
> >  	time->tm_mday = bcd2bin(day);
> > -	time->tm_mon = bcd2bin(month & 0x7F);
> > +	/* linux tm_mon range:0~11, while month range is 1~12 in RTC chip */
> > +	time->tm_mon = bcd2bin(month & 0x7F) - 1;
> >  	if (century)
> >  		add_century = 100;
> >  
> > @@ -162,9 +164,11 @@ static int ds3232_set_time(struct device *dev, struct rtc_time *time)
> >  	buf[0] = bin2bcd(time->tm_sec);
> >  	buf[1] = bin2bcd(time->tm_min);
> >  	buf[2] = bin2bcd(time->tm_hour);
> > -	buf[3] = bin2bcd(time->tm_wday); /* Day of the week */
> > +	/* Day of the week in linux range is 0~6 while 1~7 in RTC chip */
> > +	buf[3] = bin2bcd(time->tm_wday + 1);
> >  	buf[4] = bin2bcd(time->tm_mday); /* Date */
> > -	buf[5] = bin2bcd(time->tm_mon);
> > +	/* linux tm_mon range:0~11, while month range is 1~12 in RTC chip */
> > +	buf[5] = bin2bcd(time->tm_mon + 1);
> >  	if (time->tm_year >= 100) {
> >  		buf[5] |= 0x80;
> >  		buf[6] = bin2bcd(time->tm_year - 100);
> 
> What were the user-visible effects of this bug?  Please always include
> this information when fixing bugs!
> 
> I assume that over short time periods, the hardware appeared to work
> correctly but it wold do weird things at the end of the month?
> 
Thanks.
As your assumption, most of month will be operated as next month by
hardware(When in Jan it maybe even worse), for example, if in May,
software wrote 4 to the hardware, which handled as April. Then the logic
would be different between software and hardware, which maybe result
weird things.

Patch

diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c
index 23a9ee1..9507354 100644
--- a/drivers/rtc/rtc-ds3232.c
+++ b/drivers/rtc/rtc-ds3232.c
@@ -1,7 +1,7 @@ 
 /*
  * RTC client/driver for the Maxim/Dallas DS3232 Real-Time Clock over I2C
  *
- * Copyright (C) 2009-2010 Freescale Semiconductor.
+ * Copyright (C) 2009-2011 Freescale Semiconductor.
  * Author: Jack Lan <jack.lan@freescale.com>
  *
  * This program is free software; you can redistribute  it and/or modify it
@@ -141,9 +141,11 @@  static int ds3232_read_time(struct device *dev, struct rtc_time *time)
 		time->tm_hour = bcd2bin(hour);
 	}
 
-	time->tm_wday = bcd2bin(week);
+	/* Day of the week in linux range is 0~6 while 1~7 in RTC chip */
+	time->tm_wday = bcd2bin(week) - 1;
 	time->tm_mday = bcd2bin(day);
-	time->tm_mon = bcd2bin(month & 0x7F);
+	/* linux tm_mon range:0~11, while month range is 1~12 in RTC chip */
+	time->tm_mon = bcd2bin(month & 0x7F) - 1;
 	if (century)
 		add_century = 100;
 
@@ -162,9 +164,11 @@  static int ds3232_set_time(struct device *dev, struct rtc_time *time)
 	buf[0] = bin2bcd(time->tm_sec);
 	buf[1] = bin2bcd(time->tm_min);
 	buf[2] = bin2bcd(time->tm_hour);
-	buf[3] = bin2bcd(time->tm_wday); /* Day of the week */
+	/* Day of the week in linux range is 0~6 while 1~7 in RTC chip */
+	buf[3] = bin2bcd(time->tm_wday + 1);
 	buf[4] = bin2bcd(time->tm_mday); /* Date */
-	buf[5] = bin2bcd(time->tm_mon);
+	/* linux tm_mon range:0~11, while month range is 1~12 in RTC chip */
+	buf[5] = bin2bcd(time->tm_mon + 1);
 	if (time->tm_year >= 100) {
 		buf[5] |= 0x80;
 		buf[6] = bin2bcd(time->tm_year - 100);