mirror of https://gitee.com/openkylin/linux.git
MIPS: Convert update_persistent_clock() to update_persistent_clock64()
Since struct timespec is not y2038 safe on 32bit machines, this patch converts update_persistent_clock() to update_persistent_clock64() using struct timespec64. The rtc_mips_set_time() and rtc_mips_set_mmss() interfaces were using 'unsigned long' type that is not y2038 safe on 32bit machines, moreover there is only one platform implementing rtc_mips_set_time() and two platforms implementing rtc_mips_set_mmss(), so we can just make them each implement update_persistent_clock64() directly, to get that helper out of the common mips code by removing rtc_mips_set_time() and rtc_mips_set_mmss() interfaces. Signed-off-by: Baolin Wang <baolin.wang@linaro.org> Acked-by: Arnd Bergmann <arnd@arndb.de> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: Huacai Chen <chenhc@lemote.com> Cc: Paul Burton <paul.burton@mips.com> Cc: linux-mips@linux-mips.org Signed-off-by: James Hogan <jhogan@kernel.org>
This commit is contained in:
parent
09adad1719
commit
f06e7aa47f
|
@ -59,14 +59,15 @@ void read_persistent_clock64(struct timespec64 *ts)
|
|||
}
|
||||
|
||||
/*
|
||||
* In order to set the CMOS clock precisely, rtc_mips_set_mmss has to
|
||||
* In order to set the CMOS clock precisely, update_persistent_clock64 has to
|
||||
* be called 500 ms after the second nowtime has started, because when
|
||||
* nowtime is written into the registers of the CMOS clock, it will
|
||||
* jump to the next second precisely 500 ms later. Check the Dallas
|
||||
* DS1287 data sheet for details.
|
||||
*/
|
||||
int rtc_mips_set_mmss(unsigned long nowtime)
|
||||
int update_persistent_clock64(struct timespec64 now)
|
||||
{
|
||||
time64_t nowtime = now.tv_sec;
|
||||
int retval = 0;
|
||||
int real_seconds, real_minutes, cmos_minutes;
|
||||
unsigned char save_control, save_freq_select;
|
||||
|
@ -91,8 +92,7 @@ int rtc_mips_set_mmss(unsigned long nowtime)
|
|||
* messing with unknown time zones but requires your
|
||||
* RTC not to be off by more than 15 minutes
|
||||
*/
|
||||
real_seconds = nowtime % 60;
|
||||
real_minutes = nowtime / 60;
|
||||
real_minutes = div_s64_rem(nowtime, 60, &real_seconds);
|
||||
if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1)
|
||||
real_minutes += 30; /* correct for half hour time zone */
|
||||
real_minutes %= 60;
|
||||
|
|
|
@ -21,15 +21,6 @@
|
|||
|
||||
extern spinlock_t rtc_lock;
|
||||
|
||||
/*
|
||||
* RTC ops. By default, they point to weak no-op RTC functions.
|
||||
* rtc_mips_set_time - reverse the above translation and set time to RTC.
|
||||
* rtc_mips_set_mmss - similar to rtc_set_time, but only min and sec need
|
||||
* to be set. Used by RTC sync-up.
|
||||
*/
|
||||
extern int rtc_mips_set_time(unsigned long);
|
||||
extern int rtc_mips_set_mmss(unsigned long);
|
||||
|
||||
/*
|
||||
* board specific routines required by time_init().
|
||||
*/
|
||||
|
|
|
@ -34,21 +34,6 @@
|
|||
DEFINE_SPINLOCK(rtc_lock);
|
||||
EXPORT_SYMBOL(rtc_lock);
|
||||
|
||||
int __weak rtc_mips_set_time(unsigned long sec)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int __weak rtc_mips_set_mmss(unsigned long nowtime)
|
||||
{
|
||||
return rtc_mips_set_time(nowtime);
|
||||
}
|
||||
|
||||
int update_persistent_clock(struct timespec now)
|
||||
{
|
||||
return rtc_mips_set_mmss(now.tv_sec);
|
||||
}
|
||||
|
||||
static int null_perf_irq(void)
|
||||
{
|
||||
return 0;
|
||||
|
|
|
@ -152,14 +152,19 @@ void read_persistent_clock64(struct timespec64 *ts)
|
|||
ts->tv_nsec = 0;
|
||||
}
|
||||
|
||||
int rtc_mips_set_mmss(unsigned long time)
|
||||
int update_persistent_clock64(struct timespec64 now)
|
||||
{
|
||||
time64_t time = now.tv_sec;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rtc_lock, flags);
|
||||
rtc_init_op();
|
||||
rtc_write_byte(SET_TIME_CMD);
|
||||
rtc_write_word(time);
|
||||
/*
|
||||
* Due to the hardware limitation, we cast to 'unsigned long' type,
|
||||
* so it will overflow in year 2106 on 32-bit machine.
|
||||
*/
|
||||
rtc_write_word((unsigned long)time);
|
||||
rtc_end_op();
|
||||
spin_unlock_irqrestore(&rtc_lock, flags);
|
||||
|
||||
|
|
|
@ -73,8 +73,16 @@ int proc_dolasatrtc(struct ctl_table *table, int write,
|
|||
if (r)
|
||||
return r;
|
||||
|
||||
if (write)
|
||||
rtc_mips_set_mmss(rtctmp);
|
||||
if (write) {
|
||||
/*
|
||||
* Due to the RTC hardware limitation, we can not actually
|
||||
* use the full 64-bit range here.
|
||||
*/
|
||||
ts.tv_sec = rtctmp;
|
||||
ts.tv_nsec = 0;
|
||||
|
||||
update_persistent_clock64(ts);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -141,13 +141,13 @@ static int m41t81_write(uint8_t addr, int b)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int m41t81_set_time(unsigned long t)
|
||||
int m41t81_set_time(time64_t t)
|
||||
{
|
||||
struct rtc_time tm;
|
||||
unsigned long flags;
|
||||
|
||||
/* Note we don't care about the century */
|
||||
rtc_time_to_tm(t, &tm);
|
||||
rtc_time64_to_tm(t, &tm);
|
||||
|
||||
/*
|
||||
* Note the write order matters as it ensures the correctness.
|
||||
|
|
|
@ -109,13 +109,13 @@ static int xicor_write(uint8_t addr, int b)
|
|||
}
|
||||
}
|
||||
|
||||
int xicor_set_time(unsigned long t)
|
||||
int xicor_set_time(time64_t t)
|
||||
{
|
||||
struct rtc_time tm;
|
||||
int tmp;
|
||||
unsigned long flags;
|
||||
|
||||
rtc_time_to_tm(t, &tm);
|
||||
rtc_time64_to_tm(t, &tm);
|
||||
tm.tm_year += 1900;
|
||||
|
||||
spin_lock_irqsave(&rtc_lock, flags);
|
||||
|
|
|
@ -57,11 +57,11 @@ extern void sb1250_setup(void);
|
|||
#endif
|
||||
|
||||
extern int xicor_probe(void);
|
||||
extern int xicor_set_time(unsigned long);
|
||||
extern int xicor_set_time(time64_t);
|
||||
extern time64_t xicor_get_time(void);
|
||||
|
||||
extern int m41t81_probe(void);
|
||||
extern int m41t81_set_time(unsigned long);
|
||||
extern int m41t81_set_time(time64_t);
|
||||
extern time64_t m41t81_get_time(void);
|
||||
|
||||
const char *get_system_type(void)
|
||||
|
@ -109,8 +109,10 @@ void read_persistent_clock64(struct timespec64 *ts)
|
|||
ts->tv_nsec = 0;
|
||||
}
|
||||
|
||||
int rtc_mips_set_time(unsigned long sec)
|
||||
int update_persistent_clock64(struct timespec64 now)
|
||||
{
|
||||
time64_t sec = now.tv_sec;
|
||||
|
||||
switch (swarm_rtc_type) {
|
||||
case RTC_XICOR:
|
||||
return xicor_set_time(sec);
|
||||
|
|
Loading…
Reference in New Issue