clocksource: add enable() and disable() callbacks

Add enable() and disable() callbacks for clocksources.

This allows us to put unused clocksources in power save mode.  The
functions clocksource_enable() and clocksource_disable() wrap the
callbacks and are inserted in the timekeeping code to enable before use
and disable after switching to a new clocksource.

Signed-off-by: Magnus Damm <damm@igel.co.jp>
Acked-by: John Stultz <johnstul@us.ibm.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Magnus Damm 2009-04-21 12:24:02 -07:00 коммит произвёл Linus Torvalds
Родитель 8e19608e8b
Коммит 4614e6adaf
2 изменённых файлов: 40 добавлений и 3 удалений

Просмотреть файл

@ -144,6 +144,8 @@ extern u64 timecounter_cyc2time(struct timecounter *tc,
* The ideal clocksource. A must-use where * The ideal clocksource. A must-use where
* available. * available.
* @read: returns a cycle value, passes clocksource as argument * @read: returns a cycle value, passes clocksource as argument
* @enable: optional function to enable the clocksource
* @disable: optional function to disable the clocksource
* @mask: bitmask for two's complement * @mask: bitmask for two's complement
* subtraction of non 64 bit counters * subtraction of non 64 bit counters
* @mult: cycle to nanosecond multiplier (adjusted by NTP) * @mult: cycle to nanosecond multiplier (adjusted by NTP)
@ -163,6 +165,8 @@ struct clocksource {
struct list_head list; struct list_head list;
int rating; int rating;
cycle_t (*read)(struct clocksource *cs); cycle_t (*read)(struct clocksource *cs);
int (*enable)(struct clocksource *cs);
void (*disable)(struct clocksource *cs);
cycle_t mask; cycle_t mask;
u32 mult; u32 mult;
u32 mult_orig; u32 mult_orig;
@ -274,6 +278,33 @@ static inline cycle_t clocksource_read(struct clocksource *cs)
return cs->read(cs); return cs->read(cs);
} }
/**
* clocksource_enable: - enable clocksource
* @cs: pointer to clocksource
*
* Enables the specified clocksource. The clocksource callback
* function should start up the hardware and setup mult and field
* members of struct clocksource to reflect hardware capabilities.
*/
static inline int clocksource_enable(struct clocksource *cs)
{
return cs->enable ? cs->enable(cs) : 0;
}
/**
* clocksource_disable: - disable clocksource
* @cs: pointer to clocksource
*
* Disables the specified clocksource. The clocksource callback
* function should power down the now unused hardware block to
* save power.
*/
static inline void clocksource_disable(struct clocksource *cs)
{
if (cs->disable)
cs->disable(cs);
}
/** /**
* cyc2ns - converts clocksource cycles to nanoseconds * cyc2ns - converts clocksource cycles to nanoseconds
* @cs: Pointer to clocksource * @cs: Pointer to clocksource

Просмотреть файл

@ -182,7 +182,7 @@ EXPORT_SYMBOL(do_settimeofday);
*/ */
static void change_clocksource(void) static void change_clocksource(void)
{ {
struct clocksource *new; struct clocksource *new, *old;
new = clocksource_get_next(); new = clocksource_get_next();
@ -191,11 +191,16 @@ static void change_clocksource(void)
clocksource_forward_now(); clocksource_forward_now();
new->raw_time = clock->raw_time; if (clocksource_enable(new))
return;
new->raw_time = clock->raw_time;
old = clock;
clock = new; clock = new;
clocksource_disable(old);
clock->cycle_last = 0; clock->cycle_last = 0;
clock->cycle_last = clocksource_read(new); clock->cycle_last = clocksource_read(clock);
clock->error = 0; clock->error = 0;
clock->xtime_nsec = 0; clock->xtime_nsec = 0;
clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH); clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
@ -292,6 +297,7 @@ void __init timekeeping_init(void)
ntp_init(); ntp_init();
clock = clocksource_get_next(); clock = clocksource_get_next();
clocksource_enable(clock);
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);