forked from luck/tmp_suning_uos_patched
[ARM] 4259/1: clockevent support for ixp4xx platform
Update ixp4xx timer support to use new clockevent infrastructure. Signed-off-by: Kevin Hilman <khilman@mvista.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
parent
9e4559ddff
commit
e32f1502be
|
@ -266,6 +266,7 @@ config ARCH_IXP4XX
|
|||
bool "IXP4xx-based"
|
||||
depends on MMU
|
||||
select GENERIC_TIME
|
||||
select GENERIC_CLOCKEVENTS
|
||||
help
|
||||
Support for Intel's IXP4XX (XScale) family of processors.
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/time.h>
|
||||
#include <linux/timex.h>
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/clockchips.h>
|
||||
|
||||
#include <asm/arch/udc.h>
|
||||
#include <asm/hardware.h>
|
||||
|
@ -41,6 +42,8 @@
|
|||
#include <asm/mach/time.h>
|
||||
|
||||
static int __init ixp4xx_clocksource_init(void);
|
||||
static int __init ixp4xx_clockevent_init(void);
|
||||
static struct clock_event_device clockevent_ixp4xx;
|
||||
|
||||
/*************************************************************************
|
||||
* IXP4xx chipset I/O mapping
|
||||
|
@ -239,52 +242,40 @@ void __init ixp4xx_init_irq(void)
|
|||
* counter as a source of real clock ticks to account for missed jiffies.
|
||||
*************************************************************************/
|
||||
|
||||
static unsigned volatile last_jiffy_time;
|
||||
|
||||
#define CLOCK_TICKS_PER_USEC ((CLOCK_TICK_RATE + USEC_PER_SEC/2) / USEC_PER_SEC)
|
||||
|
||||
static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
write_seqlock(&xtime_lock);
|
||||
struct clock_event_device *evt = &clockevent_ixp4xx;
|
||||
|
||||
/* Clear Pending Interrupt by writing '1' to it */
|
||||
*IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND;
|
||||
|
||||
/*
|
||||
* Catch up with the real idea of time
|
||||
*/
|
||||
while ((signed long)(*IXP4XX_OSTS - last_jiffy_time) >= LATCH) {
|
||||
timer_tick();
|
||||
last_jiffy_time += LATCH;
|
||||
}
|
||||
|
||||
write_sequnlock(&xtime_lock);
|
||||
evt->event_handler(evt);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct irqaction ixp4xx_timer_irq = {
|
||||
.name = "IXP4xx Timer Tick",
|
||||
.name = "timer1",
|
||||
.flags = IRQF_DISABLED | IRQF_TIMER,
|
||||
.handler = ixp4xx_timer_interrupt,
|
||||
};
|
||||
|
||||
static void __init ixp4xx_timer_init(void)
|
||||
{
|
||||
/* Reset/disable counter */
|
||||
*IXP4XX_OSRT1 = 0;
|
||||
|
||||
/* Clear Pending Interrupt by writing '1' to it */
|
||||
*IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND;
|
||||
|
||||
/* Setup the Timer counter value */
|
||||
*IXP4XX_OSRT1 = (LATCH & ~IXP4XX_OST_RELOAD_MASK) | IXP4XX_OST_ENABLE;
|
||||
|
||||
/* Reset time-stamp counter */
|
||||
*IXP4XX_OSTS = 0;
|
||||
last_jiffy_time = 0;
|
||||
|
||||
/* Connect the interrupt handler and enable the interrupt */
|
||||
setup_irq(IRQ_IXP4XX_TIMER1, &ixp4xx_timer_irq);
|
||||
|
||||
ixp4xx_clocksource_init();
|
||||
ixp4xx_clockevent_init();
|
||||
}
|
||||
|
||||
struct sys_timer ixp4xx_timer = {
|
||||
|
@ -384,6 +375,9 @@ void __init ixp4xx_sys_init(void)
|
|||
ixp4xx_exp_bus_size >> 20);
|
||||
}
|
||||
|
||||
/*
|
||||
* clocksource
|
||||
*/
|
||||
cycle_t ixp4xx_get_cycles(void)
|
||||
{
|
||||
return *IXP4XX_OSTS;
|
||||
|
@ -408,3 +402,64 @@ static int __init ixp4xx_clocksource_init(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* clockevents
|
||||
*/
|
||||
static int ixp4xx_set_next_event(unsigned long evt,
|
||||
struct clock_event_device *unused)
|
||||
{
|
||||
unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK;
|
||||
|
||||
*IXP4XX_OSRT1 = (evt & ~IXP4XX_OST_RELOAD_MASK) | opts;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ixp4xx_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
unsigned long opts, osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK;
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
osrt = LATCH & ~IXP4XX_OST_RELOAD_MASK;
|
||||
opts = IXP4XX_OST_ENABLE;
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
/* period set by 'set next_event' */
|
||||
osrt = 0;
|
||||
opts = IXP4XX_OST_ENABLE | IXP4XX_OST_ONE_SHOT;
|
||||
break;
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
default:
|
||||
osrt = opts = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
*IXP4XX_OSRT1 = osrt | opts;
|
||||
}
|
||||
|
||||
static struct clock_event_device clockevent_ixp4xx = {
|
||||
.name = "ixp4xx timer1",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
||||
.rating = 200,
|
||||
.shift = 24,
|
||||
.set_mode = ixp4xx_set_mode,
|
||||
.set_next_event = ixp4xx_set_next_event,
|
||||
};
|
||||
|
||||
static int __init ixp4xx_clockevent_init(void)
|
||||
{
|
||||
clockevent_ixp4xx.mult = div_sc(FREQ, NSEC_PER_SEC,
|
||||
clockevent_ixp4xx.shift);
|
||||
clockevent_ixp4xx.max_delta_ns =
|
||||
clockevent_delta2ns(0xfffffffe, &clockevent_ixp4xx);
|
||||
clockevent_ixp4xx.min_delta_ns =
|
||||
clockevent_delta2ns(0xf, &clockevent_ixp4xx);
|
||||
clockevent_ixp4xx.cpumask = cpumask_of_cpu(0);
|
||||
|
||||
clockevents_register_device(&clockevent_ixp4xx);
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user