mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
[PATCH] GTOD: persistent clock support
Persistent clock support: do proper timekeeping across suspend/resume. [bunk@stusta.de: cleanup] Signed-off-by: John Stultz <johnstul@us.ibm.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@elte.hu> Cc: Roman Zippel <zippel@linux-m68k.org> Cc: Adrian Bunk <bunk@stusta.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
9f907c0144
commit
411187fb05
4 changed files with 50 additions and 1 deletions
|
@ -146,6 +146,9 @@ extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl,
|
||||||
/* Soft interrupt function to run the hrtimer queues: */
|
/* Soft interrupt function to run the hrtimer queues: */
|
||||||
extern void hrtimer_run_queues(void);
|
extern void hrtimer_run_queues(void);
|
||||||
|
|
||||||
|
/* Resume notification */
|
||||||
|
void hrtimer_notify_resume(void);
|
||||||
|
|
||||||
/* Bootup initialization: */
|
/* Bootup initialization: */
|
||||||
extern void __init hrtimers_init(void);
|
extern void __init hrtimers_init(void);
|
||||||
|
|
||||||
|
|
|
@ -92,6 +92,7 @@ extern struct timespec xtime;
|
||||||
extern struct timespec wall_to_monotonic;
|
extern struct timespec wall_to_monotonic;
|
||||||
extern seqlock_t xtime_lock __attribute__((weak));
|
extern seqlock_t xtime_lock __attribute__((weak));
|
||||||
|
|
||||||
|
extern unsigned long read_persistent_clock(void);
|
||||||
void timekeeping_init(void);
|
void timekeeping_init(void);
|
||||||
|
|
||||||
static inline unsigned long get_seconds(void)
|
static inline unsigned long get_seconds(void)
|
||||||
|
|
|
@ -291,6 +291,14 @@ static unsigned long ktime_divns(const ktime_t kt, s64 div)
|
||||||
# define ktime_divns(kt, div) (unsigned long)((kt).tv64 / (div))
|
# define ktime_divns(kt, div) (unsigned long)((kt).tv64 / (div))
|
||||||
#endif /* BITS_PER_LONG >= 64 */
|
#endif /* BITS_PER_LONG >= 64 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Timekeeping resumed notification
|
||||||
|
*/
|
||||||
|
void hrtimer_notify_resume(void)
|
||||||
|
{
|
||||||
|
clock_was_set();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Counterpart to lock_timer_base above:
|
* Counterpart to lock_timer_base above:
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -878,12 +878,27 @@ int timekeeping_is_continuous(void)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read_persistent_clock - Return time in seconds from the persistent clock.
|
||||||
|
*
|
||||||
|
* Weak dummy function for arches that do not yet support it.
|
||||||
|
* Returns seconds from epoch using the battery backed persistent clock.
|
||||||
|
* Returns zero if unsupported.
|
||||||
|
*
|
||||||
|
* XXX - Do be sure to remove it once all arches implement it.
|
||||||
|
*/
|
||||||
|
unsigned long __attribute__((weak)) read_persistent_clock(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* timekeeping_init - Initializes the clocksource and common timekeeping values
|
* timekeeping_init - Initializes the clocksource and common timekeeping values
|
||||||
*/
|
*/
|
||||||
void __init timekeeping_init(void)
|
void __init timekeeping_init(void)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
unsigned long sec = read_persistent_clock();
|
||||||
|
|
||||||
write_seqlock_irqsave(&xtime_lock, flags);
|
write_seqlock_irqsave(&xtime_lock, flags);
|
||||||
|
|
||||||
|
@ -893,11 +908,20 @@ void __init timekeeping_init(void)
|
||||||
clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
|
clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
|
||||||
clock->cycle_last = clocksource_read(clock);
|
clock->cycle_last = clocksource_read(clock);
|
||||||
|
|
||||||
|
xtime.tv_sec = sec;
|
||||||
|
xtime.tv_nsec = 0;
|
||||||
|
set_normalized_timespec(&wall_to_monotonic,
|
||||||
|
-xtime.tv_sec, -xtime.tv_nsec);
|
||||||
|
|
||||||
write_sequnlock_irqrestore(&xtime_lock, flags);
|
write_sequnlock_irqrestore(&xtime_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* flag for if timekeeping is suspended */
|
||||||
static int timekeeping_suspended;
|
static int timekeeping_suspended;
|
||||||
|
/* time in seconds when suspend began */
|
||||||
|
static unsigned long timekeeping_suspend_time;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* timekeeping_resume - Resumes the generic timekeeping subsystem.
|
* timekeeping_resume - Resumes the generic timekeeping subsystem.
|
||||||
* @dev: unused
|
* @dev: unused
|
||||||
|
@ -909,13 +933,25 @@ static int timekeeping_suspended;
|
||||||
static int timekeeping_resume(struct sys_device *dev)
|
static int timekeeping_resume(struct sys_device *dev)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
unsigned long now = read_persistent_clock();
|
||||||
|
|
||||||
write_seqlock_irqsave(&xtime_lock, flags);
|
write_seqlock_irqsave(&xtime_lock, flags);
|
||||||
/* restart the last cycle value */
|
|
||||||
|
if (now && (now > timekeeping_suspend_time)) {
|
||||||
|
unsigned long sleep_length = now - timekeeping_suspend_time;
|
||||||
|
|
||||||
|
xtime.tv_sec += sleep_length;
|
||||||
|
wall_to_monotonic.tv_sec -= sleep_length;
|
||||||
|
}
|
||||||
|
/* re-base the last cycle value */
|
||||||
clock->cycle_last = clocksource_read(clock);
|
clock->cycle_last = clocksource_read(clock);
|
||||||
clock->error = 0;
|
clock->error = 0;
|
||||||
timekeeping_suspended = 0;
|
timekeeping_suspended = 0;
|
||||||
write_sequnlock_irqrestore(&xtime_lock, flags);
|
write_sequnlock_irqrestore(&xtime_lock, flags);
|
||||||
|
|
||||||
|
touch_softlockup_watchdog();
|
||||||
|
hrtimer_notify_resume();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -925,6 +961,7 @@ static int timekeeping_suspend(struct sys_device *dev, pm_message_t state)
|
||||||
|
|
||||||
write_seqlock_irqsave(&xtime_lock, flags);
|
write_seqlock_irqsave(&xtime_lock, flags);
|
||||||
timekeeping_suspended = 1;
|
timekeeping_suspended = 1;
|
||||||
|
timekeeping_suspend_time = read_persistent_clock();
|
||||||
write_sequnlock_irqrestore(&xtime_lock, flags);
|
write_sequnlock_irqrestore(&xtime_lock, flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue