Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b49c87c2 authored by Kevin Hilman's avatar Kevin Hilman Committed by Russell King
Browse files

[ARM] 4260/1: clocksource support for Versatile platform



Update Versatile to use new clocksource infrastructure for basic timekeeping.

Signed-off-by: default avatarKevin Hilman <khilman@mvista.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent e32f1502
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -166,6 +166,7 @@ config ARCH_VERSATILE
	select ARM_AMBA
	select ARM_VIC
	select ICST307
	select GENERIC_TIME
	help
	  This enables support for ARM Ltd Versatile board.

+34 −41
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <linux/interrupt.h>
#include <linux/amba/bus.h>
#include <linux/amba/clcd.h>
#include <linux/clocksource.h>

#include <asm/cnt32_to_63.h>
#include <asm/system.h>
@@ -828,46 +829,6 @@ void __init versatile_init(void)
#define TICKS2USECS(x)	((x) / TICKS_PER_uSEC)
#endif

/*
 * Returns number of ms since last clock interrupt.  Note that interrupts
 * will have been disabled by do_gettimeoffset()
 */
static unsigned long versatile_gettimeoffset(void)
{
	unsigned long ticks1, ticks2, status;

	/*
	 * Get the current number of ticks.  Note that there is a race
	 * condition between us reading the timer and checking for
	 * an interrupt.  We get around this by ensuring that the
	 * counter has not reloaded between our two reads.
	 */
	ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
	do {
		ticks1 = ticks2;
		status = __raw_readl(VA_IC_BASE + VIC_RAW_STATUS);
		ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
	} while (ticks2 > ticks1);

	/*
	 * Number of ticks since last interrupt.
	 */
	ticks1 = TIMER_RELOAD - ticks2;

	/*
	 * Interrupt pending?  If so, we've reloaded once already.
	 *
	 * FIXME: Need to check this is effectively timer 0 that expires
	 */
	if (status & IRQMASK_TIMERINT0_1)
		ticks1 += TIMER_RELOAD;

	/*
	 * Convert the ticks to usecs
	 */
	return TICKS2USECS(ticks1);
}

/*
 * IRQ handler for the timer
 */
@@ -891,6 +852,36 @@ static struct irqaction versatile_timer_irq = {
	.handler	= versatile_timer_interrupt,
};

static cycle_t versatile_get_cycles(void)
{
	return ~readl(TIMER3_VA_BASE + TIMER_VALUE);
}

static struct clocksource clocksource_versatile = {
	.name 		= "timer3",
 	.rating		= 200,
 	.read		= versatile_get_cycles,
	.mask		= CLOCKSOURCE_MASK(32),
 	.shift 		= 20,
	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
};

static int __init versatile_clocksource_init(void)
{
	/* setup timer3 as free-running clocksource */
	writel(0, TIMER3_VA_BASE + TIMER_CTRL);
	writel(0xffffffff, TIMER3_VA_BASE + TIMER_LOAD);
	writel(0xffffffff, TIMER3_VA_BASE + TIMER_VALUE);
	writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
	       TIMER3_VA_BASE + TIMER_CTRL);

 	clocksource_versatile.mult =
 		clocksource_khz2mult(1000, clocksource_versatile.shift);
 	clocksource_register(&clocksource_versatile);

 	return 0;
}

/*
 * Set up timer interrupt, and return the current time in seconds.
 */
@@ -927,9 +918,11 @@ static void __init versatile_timer_init(void)
	 * Make irqs happen for the system timer
	 */
	setup_irq(IRQ_TIMERINT0_1, &versatile_timer_irq);

	versatile_clocksource_init();
}

struct sys_timer versatile_timer = {
	.init		= versatile_timer_init,
	.offset		= versatile_gettimeoffset,
};