Commit cf4541c1 authored by Viresh Kumar's avatar Viresh Kumar Committed by Daniel Lezcano

clockevents/drivers/tcb_clksrc: Migrate to new 'set-state' interface

Migrate tcb_clksrc driver to the new 'set-state' interface provided by
clockevents core, the earlier 'set-mode' interface is marked obsolete
now.

This also enables us to implement callbacks for new states of clockevent
devices, for example: ONESHOT_STOPPED.

Cc: Nicolas Ferre <nicolas.ferre@atmel.com>
Signed-off-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: default avatarDaniel Lezcano <daniel.lezcano@linaro.org>
parent f0753793
...@@ -91,55 +91,62 @@ static struct tc_clkevt_device *to_tc_clkevt(struct clock_event_device *clkevt) ...@@ -91,55 +91,62 @@ static struct tc_clkevt_device *to_tc_clkevt(struct clock_event_device *clkevt)
*/ */
static u32 timer_clock; static u32 timer_clock;
static void tc_mode(enum clock_event_mode m, struct clock_event_device *d) static int tc_shutdown(struct clock_event_device *d)
{ {
struct tc_clkevt_device *tcd = to_tc_clkevt(d); struct tc_clkevt_device *tcd = to_tc_clkevt(d);
void __iomem *regs = tcd->regs; void __iomem *regs = tcd->regs;
if (tcd->clkevt.mode == CLOCK_EVT_MODE_PERIODIC
|| tcd->clkevt.mode == CLOCK_EVT_MODE_ONESHOT) {
__raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR)); __raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR));
__raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR)); __raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR));
clk_disable(tcd->clk); clk_disable(tcd->clk);
}
switch (m) { return 0;
}
static int tc_set_oneshot(struct clock_event_device *d)
{
struct tc_clkevt_device *tcd = to_tc_clkevt(d);
void __iomem *regs = tcd->regs;
if (clockevent_state_oneshot(d) || clockevent_state_periodic(d))
tc_shutdown(d);
clk_enable(tcd->clk);
/* slow clock, count up to RC, then irq and stop */
__raw_writel(timer_clock | ATMEL_TC_CPCSTOP | ATMEL_TC_WAVE |
ATMEL_TC_WAVESEL_UP_AUTO, regs + ATMEL_TC_REG(2, CMR));
__raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
/* set_next_event() configures and starts the timer */
return 0;
}
static int tc_set_periodic(struct clock_event_device *d)
{
struct tc_clkevt_device *tcd = to_tc_clkevt(d);
void __iomem *regs = tcd->regs;
if (clockevent_state_oneshot(d) || clockevent_state_periodic(d))
tc_shutdown(d);
/* By not making the gentime core emulate periodic mode on top /* By not making the gentime core emulate periodic mode on top
* of oneshot, we get lower overhead and improved accuracy. * of oneshot, we get lower overhead and improved accuracy.
*/ */
case CLOCK_EVT_MODE_PERIODIC:
clk_enable(tcd->clk); clk_enable(tcd->clk);
/* slow clock, count up to RC, then irq and restart */ /* slow clock, count up to RC, then irq and restart */
__raw_writel(timer_clock __raw_writel(timer_clock | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO,
| ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO,
regs + ATMEL_TC_REG(2, CMR)); regs + ATMEL_TC_REG(2, CMR));
__raw_writel((32768 + HZ/2) / HZ, tcaddr + ATMEL_TC_REG(2, RC)); __raw_writel((32768 + HZ / 2) / HZ, tcaddr + ATMEL_TC_REG(2, RC));
/* Enable clock and interrupts on RC compare */ /* Enable clock and interrupts on RC compare */
__raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER)); __raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
/* go go gadget! */ /* go go gadget! */
__raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG, __raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG, regs +
regs + ATMEL_TC_REG(2, CCR)); ATMEL_TC_REG(2, CCR));
break; return 0;
case CLOCK_EVT_MODE_ONESHOT:
clk_enable(tcd->clk);
/* slow clock, count up to RC, then irq and stop */
__raw_writel(timer_clock | ATMEL_TC_CPCSTOP
| ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO,
regs + ATMEL_TC_REG(2, CMR));
__raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
/* set_next_event() configures and starts the timer */
break;
default:
break;
}
} }
static int tc_next_event(unsigned long delta, struct clock_event_device *d) static int tc_next_event(unsigned long delta, struct clock_event_device *d)
...@@ -155,12 +162,14 @@ static int tc_next_event(unsigned long delta, struct clock_event_device *d) ...@@ -155,12 +162,14 @@ static int tc_next_event(unsigned long delta, struct clock_event_device *d)
static struct tc_clkevt_device clkevt = { static struct tc_clkevt_device clkevt = {
.clkevt = { .clkevt = {
.name = "tc_clkevt", .name = "tc_clkevt",
.features = CLOCK_EVT_FEAT_PERIODIC .features = CLOCK_EVT_FEAT_PERIODIC |
| CLOCK_EVT_FEAT_ONESHOT, CLOCK_EVT_FEAT_ONESHOT,
/* Should be lower than at91rm9200's system timer */ /* Should be lower than at91rm9200's system timer */
.rating = 125, .rating = 125,
.set_next_event = tc_next_event, .set_next_event = tc_next_event,
.set_mode = tc_mode, .set_state_shutdown = tc_shutdown,
.set_state_periodic = tc_set_periodic,
.set_state_oneshot = tc_set_oneshot,
}, },
}; };
......
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