Commit 52e43a11 authored by Olof Johansson's avatar Olof Johansson

Merge branch 'ARM/clkevt/set-state-4.3' of...

Merge branch 'ARM/clkevt/set-state-4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/linux into next/cleanup

Merge "ARM: clockevents: Migrate to 'set-state' callbacks" from Viresh Kumar:

This series migrates ARM clockevent drivers (present in arch/arm/
directory), to the new set-state interface. This would enable these
drivers to use new states (like: ONESHOT_STOPPED, etc.) of a clockevent
device (if required), as the set-mode interface is marked obsolete now
and wouldn't be expanded to handle new states.

* 'ARM/clkevt/set-state-4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/linux:
  ARM/orion/time: Migrate to new 'set-state' interface
  ARM/iop/time: Migrate to new 'set-state' interface
  ARM/w90x900/time: Migrate to new 'set-state' interface
  ARM/SPEAr/time: Migrate to new 'set-state' interface
  ARM/omap2/timer: Migrate to new 'set-state' interface
  ARM/omap1/timer32: Migrate to new 'set-state' interface
  ARM/omap1/time: Migrate to new 'set-state' interface
  ARM/netx/time: Migrate to new 'set-state' interface
  ARM/mmp/time: Migrate to new 'set-state' interface
  ARM/lpc32xx/timer: Migrate to new 'set-state' interface
  ARM/ks8695/time: Migrate to new 'set-state' interface
  ARM/ixp4xx/timer: Migrate to new 'set-state' interface
  ARM/imx/epit: Migrate to new 'set-state' interface
  ARM/gemini/time: Migrate to new 'set-state' interface
  ARM/dc21285-timer: Migrate to new 'set-state' interface
  ARM/davinci/time: Migrate to new 'set-state' interface
  ARM/cns3xxx/timer: Migrate to new 'set-state' interface
  ARM/smp_twd: Migrate to new 'set-state' interface
