@ -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 ) ;