Thread (8 messages) flat view 8 messages, 4 authors, 2011-01-04

ks8695_gettimeoffset

From: Russell King - ARM Linux <hidden>
Date: 2011-01-03 00:28:58

On Mon, Dec 27, 2010 at 04:37:25PM +0100, Yegor Yefremov wrote:
Am 20.12.2010 20:30, schrieb Russell King - ARM Linux:
quoted
On Mon, Dec 20, 2010 at 01:09:47PM -0600, Dick Hollenbeck wrote:
quoted
quoted
From userspace, printing the return values from a rapid looping
sequence of calls to

   clock_gettime( CLOCK_MONOTONIC, &now );

leads me to believe that kernel function ks8695_gettimeoffset() is
not worth anything.
That'll be because clock_gettime(CLOCK_MONOTONIC) doesn't use the old
gettimeoffset() method to correct the returned time - none of the POSIX
timers use the old gettimeoffset() stuff, only gettimeofday() does.

Platforms really should be using the clocksource/clockevents code
where ever possible, rather than selecting ARCH_USES_GETTIMEOFFSET.

Does someone with a KS8695-based platform want to have a go at
converting it over to clocksource/clockevents?
Is it possible at all to implement clocksource/clockevents for KS8695?
As Dick and "Register Description" already said you cannot read the
time register, so clocksource->read cannot be implemented to return
ticks elapsed. Or do I see it wrong? 
If you have no register which ticks at a fixed rate, then you have no
hope to use the clocksource/clockevents code, and will be stuck with
the old gettimeoffset() stuff.

Note that even a 16-bit 32768Hz counter would be a candidate for a
clocksource (it'd be an improvement over either a buggy gettimeoffset()
or no gettimeoffset().)
Is there any documentation for clocksource/clockevents? 
That's a question I've asked many times.

The answer is nothing beyond the comments in the header files
(include/linux/clocksource.h, include/linux/clockchips.h), source files
(kernel/time/), commits covering the same, the already merged
implementations, and some stuff in Documentation/timers/.

Clocksources themselves are very simple:

static cycle_t cksrc_foo_read(struct clocksource *cs)
{
	return readl(cycle_counter);
}

and add maths to make sure the returned value is incrementing if it
isn't.  Optionally implement the enable/disable callbacks if you can
turn on/off this clocksource:

static int cksrc_foo_enable(struct clocksource *cs)
{
	writel(enable_val, enable_reg);
}

static void clksrc_foo_disable(struct clocksource *cs)
{
	writel(disable_val, enable_reg);
}

Declare the clocksource structure:

static struct clocksource cksrc_foo = {
	.name		= "some_descriptive_name",
	.rating 	= 200,
	.read		= cksrc_foo_read,
	.enable 	= cksrc_foo_enable,
	.disable	= cksrc_foo_disable,
	.mask		= CLOCKSOURCE_MASK(number_of_bits_in_cycle_counter),
	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
};

Finally, register it in the sys_timer init method:

	clocksource_register_hz(&cksrc_foo, cycle_counter_tick_rate_in_hz);
or
	clocksource_register_khz(&cksrc_foo, cycle_counter_tick_rate_in_khz);

Once you have that in place, you can kill off the gettimeoffset() stuff
and ensure that you don't enable the ARCH_USES_GETTIMEOFFSET config symbol.

The gotcha here is that the cycle counter must not overflow between any
two timer interrupts - so make sure that it won't wrap within your normal
periodic timer tick rate.  If it does wrap, you won't keep good time.

The clockevent support is similar - but more complicated to explain in an
email without knowing the details of the hardware (because there's too
many possibilities.)  I believe the clockevent stuff needs the clocksource
stuff to be in place first though.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help