Signed-off-by: default avatarOlof Johansson <olof@lixom.net>
parents b3f81739 10dca88a
...@@ -36,29 +36,30 @@ static DEFINE_PER_CPU(bool, percpu_setup_called); ...@@ -36,29 +36,30 @@ static DEFINE_PER_CPU(bool, percpu_setup_called);
static struct clock_event_device __percpu *twd_evt; static struct clock_event_device __percpu *twd_evt;
static int twd_ppi; static int twd_ppi;
static void twd_set_mode(enum clock_event_mode mode, static int twd_shutdown(struct clock_event_device *clk)
struct clock_event_device *clk)
{ {
unsigned long ctrl; writel_relaxed(0, twd_base + TWD_TIMER_CONTROL);
return 0;
switch (mode) { }
case CLOCK_EVT_MODE_PERIODIC:
ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE
| TWD_TIMER_CONTROL_PERIODIC;
writel_relaxed(DIV_ROUND_CLOSEST(twd_timer_rate, HZ),
twd_base + TWD_TIMER_LOAD);
break;
case CLOCK_EVT_MODE_ONESHOT:
/* period set, and timer enabled in 'next_event' hook */
ctrl = TWD_TIMER_CONTROL_IT_ENABLE | TWD_TIMER_CONTROL_ONESHOT;
break;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
default:
ctrl = 0;
}
static int twd_set_oneshot(struct clock_event_device *clk)
{
/* period set, and timer enabled in 'next_event' hook */
writel_relaxed(TWD_TIMER_CONTROL_IT_ENABLE | TWD_TIMER_CONTROL_ONESHOT,
twd_base + TWD_TIMER_CONTROL);
return 0;
}
static int twd_set_periodic(struct clock_event_device *clk)
{
unsigned long ctrl = TWD_TIMER_CONTROL_ENABLE |
TWD_TIMER_CONTROL_IT_ENABLE |
TWD_TIMER_CONTROL_PERIODIC;
writel_relaxed(DIV_ROUND_CLOSEST(twd_timer_rate, HZ),
twd_base + TWD_TIMER_LOAD);
writel_relaxed(ctrl, twd_base + TWD_TIMER_CONTROL); writel_relaxed(ctrl, twd_base + TWD_TIMER_CONTROL);
return 0;
} }
static int twd_set_next_event(unsigned long evt, static int twd_set_next_event(unsigned long evt,
...@@ -94,7 +95,7 @@ static void twd_timer_stop(void) ...@@ -94,7 +95,7 @@ static void twd_timer_stop(void)
{ {
struct clock_event_device *clk = raw_cpu_ptr(twd_evt); struct clock_event_device *clk = raw_cpu_ptr(twd_evt);
twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk); twd_shutdown(clk);
disable_percpu_irq(clk->irq); disable_percpu_irq(clk->irq);
} }
...@@ -296,7 +297,10 @@ static void twd_timer_setup(void) ...@@ -296,7 +297,10 @@ static void twd_timer_setup(void)
clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
CLOCK_EVT_FEAT_C3STOP; CLOCK_EVT_FEAT_C3STOP;
clk->rating = 350; clk->rating = 350;
clk->set_mode = twd_set_mode; clk->set_state_shutdown = twd_shutdown;
clk->set_state_periodic = twd_set_periodic;
clk->set_state_oneshot = twd_set_oneshot;
clk->tick_resume = twd_shutdown;
clk->set_next_event = twd_set_next_event; clk->set_next_event = twd_set_next_event;
clk->irq = twd_ppi; clk->irq = twd_ppi;
clk->cpumask = cpumask_of(cpu); clk->cpumask = cpumask_of(cpu);
......
...@@ -113,30 +113,33 @@ void cns3xxx_power_off(void) ...@@ -113,30 +113,33 @@ void cns3xxx_power_off(void)
*/ */
static void __iomem *cns3xxx_tmr1; static void __iomem *cns3xxx_tmr1;
static void cns3xxx_timer_set_mode(enum clock_event_mode mode, static int cns3xxx_shutdown(struct clock_event_device *clk)
struct clock_event_device *clk) {
writel(0, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
return 0;
}
static int cns3xxx_set_oneshot(struct clock_event_device *clk)
{
unsigned long ctrl = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
/* period set, and timer enabled in 'next_event' hook */
ctrl |= (1 << 2) | (1 << 9);
writel(ctrl, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
return 0;
}
static int cns3xxx_set_periodic(struct clock_event_device *clk)
{ {
unsigned long ctrl = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET); unsigned long ctrl = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
int pclk = cns3xxx_cpu_clock() / 8; int pclk = cns3xxx_cpu_clock() / 8;
int reload; int reload;
switch (mode) { reload = pclk * 20 / (3 * HZ) * 0x25000;
case CLOCK_EVT_MODE_PERIODIC: writel(reload, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET);
reload = pclk * 20 / (3 * HZ) * 0x25000; ctrl |= (1 << 0) | (1 << 2) | (1 << 9);
writel(reload, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET);
ctrl |= (1 << 0) | (1 << 2) | (1 << 9);
break;
case CLOCK_EVT_MODE_ONESHOT:
/* period set, and timer enabled in 'next_event' hook */
ctrl |= (1 << 2) | (1 << 9);
break;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
default:
ctrl = 0;
}
writel(ctrl, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET); writel(ctrl, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET);
return 0;
} }
static int cns3xxx_timer_set_next_event(unsigned long evt, static int cns3xxx_timer_set_next_event(unsigned long evt,
...@@ -151,12 +154,16 @@ static int cns3xxx_timer_set_next_event(unsigned long evt, ...@@ -151,12 +154,16 @@ static int cns3xxx_timer_set_next_event(unsigned long evt,
} }
static struct clock_event_device cns3xxx_tmr1_clockevent = { static struct clock_event_device cns3xxx_tmr1_clockevent = {
.name = "cns3xxx timer1", .name = "cns3xxx timer1",
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .features = CLOCK_EVT_FEAT_PERIODIC |
.set_mode = cns3xxx_timer_set_mode, CLOCK_EVT_FEAT_ONESHOT,
.set_next_event = cns3xxx_timer_set_next_event, .set_state_shutdown = cns3xxx_shutdown,
.rating = 350, .set_state_periodic = cns3xxx_set_periodic,
.cpumask = cpu_all_mask, .set_state_oneshot = cns3xxx_set_oneshot,
.tick_resume = cns3xxx_shutdown,
.set_next_event = cns3xxx_timer_set_next_event,
.rating = 350,
.cpumask = cpu_all_mask,
}; };
static void __init cns3xxx_clockevents_init(unsigned int timer_irq) static void __init cns3xxx_clockevents_init(unsigned int timer_irq)
......
...@@ -303,36 +303,42 @@ static int davinci_set_next_event(unsigned long cycles, ...@@ -303,36 +303,42 @@ static int davinci_set_next_event(unsigned long cycles,
return 0; return 0;
} }
static void davinci_set_mode(enum clock_event_mode mode, static int davinci_shutdown(struct clock_event_device *evt)
struct clock_event_device *evt)
{ {
struct timer_s *t = &timers[TID_CLOCKEVENT]; struct timer_s *t = &timers[TID_CLOCKEVENT];
switch (mode) { t->opts &= ~TIMER_OPTS_STATE_MASK;
case CLOCK_EVT_MODE_PERIODIC: t->opts |= TIMER_OPTS_DISABLED;
t->period = davinci_clock_tick_rate / (HZ); return 0;
t->opts &= ~TIMER_OPTS_STATE_MASK; }
t->opts |= TIMER_OPTS_PERIODIC;
timer32_config(t); static int davinci_set_oneshot(struct clock_event_device *evt)
break; {
case CLOCK_EVT_MODE_ONESHOT: struct timer_s *t = &timers[TID_CLOCKEVENT];
t->opts &= ~TIMER_OPTS_STATE_MASK;
t->opts |= TIMER_OPTS_ONESHOT; t->opts &= ~TIMER_OPTS_STATE_MASK;
break; t->opts |= TIMER_OPTS_ONESHOT;
case CLOCK_EVT_MODE_UNUSED: return 0;
case CLOCK_EVT_MODE_SHUTDOWN: }
t->opts &= ~TIMER_OPTS_STATE_MASK;
t->opts |= TIMER_OPTS_DISABLED; static int davinci_set_periodic(struct clock_event_device *evt)
break; {
case CLOCK_EVT_MODE_RESUME: struct timer_s *t = &timers[TID_CLOCKEVENT];
break;
} t->period = davinci_clock_tick_rate / (HZ);
t->opts &= ~TIMER_OPTS_STATE_MASK;
t->opts |= TIMER_OPTS_PERIODIC;
timer32_config(t);
return 0;
} }
static struct clock_event_device clockevent_davinci = { static struct clock_event_device clockevent_davinci = {
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .features = CLOCK_EVT_FEAT_PERIODIC |
.set_next_event = davinci_set_next_event, CLOCK_EVT_FEAT_ONESHOT,
.set_mode = davinci_set_mode, .set_next_event = davinci_set_next_event,
.set_state_shutdown = davinci_shutdown,
.set_state_periodic = davinci_set_periodic,
.set_state_oneshot = davinci_set_oneshot,
}; };
......
...@@ -57,34 +57,32 @@ static int ckevt_dc21285_set_next_event(unsigned long delta, ...@@ -57,34 +57,32 @@ static int ckevt_dc21285_set_next_event(unsigned long delta,
return 0; return 0;
} }
static void ckevt_dc21285_set_mode(enum clock_event_mode mode, static int ckevt_dc21285_shutdown(struct clock_event_device *c)
struct clock_event_device *c)
{ {
switch (mode) { *CSR_TIMER1_CNTL = 0;
case CLOCK_EVT_MODE_RESUME: return 0;
case CLOCK_EVT_MODE_PERIODIC: }
*CSR_TIMER1_CLR = 0;
*CSR_TIMER1_LOAD = (mem_fclk_21285 + 8 * HZ) / (16 * HZ); static int ckevt_dc21285_set_periodic(struct clock_event_device *c)
*CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | {
TIMER_CNTL_DIV16; *CSR_TIMER1_CLR = 0;
break; *CSR_TIMER1_LOAD = (mem_fclk_21285 + 8 * HZ) / (16 * HZ);
*CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD |
case CLOCK_EVT_MODE_ONESHOT: TIMER_CNTL_DIV16;
case CLOCK_EVT_MODE_UNUSED: return 0;
case CLOCK_EVT_MODE_SHUTDOWN:
*CSR_TIMER1_CNTL = 0;
break;
}
} }
static struct clock_event_device ckevt_dc21285 = { static struct clock_event_device ckevt_dc21285 = {
.name = "dc21285_timer1", .name = "dc21285_timer1",
.features = CLOCK_EVT_FEAT_PERIODIC | .features = CLOCK_EVT_FEAT_PERIODIC |
CLOCK_EVT_FEAT_ONESHOT, CLOCK_EVT_FEAT_ONESHOT,
.rating = 200, .rating = 200,
.irq = IRQ_TIMER1, .irq = IRQ_TIMER1,
.set_next_event = ckevt_dc21285_set_next_event, .set_next_event = ckevt_dc21285_set_next_event,
.set_mode = ckevt_dc21285_set_mode, .set_state_shutdown = ckevt_dc21285_shutdown,
.set_state_periodic = ckevt_dc21285_set_periodic,
.set_state_oneshot = ckevt_dc21285_shutdown,
.tick_resume = ckevt_dc21285_set_periodic,
}; };
static irqreturn_t timer1_interrupt(int irq, void *dev_id) static irqreturn_t timer1_interrupt(int irq, void *dev_id)
...@@ -94,7 +92,7 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id) ...@@ -94,7 +92,7 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id)
*CSR_TIMER1_CLR = 0; *CSR_TIMER1_CLR = 0;
/* Stop the timer if in one-shot mode */ /* Stop the timer if in one-shot mode */
if (ce->mode == CLOCK_EVT_MODE_ONESHOT) if (clockevent_state_oneshot(ce))
*CSR_TIMER1_CNTL = 0; *CSR_TIMER1_CNTL = 0;
ce->event_handler(ce); ce->event_handler(ce);
......
...@@ -59,49 +59,48 @@ static int gemini_timer_set_next_event(unsigned long cycles, ...@@ -59,49 +59,48 @@ static int gemini_timer_set_next_event(unsigned long cycles,
return 0; return 0;
} }
static void gemini_timer_set_mode(enum clock_event_mode mode, static int gemini_timer_shutdown(struct clock_event_device *evt)
struct clock_event_device *evt) {
u32 cr;
/*
* Disable also for oneshot: the set_next() call will arm the timer
* instead.
*/
cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
cr &= ~TIMER_2_CR_ENABLE;
cr &= ~TIMER_2_CR_INT;
writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
return 0;
}
static int gemini_timer_set_periodic(struct clock_event_device *evt)
{ {
u32 period = DIV_ROUND_CLOSEST(tick_rate, HZ); u32 period = DIV_ROUND_CLOSEST(tick_rate, HZ);
u32 cr; u32 cr;
switch (mode) { /* Start the timer */
case CLOCK_EVT_MODE_PERIODIC: writel(period, TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER2_BASE)));
/* Start the timer */ writel(period, TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER2_BASE)));
writel(period, cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER2_BASE))); cr |= TIMER_2_CR_ENABLE;
writel(period, cr |= TIMER_2_CR_INT;
TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER2_BASE))); writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE))); return 0;
cr |= TIMER_2_CR_ENABLE;
cr |= TIMER_2_CR_INT;
writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
break;
case CLOCK_EVT_MODE_ONESHOT:
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_RESUME:
/*
* Disable also for oneshot: the set_next() call will
* arm the timer instead.
*/
cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
cr &= ~TIMER_2_CR_ENABLE;
cr &= ~TIMER_2_CR_INT;
writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
break;
default:
break;
}
} }
/* Use TIMER2 as clock event */ /* Use TIMER2 as clock event */
static struct clock_event_device gemini_clockevent = { static struct clock_event_device gemini_clockevent = {
.name = "TIMER2", .name = "TIMER2",
.rating = 300, /* Reasonably fast and accurate clock event */ /* Reasonably fast and accurate clock event */
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .rating = 300,
.set_next_event = gemini_timer_set_next_event, .features = CLOCK_EVT_FEAT_PERIODIC |
.set_mode = gemini_timer_set_mode, CLOCK_EVT_FEAT_ONESHOT,
.set_next_event = gemini_timer_set_next_event,
.set_state_shutdown = gemini_timer_shutdown,
.set_state_periodic = gemini_timer_set_periodic,
.set_state_oneshot = gemini_timer_shutdown,
.tick_resume = gemini_timer_shutdown,
}; };
/* /*
......
...@@ -57,7 +57,6 @@ ...@@ -57,7 +57,6 @@
#include "hardware.h" #include "hardware.h"
static struct clock_event_device clockevent_epit; static struct clock_event_device clockevent_epit;
static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
static void __iomem *timer_base; static void __iomem *timer_base;
...@@ -106,8 +105,8 @@ static int epit_set_next_event(unsigned long evt, ...@@ -106,8 +105,8 @@ static int epit_set_next_event(unsigned long evt,
return 0; return 0;
} }
static void epit_set_mode(enum clock_event_mode mode, /* Left event sources disabled, no more interrupts appear */
struct clock_event_device *evt) static int epit_shutdown(struct clock_event_device *evt)
{ {
unsigned long flags; unsigned long flags;
...@@ -120,39 +119,41 @@ static void epit_set_mode(enum clock_event_mode mode, ...@@ -120,39 +119,41 @@ static void epit_set_mode(enum clock_event_mode mode,
/* Disable interrupt in GPT module */ /* Disable interrupt in GPT module */
epit_irq_disable(); epit_irq_disable();
if (mode != clockevent_mode) { /* Clear pending interrupt */
/* Set event time into far-far future */ epit_irq_acknowledge();
/* Clear pending interrupt */
epit_irq_acknowledge();
}
/* Remember timer mode */
clockevent_mode = mode;
local_irq_restore(flags); local_irq_restore(flags);
switch (mode) { return 0;
case CLOCK_EVT_MODE_PERIODIC: }
printk(KERN_ERR "epit_set_mode: Periodic mode is not "
"supported for i.MX EPIT\n"); static int epit_set_oneshot(struct clock_event_device *evt)
break; {
case CLOCK_EVT_MODE_ONESHOT: unsigned long flags;
/*
* The timer interrupt generation is disabled at least
* for enough time to call epit_set_next_event()
*/
local_irq_save(flags);
/* Disable interrupt in GPT module */
epit_irq_disable();
/* Clear pending interrupt, only while switching mode */
if (!clockevent_state_oneshot(evt))
epit_irq_acknowledge();
/* /*
* Do not put overhead of interrupt enable/disable into * Do not put overhead of interrupt enable/disable into
* epit_set_next_event(), the core has about 4 minutes * epit_set_next_event(), the core has about 4 minutes
* to call epit_set_next_event() or shutdown clock after * to call epit_set_next_event() or shutdown clock after
* mode switching * mode switching
*/ */
local_irq_save(flags); epit_irq_enable();
epit_irq_enable(); local_irq_restore(flags);
local_irq_restore(flags);
break; return 0;
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_RESUME:
/* Left event sources disabled, no more interrupts appear */
break;
}
} }
/* /*
...@@ -176,11 +177,13 @@ static struct irqaction epit_timer_irq = { ...@@ -176,11 +177,13 @@ static struct irqaction epit_timer_irq = {
}; };
static struct clock_event_device clockevent_epit = { static struct clock_event_device clockevent_epit = {
.name = "epit", .name = "epit",
.features = CLOCK_EVT_FEAT_ONESHOT, .features = CLOCK_EVT_FEAT_ONESHOT,
.set_mode = epit_set_mode, .set_state_shutdown = epit_shutdown,
.set_next_event = epit_set_next_event, .tick_resume = epit_shutdown,
.rating = 200, .set_state_oneshot = epit_set_oneshot,
.set_next_event = epit_set_next_event,
.rating = 200,
}; };
static int __init epit_clockevent_init(struct clk *timer_clk) static int __init epit_clockevent_init(struct clk *timer_clk)
......
...@@ -521,43 +521,55 @@ static int ixp4xx_set_next_event(unsigned long evt, ...@@ -521,43 +521,55 @@ static int ixp4xx_set_next_event(unsigned long evt,
return 0; return 0;
} }
static void ixp4xx_set_mode(enum clock_event_mode mode, static int ixp4xx_shutdown(struct clock_event_device *evt)
struct clock_event_device *evt)
{ {
unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK; unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK;
unsigned long osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK; unsigned long osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK;
switch (mode) { opts &= ~IXP4XX_OST_ENABLE;
case CLOCK_EVT_MODE_PERIODIC: *IXP4XX_OSRT1 = osrt | opts;
osrt = IXP4XX_LATCH & ~IXP4XX_OST_RELOAD_MASK; return 0;
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:
opts &= ~IXP4XX_OST_ENABLE;
break;
case CLOCK_EVT_MODE_RESUME:
opts |= IXP4XX_OST_ENABLE;
break;
case CLOCK_EVT_MODE_UNUSED:
default:
osrt = opts = 0;
break;
}
static int ixp4xx_set_oneshot(struct clock_event_device *evt)
{
unsigned long opts = IXP4XX_OST_ENABLE | IXP4XX_OST_ONE_SHOT;
unsigned long osrt = 0;
/* period set by 'set next_event' */
*IXP4XX_OSRT1 = osrt | opts; *IXP4XX_OSRT1 = osrt | opts;
return 0;
}
static int ixp4xx_set_periodic(struct clock_event_device *evt)
{
unsigned long opts = IXP4XX_OST_ENABLE;
unsigned long osrt = IXP4XX_LATCH & ~IXP4XX_OST_RELOAD_MASK;
*IXP4XX_OSRT1 = osrt | opts;
return 0;
}
static int ixp4xx_resume(struct clock_event_device *evt)
{
unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK;
unsigned long osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK;
opts |= IXP4XX_OST_ENABLE;
*IXP4XX_OSRT1 = osrt | opts;
return 0;
} }
static struct clock_event_device clockevent_ixp4xx = { static struct clock_event_device clockevent_ixp4xx = {
.name = "ixp4xx timer1", .name = "ixp4xx timer1",
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .features = CLOCK_EVT_FEAT_PERIODIC |
.rating = 200, CLOCK_EVT_FEAT_ONESHOT,
.set_mode = ixp4xx_set_mode, .rating = 200,
.set_next_event = ixp4xx_set_next_event, .set_state_shutdown = ixp4xx_shutdown,
.set_state_periodic = ixp4xx_set_periodic,
.set_state_oneshot = ixp4xx_set_oneshot,
.tick_resume = ixp4xx_resume,
.set_next_event = ixp4xx_set_next_event,
}; };
static void __init ixp4xx_clockevent_init(void) static void __init ixp4xx_clockevent_init(void)
......
...@@ -54,28 +54,25 @@ ...@@ -54,28 +54,25 @@
/* Timer0 Timeout Counter Register */ /* Timer0 Timeout Counter Register */
#define T0TC_WATCHDOG (0xff) /* Enable watchdog mode */ #define T0TC_WATCHDOG (0xff) /* Enable watchdog mode */
static void ks8695_set_mode(enum clock_event_mode mode, static int ks8695_set_periodic(struct clock_event_device *evt)
struct clock_event_device *evt)
{ {
u32 rate = DIV_ROUND_CLOSEST(KS8695_CLOCK_RATE, HZ);
u32 half = DIV_ROUND_CLOSEST(rate, 2);
u32 tmcon; u32 tmcon;
if (mode == CLOCK_EVT_FEAT_PERIODIC) { /* Disable timer 1 */
u32 rate = DIV_ROUND_CLOSEST(KS8695_CLOCK_RATE, HZ); tmcon = readl_relaxed(KS8695_TMR_VA + KS8695_TMCON);
u32 half = DIV_ROUND_CLOSEST(rate, 2); tmcon &= ~TMCON_T1EN;
writel_relaxed(tmcon, KS8695_TMR_VA + KS8695_TMCON);
/* Disable timer 1 */
tmcon = readl_relaxed(KS8695_TMR_VA + KS8695_TMCON);
tmcon &= ~TMCON_T1EN;
writel_relaxed(tmcon, KS8695_TMR_VA + KS8695_TMCON);
/* Both registers need to count down */ /* Both registers need to count down */
writel_relaxed(half, KS8695_TMR_VA + KS8695_T1TC); writel_relaxed(half, KS8695_TMR_VA + KS8695_T1TC);
writel_relaxed(half, KS8695_TMR_VA + KS8695_T1PD); writel_relaxed(half, KS8695_TMR_VA + KS8695_T1PD);
/* Re-enable timer1 */ /* Re-enable timer1 */
tmcon |= TMCON_T1EN; tmcon |= TMCON_T1EN;
writel_relaxed(tmcon, KS8695_TMR_VA + KS8695_TMCON); writel_relaxed(tmcon, KS8695_TMR_VA + KS8695_TMCON);
} return 0;
} }
static int ks8695_set_next_event(unsigned long cycles, static int ks8695_set_next_event(unsigned long cycles,
...@@ -102,11 +99,13 @@ static int ks8695_set_next_event(unsigned long cycles, ...@@ -102,11 +99,13 @@ static int ks8695_set_next_event(unsigned long cycles,
} }
static struct clock_event_device clockevent_ks8695 = { static struct clock_event_device clockevent_ks8695 = {
.name = "ks8695_t1tc", .name = "ks8695_t1tc",
.rating = 300, /* Reasonably fast and accurate clock event */ /* Reasonably fast and accurate clock event */
.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, .rating = 300,
.set_next_event = ks8695_set_next_event, .features = CLOCK_EVT_FEAT_ONESHOT |
.set_mode = ks8695_set_mode, CLOCK_EVT_FEAT_PERIODIC,
.set_next_event = ks8695_set_next_event,
.set_state_periodic = ks8695_set_periodic,
}; };
/* /*
......
...@@ -43,36 +43,24 @@ static int lpc32xx_clkevt_next_event(unsigned long delta, ...@@ -43,36 +43,24 @@ static int lpc32xx_clkevt_next_event(unsigned long delta,
return 0; return 0;
} }
static void lpc32xx_clkevt_mode(enum clock_event_mode mode, static int lpc32xx_shutdown(struct clock_event_device *evt)
struct clock_event_device *dev)
{ {
switch (mode) { /*
case CLOCK_EVT_MODE_PERIODIC: * Disable the timer. When using oneshot, we must also
WARN_ON(1); * disable the timer to wait for the first call to
break; * set_next_event().
*/
case CLOCK_EVT_MODE_ONESHOT: __raw_writel(0, LPC32XX_TIMER_TCR(LPC32XX_TIMER0_BASE));
case CLOCK_EVT_MODE_SHUTDOWN: return 0;
/*
* Disable the timer. When using oneshot, we must also
* disable the timer to wait for the first call to
* set_next_event().
*/
__raw_writel(0, LPC32XX_TIMER_TCR(LPC32XX_TIMER0_BASE));
break;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_RESUME:
break;
}
} }
static struct clock_event_device lpc32xx_clkevt = { static struct clock_event_device lpc32xx_clkevt = {
.name = "lpc32xx_clkevt", .name = "lpc32xx_clkevt",
.features = CLOCK_EVT_FEAT_ONESHOT, .features = CLOCK_EVT_FEAT_ONESHOT,
.rating = 300, .rating = 300,
.set_next_event = lpc32xx_clkevt_next_event, .set_next_event = lpc32xx_clkevt_next_event,
.set_mode = lpc32xx_clkevt_mode, .set_state_shutdown = lpc32xx_shutdown,
.set_state_oneshot = lpc32xx_shutdown,
}; };
static irqreturn_t lpc32xx_timer_interrupt(int irq, void *dev_id) static irqreturn_t lpc32xx_timer_interrupt(int irq, void *dev_id)
......
...@@ -124,32 +124,25 @@ static int timer_set_next_event(unsigned long delta, ...@@ -124,32 +124,25 @@ static int timer_set_next_event(unsigned long delta,
return 0; return 0;
} }
static void timer_set_mode(enum clock_event_mode mode, static int timer_set_shutdown(struct clock_event_device *evt)
struct clock_event_device *dev)
{ {
unsigned long flags; unsigned long flags;
local_irq_save(flags); local_irq_save(flags);
switch (mode) { /* disable the matching interrupt */
case CLOCK_EVT_MODE_ONESHOT: __raw_writel(0x00, mmp_timer_base + TMR_IER(0));
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
/* disable the matching interrupt */
__raw_writel(0x00, mmp_timer_base + TMR_IER(0));
break;
case CLOCK_EVT_MODE_RESUME:
case CLOCK_EVT_MODE_PERIODIC:
break;
}
local_irq_restore(flags); local_irq_restore(flags);
return 0;
} }
static struct clock_event_device ckevt = { static struct clock_event_device ckevt = {
.name = "clockevent", .name = "clockevent",
.features = CLOCK_EVT_FEAT_ONESHOT, .features = CLOCK_EVT_FEAT_ONESHOT,
.rating = 200, .rating = 200,
.set_next_event = timer_set_next_event, .set_next_event = timer_set_next_event,
.set_mode = timer_set_mode, .set_state_shutdown = timer_set_shutdown,
.set_state_oneshot = timer_set_shutdown,
}; };
static cycle_t clksrc_read(struct clocksource *cs) static cycle_t clksrc_read(struct clocksource *cs)
......
...@@ -34,40 +34,40 @@ ...@@ -34,40 +34,40 @@
#define TIMER_CLOCKEVENT 0 #define TIMER_CLOCKEVENT 0
#define TIMER_CLOCKSOURCE 1 #define TIMER_CLOCKSOURCE 1
static void netx_set_mode(enum clock_event_mode mode, static inline void timer_shutdown(struct clock_event_device *evt)
struct clock_event_device *clk)
{ {
u32 tmode;
/* disable timer */ /* disable timer */
writel(0, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT)); writel(0, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT));
}
static int netx_shutdown(struct clock_event_device *evt)
{
timer_shutdown(evt);
return 0;
}
static int netx_set_oneshot(struct clock_event_device *evt)
{
u32 tmode = NETX_GPIO_COUNTER_CTRL_IRQ_EN | NETX_GPIO_COUNTER_CTRL_RUN;
timer_shutdown(evt);
writel(0, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKEVENT));
writel(tmode, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT));
switch (mode) { return 0;
case CLOCK_EVT_MODE_PERIODIC: }
writel(NETX_LATCH, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKEVENT));
tmode = NETX_GPIO_COUNTER_CTRL_RST_EN |
NETX_GPIO_COUNTER_CTRL_IRQ_EN |
NETX_GPIO_COUNTER_CTRL_RUN;
break;
case CLOCK_EVT_MODE_ONESHOT:
writel(0, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKEVENT));
tmode = NETX_GPIO_COUNTER_CTRL_IRQ_EN |
NETX_GPIO_COUNTER_CTRL_RUN;
break;
default:
WARN(1, "%s: unhandled mode %d\n", __func__, mode);
/* fall through */
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_RESUME:
tmode = 0;
break;
}
static int netx_set_periodic(struct clock_event_device *evt)
{
u32 tmode = NETX_GPIO_COUNTER_CTRL_RST_EN |
NETX_GPIO_COUNTER_CTRL_IRQ_EN | NETX_GPIO_COUNTER_CTRL_RUN;
timer_shutdown(evt);
writel(NETX_LATCH, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKEVENT));
writel(tmode, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT)); writel(tmode, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT));
return 0;
} }
static int netx_set_next_event(unsigned long evt, static int netx_set_next_event(unsigned long evt,
...@@ -81,7 +81,10 @@ static struct clock_event_device netx_clockevent = { ...@@ -81,7 +81,10 @@ static struct clock_event_device netx_clockevent = {
.name = "netx-timer" __stringify(TIMER_CLOCKEVENT), .name = "netx-timer" __stringify(TIMER_CLOCKEVENT),
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
.set_next_event = netx_set_next_event, .set_next_event = netx_set_next_event,
.set_mode = netx_set_mode, .set_state_shutdown = netx_shutdown,
.set_state_periodic = netx_set_periodic,
.set_state_oneshot = netx_set_oneshot,
.tick_resume = netx_shutdown,
}; };
/* /*
......
...@@ -124,29 +124,26 @@ static int omap_mpu_set_next_event(unsigned long cycles, ...@@ -124,29 +124,26 @@ static int omap_mpu_set_next_event(unsigned long cycles,
return 0; return 0;
} }
static void omap_mpu_set_mode(enum clock_event_mode mode, static int omap_mpu_set_oneshot(struct clock_event_device *evt)
struct clock_event_device *evt)
{ {
switch (mode) { omap_mpu_timer_stop(0);
case CLOCK_EVT_MODE_PERIODIC: omap_mpu_remove_autoreset(0);
omap_mpu_set_autoreset(0); return 0;
break; }
case CLOCK_EVT_MODE_ONESHOT:
omap_mpu_timer_stop(0); static int omap_mpu_set_periodic(struct clock_event_device *evt)
omap_mpu_remove_autoreset(0); {
break; omap_mpu_set_autoreset(0);
case CLOCK_EVT_MODE_UNUSED: return 0;
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_RESUME:
break;
}
} }
static struct clock_event_device clockevent_mpu_timer1 = { static struct clock_event_device clockevent_mpu_timer1 = {
.name = "mpu_timer1", .name = "mpu_timer1",
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .features = CLOCK_EVT_FEAT_PERIODIC |
.set_next_event = omap_mpu_set_next_event, CLOCK_EVT_FEAT_ONESHOT,
.set_mode = omap_mpu_set_mode, .set_next_event = omap_mpu_set_next_event,
.set_state_periodic = omap_mpu_set_periodic,
.set_state_oneshot = omap_mpu_set_oneshot,
}; };
static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id) static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id)
......
...@@ -114,29 +114,28 @@ static int omap_32k_timer_set_next_event(unsigned long delta, ...@@ -114,29 +114,28 @@ static int omap_32k_timer_set_next_event(unsigned long delta,
return 0; return 0;
} }
static void omap_32k_timer_set_mode(enum clock_event_mode mode, static int omap_32k_timer_shutdown(struct clock_event_device *evt)
struct clock_event_device *evt)
{ {
omap_32k_timer_stop(); omap_32k_timer_stop();
return 0;
}
switch (mode) { static int omap_32k_timer_set_periodic(struct clock_event_device *evt)
case CLOCK_EVT_MODE_PERIODIC: {
omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD); omap_32k_timer_stop();
break; omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
case CLOCK_EVT_MODE_ONESHOT: return 0;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
break;
case CLOCK_EVT_MODE_RESUME:
break;
}
} }
static struct clock_event_device clockevent_32k_timer = { static struct clock_event_device clockevent_32k_timer = {
.name = "32k-timer", .name = "32k-timer",
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .features = CLOCK_EVT_FEAT_PERIODIC |
.set_next_event = omap_32k_timer_set_next_event, CLOCK_EVT_FEAT_ONESHOT,
.set_mode = omap_32k_timer_set_mode, .set_next_event = omap_32k_timer_set_next_event,
.set_state_shutdown = omap_32k_timer_shutdown,
.set_state_periodic = omap_32k_timer_set_periodic,
.set_state_oneshot = omap_32k_timer_shutdown,
.tick_resume = omap_32k_timer_shutdown,
}; };
static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id) static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id)
......
...@@ -102,38 +102,38 @@ static int omap2_gp_timer_set_next_event(unsigned long cycles, ...@@ -102,38 +102,38 @@ static int omap2_gp_timer_set_next_event(unsigned long cycles,
return 0; return 0;
} }
static void omap2_gp_timer_set_mode(enum clock_event_mode mode, static int omap2_gp_timer_shutdown(struct clock_event_device *evt)
struct clock_event_device *evt) {
__omap_dm_timer_stop(&clkev, OMAP_TIMER_POSTED, clkev.rate);
return 0;
}
static int omap2_gp_timer_set_periodic(struct clock_event_device *evt)
{ {
u32 period; u32 period;
__omap_dm_timer_stop(&clkev, OMAP_TIMER_POSTED, clkev.rate); __omap_dm_timer_stop(&clkev, OMAP_TIMER_POSTED, clkev.rate);
switch (mode) { period = clkev.rate / HZ;
case CLOCK_EVT_MODE_PERIODIC: period -= 1;
period = clkev.rate / HZ; /* Looks like we need to first set the load value separately */
period -= 1; __omap_dm_timer_write(&clkev, OMAP_TIMER_LOAD_REG, 0xffffffff - period,
/* Looks like we need to first set the load value separately */ OMAP_TIMER_POSTED);
__omap_dm_timer_write(&clkev, OMAP_TIMER_LOAD_REG, __omap_dm_timer_load_start(&clkev,
0xffffffff - period, OMAP_TIMER_POSTED); OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST,
__omap_dm_timer_load_start(&clkev, 0xffffffff - period, OMAP_TIMER_POSTED);
OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST, return 0;
0xffffffff - period, OMAP_TIMER_POSTED);
break;
case CLOCK_EVT_MODE_ONESHOT:
break;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_RESUME:
break;
}
} }
static struct clock_event_device clockevent_gpt = { static struct clock_event_device clockevent_gpt = {
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .features = CLOCK_EVT_FEAT_PERIODIC |
.rating = 300, CLOCK_EVT_FEAT_ONESHOT,
.set_next_event = omap2_gp_timer_set_next_event, .rating = 300,
.set_mode = omap2_gp_timer_set_mode, .set_next_event = omap2_gp_timer_set_next_event,
.set_state_shutdown = omap2_gp_timer_shutdown,
.set_state_periodic = omap2_gp_timer_set_periodic,
.set_state_oneshot = omap2_gp_timer_shutdown,
.tick_resume = omap2_gp_timer_shutdown,
}; };
static struct property device_disabled = { static struct property device_disabled = {
......
...@@ -66,8 +66,6 @@ ...@@ -66,8 +66,6 @@
static __iomem void *gpt_base; static __iomem void *gpt_base;
static struct clk *gpt_clk; static struct clk *gpt_clk;
static void clockevent_set_mode(enum clock_event_mode mode,
struct clock_event_device *clk_event_dev);
static int clockevent_next_event(unsigned long evt, static int clockevent_next_event(unsigned long evt,
struct clock_event_device *clk_event_dev); struct clock_event_device *clk_event_dev);
...@@ -95,54 +93,67 @@ static void __init spear_clocksource_init(void) ...@@ -95,54 +93,67 @@ static void __init spear_clocksource_init(void)
200, 16, clocksource_mmio_readw_up); 200, 16, clocksource_mmio_readw_up);
} }
static struct clock_event_device clkevt = { static inline void timer_shutdown(struct clock_event_device *evt)
.name = "tmr0", {
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, u16 val = readw(gpt_base + CR(CLKEVT));
.set_mode = clockevent_set_mode,
.set_next_event = clockevent_next_event, /* stop the timer */
.shift = 0, /* to be computed */ val &= ~CTRL_ENABLE;
}; writew(val, gpt_base + CR(CLKEVT));
}
static int spear_shutdown(struct clock_event_device *evt)
{
timer_shutdown(evt);
return 0;
}
static int spear_set_oneshot(struct clock_event_device *evt)
{
u16 val;
static void clockevent_set_mode(enum clock_event_mode mode, /* stop the timer */
struct clock_event_device *clk_event_dev) timer_shutdown(evt);
val = readw(gpt_base + CR(CLKEVT));
val |= CTRL_ONE_SHOT;
writew(val, gpt_base + CR(CLKEVT));
return 0;
}
static int spear_set_periodic(struct clock_event_device *evt)
{ {
u32 period; u32 period;
u16 val; u16 val;
/* stop the timer */ /* stop the timer */
timer_shutdown(evt);
period = clk_get_rate(gpt_clk) / HZ;
period >>= CTRL_PRESCALER16;
writew(period, gpt_base + LOAD(CLKEVT));
val = readw(gpt_base + CR(CLKEVT)); val = readw(gpt_base + CR(CLKEVT));
val &= ~CTRL_ENABLE; val &= ~CTRL_ONE_SHOT;
val |= CTRL_ENABLE | CTRL_INT_ENABLE;
writew(val, gpt_base + CR(CLKEVT)); writew(val, gpt_base + CR(CLKEVT));
switch (mode) { return 0;
case CLOCK_EVT_MODE_PERIODIC:
period = clk_get_rate(gpt_clk) / HZ;
period >>= CTRL_PRESCALER16;
writew(period, gpt_base + LOAD(CLKEVT));
val = readw(gpt_base + CR(CLKEVT));
val &= ~CTRL_ONE_SHOT;
val |= CTRL_ENABLE | CTRL_INT_ENABLE;
writew(val, gpt_base + CR(CLKEVT));
break;
case CLOCK_EVT_MODE_ONESHOT:
val = readw(gpt_base + CR(CLKEVT));
val |= CTRL_ONE_SHOT;
writew(val, gpt_base + CR(CLKEVT));
break;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_RESUME:
break;
default:
pr_err("Invalid mode requested\n");
break;
}
} }
static struct clock_event_device clkevt = {
.name = "tmr0",
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
.set_state_shutdown = spear_shutdown,
.set_state_periodic = spear_set_periodic,
.set_state_oneshot = spear_set_oneshot,
.tick_resume = spear_shutdown,
.set_next_event = clockevent_next_event,
.shift = 0, /* to be computed */
};
static int clockevent_next_event(unsigned long cycles, static int clockevent_next_event(unsigned long cycles,
struct clock_event_device *clk_event_dev) struct clock_event_device *clk_event_dev)
{ {
......
...@@ -48,31 +48,32 @@ ...@@ -48,31 +48,32 @@
static unsigned int timer0_load; static unsigned int timer0_load;
static void nuc900_clockevent_setmode(enum clock_event_mode mode, static int nuc900_clockevent_shutdown(struct clock_event_device *evt)
struct clock_event_device *clk)
{ {
unsigned int val; unsigned int val = __raw_readl(REG_TCSR0) & ~(0x03 << 27);
val = __raw_readl(REG_TCSR0); __raw_writel(val, REG_TCSR0);
val &= ~(0x03 << 27); return 0;
}
static int nuc900_clockevent_set_oneshot(struct clock_event_device *evt)
{
unsigned int val = __raw_readl(REG_TCSR0) & ~(0x03 << 27);
switch (mode) { val |= (ONESHOT | COUNTEN | INTEN | PRESCALE);
case CLOCK_EVT_MODE_PERIODIC:
__raw_writel(timer0_load, REG_TICR0);
val |= (PERIOD | COUNTEN | INTEN | PRESCALE);
break;
case CLOCK_EVT_MODE_ONESHOT: __raw_writel(val, REG_TCSR0);
val |= (ONESHOT | COUNTEN | INTEN | PRESCALE); return 0;
break; }
case CLOCK_EVT_MODE_UNUSED: static int nuc900_clockevent_set_periodic(struct clock_event_device *evt)
case CLOCK_EVT_MODE_SHUTDOWN: {
case CLOCK_EVT_MODE_RESUME: unsigned int val = __raw_readl(REG_TCSR0) & ~(0x03 << 27);
break;
}
__raw_writel(timer0_load, REG_TICR0);
val |= (PERIOD | COUNTEN | INTEN | PRESCALE);
__raw_writel(val, REG_TCSR0); __raw_writel(val, REG_TCSR0);
return 0;
} }
static int nuc900_clockevent_setnextevent(unsigned long evt, static int nuc900_clockevent_setnextevent(unsigned long evt,
...@@ -90,11 +91,15 @@ static int nuc900_clockevent_setnextevent(unsigned long evt, ...@@ -90,11 +91,15 @@ static int nuc900_clockevent_setnextevent(unsigned long evt,
} }
static struct clock_event_device nuc900_clockevent_device = { static struct clock_event_device nuc900_clockevent_device = {
.name = "nuc900-timer0", .name = "nuc900-timer0",
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .features = CLOCK_EVT_FEAT_PERIODIC |
.set_mode = nuc900_clockevent_setmode, CLOCK_EVT_FEAT_ONESHOT,
.set_next_event = nuc900_clockevent_setnextevent, .set_state_shutdown = nuc900_clockevent_shutdown,
.rating = 300, .set_state_periodic = nuc900_clockevent_set_periodic,
.set_state_oneshot = nuc900_clockevent_set_oneshot,
.tick_resume = nuc900_clockevent_shutdown,
.set_next_event = nuc900_clockevent_setnextevent,
.rating = 300,
}; };
/*IRQ handler for the timer*/ /*IRQ handler for the timer*/
......
...@@ -77,41 +77,57 @@ static int iop_set_next_event(unsigned long delta, ...@@ -77,41 +77,57 @@ static int iop_set_next_event(unsigned long delta,
static unsigned long ticks_per_jiffy; static unsigned long ticks_per_jiffy;
static void iop_set_mode(enum clock_event_mode mode, static int iop_set_periodic(struct clock_event_device *evt)
struct clock_event_device *unused)
{ {
u32 tmr = read_tmr0(); u32 tmr = read_tmr0();
switch (mode) { write_tmr0(tmr & ~IOP_TMR_EN);
case CLOCK_EVT_MODE_PERIODIC: write_tcr0(ticks_per_jiffy - 1);
write_tmr0(tmr & ~IOP_TMR_EN); write_trr0(ticks_per_jiffy - 1);
write_tcr0(ticks_per_jiffy - 1); tmr |= (IOP_TMR_RELOAD | IOP_TMR_EN);
write_trr0(ticks_per_jiffy - 1);
tmr |= (IOP_TMR_RELOAD | IOP_TMR_EN);
break;
case CLOCK_EVT_MODE_ONESHOT:
/* ->set_next_event sets period and enables timer */
tmr &= ~(IOP_TMR_RELOAD | IOP_TMR_EN);
break;
case CLOCK_EVT_MODE_RESUME:
tmr |= IOP_TMR_EN;
break;
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_UNUSED:
default:
tmr &= ~IOP_TMR_EN;
break;
}
write_tmr0(tmr); write_tmr0(tmr);
return 0;
}
static int iop_set_oneshot(struct clock_event_device *evt)
{
u32 tmr = read_tmr0();
/* ->set_next_event sets period and enables timer */
tmr &= ~(IOP_TMR_RELOAD | IOP_TMR_EN);
write_tmr0(tmr);
return 0;
}
static int iop_shutdown(struct clock_event_device *evt)
{
u32 tmr = read_tmr0();
tmr &= ~IOP_TMR_EN;
write_tmr0(tmr);
return 0;
}
static int iop_resume(struct clock_event_device *evt)
{
u32 tmr = read_tmr0();
tmr |= IOP_TMR_EN;
write_tmr0(tmr);
return 0;
} }
static struct clock_event_device iop_clockevent = { static struct clock_event_device iop_clockevent = {
.name = "iop_timer0", .name = "iop_timer0",
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .features = CLOCK_EVT_FEAT_PERIODIC |
.rating = 300, CLOCK_EVT_FEAT_ONESHOT,
.set_next_event = iop_set_next_event, .rating = 300,
.set_mode = iop_set_mode, .set_next_event = iop_set_next_event,
.set_state_shutdown = iop_shutdown,
.set_state_periodic = iop_set_periodic,
.tick_resume = iop_resume,
.set_state_oneshot = iop_set_oneshot,
}; };
static irqreturn_t static irqreturn_t
......
...@@ -106,60 +106,63 @@ orion_clkevt_next_event(unsigned long delta, struct clock_event_device *dev) ...@@ -106,60 +106,63 @@ orion_clkevt_next_event(unsigned long delta, struct clock_event_device *dev)
return 0; return 0;
} }
static void static int orion_clkevt_shutdown(struct clock_event_device *evt)
orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
{ {
unsigned long flags; unsigned long flags;
u32 u; u32 u;
local_irq_save(flags); local_irq_save(flags);
if (mode == CLOCK_EVT_MODE_PERIODIC) {
/* /* Disable timer */
* Setup timer to fire at 1/HZ intervals. u = readl(timer_base + TIMER_CTRL_OFF);
*/ writel(u & ~TIMER1_EN, timer_base + TIMER_CTRL_OFF);
writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD_OFF);
writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL_OFF); /* Disable timer interrupt */
u = readl(bridge_base + BRIDGE_MASK_OFF);
/* writel(u & ~BRIDGE_INT_TIMER1, bridge_base + BRIDGE_MASK_OFF);
* Enable timer interrupt.
*/ /* ACK pending timer interrupt */
u = readl(bridge_base + BRIDGE_MASK_OFF); writel(bridge_timer1_clr_mask, bridge_base + BRIDGE_CAUSE_OFF);
writel(u | BRIDGE_INT_TIMER1, bridge_base + BRIDGE_MASK_OFF);
local_irq_restore(flags);
/*
* Enable timer. return 0;
*/ }
u = readl(timer_base + TIMER_CTRL_OFF);
writel(u | TIMER1_EN | TIMER1_RELOAD_EN, static int orion_clkevt_set_periodic(struct clock_event_device *evt)
timer_base + TIMER_CTRL_OFF); {
} else { unsigned long flags;
/* u32 u;
* Disable timer.
*/ local_irq_save(flags);
u = readl(timer_base + TIMER_CTRL_OFF);
writel(u & ~TIMER1_EN, timer_base + TIMER_CTRL_OFF); /* Setup timer to fire at 1/HZ intervals */
writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD_OFF);
/* writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL_OFF);
* Disable timer interrupt.
*/ /* Enable timer interrupt */
u = readl(bridge_base + BRIDGE_MASK_OFF); u = readl(bridge_base + BRIDGE_MASK_OFF);
writel(u & ~BRIDGE_INT_TIMER1, bridge_base + BRIDGE_MASK_OFF); writel(u | BRIDGE_INT_TIMER1, bridge_base + BRIDGE_MASK_OFF);
/* /* Enable timer */
* ACK pending timer interrupt. u = readl(timer_base + TIMER_CTRL_OFF);
*/ writel(u | TIMER1_EN | TIMER1_RELOAD_EN, timer_base + TIMER_CTRL_OFF);
writel(bridge_timer1_clr_mask, bridge_base + BRIDGE_CAUSE_OFF);
}
local_irq_restore(flags); local_irq_restore(flags);
return 0;
} }
static struct clock_event_device orion_clkevt = { static struct clock_event_device orion_clkevt = {
.name = "orion_tick", .name = "orion_tick",
.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, .features = CLOCK_EVT_FEAT_ONESHOT |
.rating = 300, CLOCK_EVT_FEAT_PERIODIC,
.set_next_event = orion_clkevt_next_event, .rating = 300,
.set_mode = orion_clkevt_mode, .set_next_event = orion_clkevt_next_event,
.set_state_shutdown = orion_clkevt_shutdown,
.set_state_periodic = orion_clkevt_set_periodic,
.set_state_oneshot = orion_clkevt_shutdown,
.tick_resume = orion_clkevt_shutdown,
}; };
static irqreturn_t orion_timer_interrupt(int irq, void *dev_id) static irqreturn_t orion_timer_interrupt(int irq, void *dev_id)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment