2019-03-14 01:02:48 +03:00
// SPDX-License-Identifier: GPL-2.0
2006-03-27 13:16:37 +04:00
/*
* RTC subsystem , initialize system time on startup
*
* Copyright ( C ) 2005 Tower Technologies
* Author : Alessandro Zummo < a . zummo @ towertech . it >
2019-03-14 01:02:48 +03:00
*/
2006-03-27 13:16:37 +04:00
2015-04-16 22:46:14 +03:00
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2006-03-27 13:16:37 +04:00
# include <linux/rtc.h>
/* IMPORTANT: the RTC only stores whole seconds. It is arbitrary
* whether it stores the most close value or the value with partial
* seconds truncated . However , it is important that we use it to store
* the truncated value . This is because otherwise it is necessary ,
* in an rtc sync function , to read both xtime . tv_sec and
* xtime . tv_nsec . On some processors ( i . e . ARM ) , an atomic read
* of > 32 bits is not possible . So storing the most close value would
* slow down the sync API . So here we have the truncated value and
* the best guess is to add 0.5 s .
*/
static int __init rtc_hctosys ( void )
{
2010-03-11 02:20:35 +03:00
int err = - ENODEV ;
2006-03-27 13:16:37 +04:00
struct rtc_time tm ;
2015-01-22 05:31:53 +03:00
struct timespec64 tv64 = {
2010-03-11 02:20:35 +03:00
. tv_nsec = NSEC_PER_SEC > > 1 ,
} ;
2007-05-08 11:33:30 +04:00
struct rtc_device * rtc = rtc_class_open ( CONFIG_RTC_HCTOSYS_DEVICE ) ;
2006-03-27 13:16:37 +04:00
2019-03-20 14:59:09 +03:00
if ( ! rtc ) {
2015-04-16 22:46:14 +03:00
pr_info ( " unable to open rtc device (%s) \n " ,
CONFIG_RTC_HCTOSYS_DEVICE ) ;
2010-03-11 02:20:35 +03:00
goto err_open ;
2006-03-27 13:16:37 +04:00
}
2007-05-08 11:33:30 +04:00
err = rtc_read_time ( rtc , & tm ) ;
2010-03-11 02:20:35 +03:00
if ( err ) {
dev_err ( rtc - > dev . parent ,
" hctosys: unable to read the hardware clock \n " ) ;
goto err_read ;
}
2006-03-27 13:16:37 +04:00
2015-01-22 05:31:53 +03:00
tv64 . tv_sec = rtc_tm_to_time64 ( & tm ) ;
2006-03-27 13:16:37 +04:00
2018-03-09 01:27:31 +03:00
# if BITS_PER_LONG == 32
2018-11-05 06:48:25 +03:00
if ( tv64 . tv_sec > INT_MAX ) {
err = - ERANGE ;
2018-03-09 01:27:31 +03:00
goto err_read ;
2018-11-05 06:48:25 +03:00
}
2018-03-09 01:27:31 +03:00
# endif
2015-01-22 05:31:53 +03:00
err = do_settimeofday64 ( & tv64 ) ;
2006-03-27 13:16:37 +04:00
2018-12-05 00:23:12 +03:00
dev_info ( rtc - > dev . parent , " setting system clock to %ptR UTC (%lld) \n " ,
& tm , ( long long ) tv64 . tv_sec ) ;
2010-03-11 02:20:35 +03:00
err_read :
2007-05-08 11:33:30 +04:00
rtc_class_close ( rtc ) ;
2006-03-27 13:16:37 +04:00
2010-03-11 02:20:35 +03:00
err_open :
rtc_hctosys_ret = err ;
return err ;
2006-03-27 13:16:37 +04:00
}
late_initcall ( rtc_hctosys ) ;