Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull timer updates from Thomas Gleixner: "Rather large, but nothing exiting: - new range check for settimeofday() to prevent that boot time becomes negative. - fix for file time rounding - a few simplifications of the hrtimer code - fix for the proc/timerlist code so the output of clock realtime timers is accurate - more y2038 work - tree wide conversion of clockevent drivers to the new callbacks" * 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (88 commits) hrtimer: Handle failure of tick_init_highres() gracefully hrtimer: Unconfuse switch_hrtimer_base() a bit hrtimer: Simplify get_target_base() by returning current base hrtimer: Drop return code of hrtimer_switch_to_hres() time: Introduce timespec64_to_jiffies()/jiffies_to_timespec64() time: Introduce current_kernel_time64() time: Introduce struct itimerspec64 time: Add the common weak version of update_persistent_clock() time: Always make sure wall_to_monotonic isn't positive time: Fix nanosecond file time rounding in timespec_trunc() timer_list: Add the base offset so remaining nsecs are accurate for non monotonic timers cris/time: Migrate to new 'set-state' interface kernel: broadcast-hrtimer: Migrate to new 'set-state' interface xtensa/time: Migrate to new 'set-state' interface unicore/time: Migrate to new 'set-state' interface um/time: Migrate to new 'set-state' interface sparc/time: Migrate to new 'set-state' interface sh/localtimer: Migrate to new 'set-state' interface score/time: Migrate to new 'set-state' interface s390/time: Migrate to new 'set-state' interface ...
This commit is contained in:
commit
5e359bf221
|
@ -93,7 +93,7 @@ rtc_timer_interrupt(int irq, void *dev)
|
|||
struct clock_event_device *ce = &per_cpu(cpu_ce, cpu);
|
||||
|
||||
/* Don't run the hook for UNUSED or SHUTDOWN. */
|
||||
if (likely(ce->mode == CLOCK_EVT_MODE_PERIODIC))
|
||||
if (likely(clockevent_state_periodic(ce)))
|
||||
ce->event_handler(ce);
|
||||
|
||||
if (test_irq_work_pending()) {
|
||||
|
@ -104,13 +104,6 @@ rtc_timer_interrupt(int irq, void *dev)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void
|
||||
rtc_ce_set_mode(enum clock_event_mode mode, struct clock_event_device *ce)
|
||||
{
|
||||
/* The mode member of CE is updated in generic code.
|
||||
Since we only support periodic events, nothing to do. */
|
||||
}
|
||||
|
||||
static int
|
||||
rtc_ce_set_next_event(unsigned long evt, struct clock_event_device *ce)
|
||||
{
|
||||
|
@ -129,7 +122,6 @@ init_rtc_clockevent(void)
|
|||
.features = CLOCK_EVT_FEAT_PERIODIC,
|
||||
.rating = 100,
|
||||
.cpumask = cpumask_of(cpu),
|
||||
.set_mode = rtc_ce_set_mode,
|
||||
.set_next_event = rtc_ce_set_next_event,
|
||||
};
|
||||
|
||||
|
@ -161,12 +153,12 @@ static struct clocksource qemu_cs = {
|
|||
* The QEMU alarm as a clock_event_device primitive.
|
||||
*/
|
||||
|
||||
static void
|
||||
qemu_ce_set_mode(enum clock_event_mode mode, struct clock_event_device *ce)
|
||||
static int qemu_ce_shutdown(struct clock_event_device *ce)
|
||||
{
|
||||
/* The mode member of CE is updated for us in generic code.
|
||||
Just make sure that the event is disabled. */
|
||||
qemu_set_alarm_abs(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -197,7 +189,9 @@ init_qemu_clockevent(void)
|
|||
.features = CLOCK_EVT_FEAT_ONESHOT,
|
||||
.rating = 400,
|
||||
.cpumask = cpumask_of(cpu),
|
||||
.set_mode = qemu_ce_set_mode,
|
||||
.set_state_shutdown = qemu_ce_shutdown,
|
||||
.set_state_oneshot = qemu_ce_shutdown,
|
||||
.tick_resume = qemu_ce_shutdown,
|
||||
.set_next_event = qemu_ce_set_next_event,
|
||||
};
|
||||
|
||||
|
|
|
@ -136,44 +136,44 @@ static int bfin_gptmr0_set_next_event(unsigned long cycles,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void bfin_gptmr0_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static int bfin_gptmr0_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC: {
|
||||
#ifndef CONFIG_BF60x
|
||||
set_gptimer_config(TIMER0_id, \
|
||||
TIMER_OUT_DIS | TIMER_IRQ_ENA | \
|
||||
TIMER_PERIOD_CNT | TIMER_MODE_PWM);
|
||||
set_gptimer_config(TIMER0_id,
|
||||
TIMER_OUT_DIS | TIMER_IRQ_ENA |
|
||||
TIMER_PERIOD_CNT | TIMER_MODE_PWM);
|
||||
#else
|
||||
set_gptimer_config(TIMER0_id, TIMER_OUT_DIS
|
||||
| TIMER_MODE_PWM_CONT | TIMER_PULSE_HI | TIMER_IRQ_PER);
|
||||
set_gptimer_config(TIMER0_id,
|
||||
TIMER_OUT_DIS | TIMER_MODE_PWM_CONT |
|
||||
TIMER_PULSE_HI | TIMER_IRQ_PER);
|
||||
#endif
|
||||
|
||||
set_gptimer_period(TIMER0_id, get_sclk() / HZ);
|
||||
set_gptimer_pwidth(TIMER0_id, get_sclk() / HZ - 1);
|
||||
enable_gptimers(TIMER0bit);
|
||||
break;
|
||||
}
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
disable_gptimers(TIMER0bit);
|
||||
set_gptimer_period(TIMER0_id, get_sclk() / HZ);
|
||||
set_gptimer_pwidth(TIMER0_id, get_sclk() / HZ - 1);
|
||||
enable_gptimers(TIMER0bit);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bfin_gptmr0_set_oneshot(struct clock_event_device *evt)
|
||||
{
|
||||
disable_gptimers(TIMER0bit);
|
||||
#ifndef CONFIG_BF60x
|
||||
set_gptimer_config(TIMER0_id, \
|
||||
TIMER_OUT_DIS | TIMER_IRQ_ENA | TIMER_MODE_PWM);
|
||||
set_gptimer_config(TIMER0_id,
|
||||
TIMER_OUT_DIS | TIMER_IRQ_ENA | TIMER_MODE_PWM);
|
||||
#else
|
||||
set_gptimer_config(TIMER0_id, TIMER_OUT_DIS | TIMER_MODE_PWM
|
||||
| TIMER_PULSE_HI | TIMER_IRQ_WID_DLY);
|
||||
set_gptimer_config(TIMER0_id,
|
||||
TIMER_OUT_DIS | TIMER_MODE_PWM | TIMER_PULSE_HI |
|
||||
TIMER_IRQ_WID_DLY);
|
||||
#endif
|
||||
|
||||
set_gptimer_period(TIMER0_id, 0);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
disable_gptimers(TIMER0bit);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
break;
|
||||
}
|
||||
set_gptimer_period(TIMER0_id, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bfin_gptmr0_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
disable_gptimers(TIMER0bit);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bfin_gptmr0_ack(void)
|
||||
|
@ -211,13 +211,16 @@ static struct irqaction gptmr0_irq = {
|
|||
};
|
||||
|
||||
static struct clock_event_device clockevent_gptmr0 = {
|
||||
.name = "bfin_gptimer0",
|
||||
.rating = 300,
|
||||
.irq = IRQ_TIMER0,
|
||||
.shift = 32,
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_next_event = bfin_gptmr0_set_next_event,
|
||||
.set_mode = bfin_gptmr0_set_mode,
|
||||
.name = "bfin_gptimer0",
|
||||
.rating = 300,
|
||||
.irq = IRQ_TIMER0,
|
||||
.shift = 32,
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC |
|
||||
CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_next_event = bfin_gptmr0_set_next_event,
|
||||
.set_state_shutdown = bfin_gptmr0_shutdown,
|
||||
.set_state_periodic = bfin_gptmr0_set_periodic,
|
||||
.set_state_oneshot = bfin_gptmr0_set_oneshot,
|
||||
};
|
||||
|
||||
static void __init bfin_gptmr0_clockevent_init(struct clock_event_device *evt)
|
||||
|
@ -250,36 +253,35 @@ static int bfin_coretmr_set_next_event(unsigned long cycles,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void bfin_coretmr_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static int bfin_coretmr_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC: {
|
||||
unsigned long tcount = ((get_cclk() / (HZ * TIME_SCALE)) - 1);
|
||||
bfin_write_TCNTL(TMPWR);
|
||||
CSYNC();
|
||||
bfin_write_TSCALE(TIME_SCALE - 1);
|
||||
bfin_write_TPERIOD(tcount);
|
||||
bfin_write_TCOUNT(tcount);
|
||||
CSYNC();
|
||||
bfin_write_TCNTL(TMPWR | TMREN | TAUTORLD);
|
||||
break;
|
||||
}
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
bfin_write_TCNTL(TMPWR);
|
||||
CSYNC();
|
||||
bfin_write_TSCALE(TIME_SCALE - 1);
|
||||
bfin_write_TPERIOD(0);
|
||||
bfin_write_TCOUNT(0);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
bfin_write_TCNTL(0);
|
||||
CSYNC();
|
||||
break;
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
break;
|
||||
}
|
||||
unsigned long tcount = ((get_cclk() / (HZ * TIME_SCALE)) - 1);
|
||||
|
||||
bfin_write_TCNTL(TMPWR);
|
||||
CSYNC();
|
||||
bfin_write_TSCALE(TIME_SCALE - 1);
|
||||
bfin_write_TPERIOD(tcount);
|
||||
bfin_write_TCOUNT(tcount);
|
||||
CSYNC();
|
||||
bfin_write_TCNTL(TMPWR | TMREN | TAUTORLD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bfin_coretmr_set_oneshot(struct clock_event_device *evt)
|
||||
{
|
||||
bfin_write_TCNTL(TMPWR);
|
||||
CSYNC();
|
||||
bfin_write_TSCALE(TIME_SCALE - 1);
|
||||
bfin_write_TPERIOD(0);
|
||||
bfin_write_TCOUNT(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bfin_coretmr_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
bfin_write_TCNTL(0);
|
||||
CSYNC();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bfin_coretmr_init(void)
|
||||
|
@ -335,7 +337,9 @@ void bfin_coretmr_clockevent_init(void)
|
|||
evt->shift = 32;
|
||||
evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
|
||||
evt->set_next_event = bfin_coretmr_set_next_event;
|
||||
evt->set_mode = bfin_coretmr_set_mode;
|
||||
evt->set_state_shutdown = bfin_coretmr_shutdown;
|
||||
evt->set_state_periodic = bfin_coretmr_set_periodic;
|
||||
evt->set_state_oneshot = bfin_coretmr_set_oneshot;
|
||||
|
||||
clock_tick = get_cclk() / TIME_SCALE;
|
||||
evt->mult = div_sc(clock_tick, NSEC_PER_SEC, evt->shift);
|
||||
|
|
|
@ -126,35 +126,37 @@ static int next_event(unsigned long delta,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void set_clock_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static int set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
timer64_enable();
|
||||
timer64_mode = TIMER64_MODE_PERIODIC;
|
||||
timer64_config(TIMER64_RATE / HZ);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
timer64_enable();
|
||||
timer64_mode = TIMER64_MODE_ONE_SHOT;
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
timer64_mode = TIMER64_MODE_DISABLED;
|
||||
timer64_disable();
|
||||
break;
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
break;
|
||||
}
|
||||
timer64_enable();
|
||||
timer64_mode = TIMER64_MODE_PERIODIC;
|
||||
timer64_config(TIMER64_RATE / HZ);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_oneshot(struct clock_event_device *evt)
|
||||
{
|
||||
timer64_enable();
|
||||
timer64_mode = TIMER64_MODE_ONE_SHOT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
timer64_mode = TIMER64_MODE_DISABLED;
|
||||
timer64_disable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clock_event_device t64_clockevent_device = {
|
||||
.name = "TIMER64_EVT32_TIMER",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
|
||||
.rating = 200,
|
||||
.set_mode = set_clock_mode,
|
||||
.set_next_event = next_event,
|
||||
.name = "TIMER64_EVT32_TIMER",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT |
|
||||
CLOCK_EVT_FEAT_PERIODIC,
|
||||
.rating = 200,
|
||||
.set_state_shutdown = shutdown,
|
||||
.set_state_periodic = set_periodic,
|
||||
.set_state_oneshot = set_oneshot,
|
||||
.set_next_event = next_event,
|
||||
};
|
||||
|
||||
static irqreturn_t timer_interrupt(int irq, void *dev_id)
|
||||
|
|
|
@ -172,8 +172,7 @@ void handle_watchdog_bite(struct pt_regs *regs)
|
|||
extern void cris_profile_sample(struct pt_regs *regs);
|
||||
static void __iomem *timer_base;
|
||||
|
||||
static void crisv32_clkevt_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *dev)
|
||||
static int crisv32_clkevt_switch_state(struct clock_event_device *dev)
|
||||
{
|
||||
reg_timer_rw_tmr0_ctrl ctrl = {
|
||||
.op = regk_timer_hold,
|
||||
|
@ -181,6 +180,7 @@ static void crisv32_clkevt_mode(enum clock_event_mode mode,
|
|||
};
|
||||
|
||||
REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crisv32_clkevt_next_event(unsigned long evt,
|
||||
|
@ -231,7 +231,9 @@ static struct clock_event_device crisv32_clockevent = {
|
|||
.name = "crisv32-timer",
|
||||
.rating = 300,
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_mode = crisv32_clkevt_mode,
|
||||
.set_state_oneshot = crisv32_clkevt_switch_state,
|
||||
.set_state_shutdown = crisv32_clkevt_switch_state,
|
||||
.tick_resume = crisv32_clkevt_switch_state,
|
||||
.set_next_event = crisv32_clkevt_next_event,
|
||||
};
|
||||
|
||||
|
|
|
@ -122,37 +122,29 @@ static int xilinx_timer_set_next_event(unsigned long delta,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void xilinx_timer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static int xilinx_timer_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
pr_info("%s: periodic\n", __func__);
|
||||
xilinx_timer0_start_periodic(freq_div_hz);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
pr_info("%s: oneshot\n", __func__);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
pr_info("%s: unused\n", __func__);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
pr_info("%s: shutdown\n", __func__);
|
||||
xilinx_timer0_stop();
|
||||
break;
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
pr_info("%s: resume\n", __func__);
|
||||
break;
|
||||
}
|
||||
pr_info("%s\n", __func__);
|
||||
xilinx_timer0_stop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xilinx_timer_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
pr_info("%s\n", __func__);
|
||||
xilinx_timer0_start_periodic(freq_div_hz);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clock_event_device clockevent_xilinx_timer = {
|
||||
.name = "xilinx_clockevent",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
|
||||
.shift = 8,
|
||||
.rating = 300,
|
||||
.set_next_event = xilinx_timer_set_next_event,
|
||||
.set_mode = xilinx_timer_set_mode,
|
||||
.name = "xilinx_clockevent",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT |
|
||||
CLOCK_EVT_FEAT_PERIODIC,
|
||||
.shift = 8,
|
||||
.rating = 300,
|
||||
.set_next_event = xilinx_timer_set_next_event,
|
||||
.set_state_shutdown = xilinx_timer_shutdown,
|
||||
.set_state_periodic = xilinx_timer_set_periodic,
|
||||
};
|
||||
|
||||
static inline void timer_ack(void)
|
||||
|
|
|
@ -41,12 +41,6 @@ static int next_event(unsigned long delta,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void set_clock_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
/* Nothing to do ... */
|
||||
}
|
||||
|
||||
static DEFINE_PER_CPU(struct clock_event_device, mn10300_clockevent_device);
|
||||
static DEFINE_PER_CPU(struct irqaction, timer_irq);
|
||||
|
||||
|
@ -108,7 +102,6 @@ int __init init_clockevents(void)
|
|||
|
||||
cd->rating = 200;
|
||||
cd->cpumask = cpumask_of(smp_processor_id());
|
||||
cd->set_mode = set_clock_mode;
|
||||
cd->event_handler = event_handler;
|
||||
cd->set_next_event = next_event;
|
||||
|
||||
|
|
|
@ -48,29 +48,6 @@ static int openrisc_timer_set_next_event(unsigned long delta,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void openrisc_timer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
pr_debug(KERN_INFO "%s: periodic\n", __func__);
|
||||
BUG();
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
pr_debug(KERN_INFO "%s: oneshot\n", __func__);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
pr_debug(KERN_INFO "%s: unused\n", __func__);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
pr_debug(KERN_INFO "%s: shutdown\n", __func__);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
pr_debug(KERN_INFO "%s: resume\n", __func__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* This is the clock event device based on the OR1K tick timer.
|
||||
* As the timer is being used as a continuous clock-source (required for HR
|
||||
* timers) we cannot enable the PERIODIC feature. The tick timer can run using
|
||||
|
@ -82,7 +59,6 @@ static struct clock_event_device clockevent_openrisc_timer = {
|
|||
.features = CLOCK_EVT_FEAT_ONESHOT,
|
||||
.rating = 300,
|
||||
.set_next_event = openrisc_timer_set_next_event,
|
||||
.set_mode = openrisc_timer_set_mode,
|
||||
};
|
||||
|
||||
static inline void timer_ack(void)
|
||||
|
|
|
@ -99,16 +99,17 @@ static struct clocksource clocksource_timebase = {
|
|||
|
||||
static int decrementer_set_next_event(unsigned long evt,
|
||||
struct clock_event_device *dev);
|
||||
static void decrementer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *dev);
|
||||
static int decrementer_shutdown(struct clock_event_device *evt);
|
||||
|
||||
struct clock_event_device decrementer_clockevent = {
|
||||
.name = "decrementer",
|
||||
.rating = 200,
|
||||
.irq = 0,
|
||||
.set_next_event = decrementer_set_next_event,
|
||||
.set_mode = decrementer_set_mode,
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP,
|
||||
.name = "decrementer",
|
||||
.rating = 200,
|
||||
.irq = 0,
|
||||
.set_next_event = decrementer_set_next_event,
|
||||
.set_state_shutdown = decrementer_shutdown,
|
||||
.tick_resume = decrementer_shutdown,
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT |
|
||||
CLOCK_EVT_FEAT_C3STOP,
|
||||
};
|
||||
EXPORT_SYMBOL(decrementer_clockevent);
|
||||
|
||||
|
@ -862,11 +863,10 @@ static int decrementer_set_next_event(unsigned long evt,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void decrementer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *dev)
|
||||
static int decrementer_shutdown(struct clock_event_device *dev)
|
||||
{
|
||||
if (mode != CLOCK_EVT_MODE_ONESHOT)
|
||||
decrementer_set_next_event(DECREMENTER_MAX, dev);
|
||||
decrementer_set_next_event(DECREMENTER_MAX, dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Interrupt handler for the timer broadcast IPI */
|
||||
|
|
|
@ -120,11 +120,6 @@ static int s390_next_event(unsigned long delta,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void s390_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up lowcore and control register of the current cpu to
|
||||
* enable TOD clock and clock comparator interrupts.
|
||||
|
@ -148,7 +143,6 @@ void init_cpu_timer(void)
|
|||
cd->rating = 400;
|
||||
cd->cpumask = cpumask_of(cpu);
|
||||
cd->set_next_event = s390_next_event;
|
||||
cd->set_mode = s390_set_mode;
|
||||
|
||||
clockevents_register_device(cd);
|
||||
|
||||
|
|
|
@ -55,31 +55,20 @@ static int score_timer_set_next_event(unsigned long delta,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void score_timer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evdev)
|
||||
static int score_timer_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
outl((TMR_M_PERIODIC | TMR_IE_ENABLE), P_TIMER0_CTRL);
|
||||
outl(SYSTEM_CLOCK/HZ, P_TIMER0_PRELOAD);
|
||||
outl(inl(P_TIMER0_CTRL) | TMR_ENABLE, P_TIMER0_CTRL);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
outl((TMR_M_PERIODIC | TMR_IE_ENABLE), P_TIMER0_CTRL);
|
||||
outl(SYSTEM_CLOCK / HZ, P_TIMER0_PRELOAD);
|
||||
outl(inl(P_TIMER0_CTRL) | TMR_ENABLE, P_TIMER0_CTRL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clock_event_device score_clockevent = {
|
||||
.name = "score_clockevent",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC,
|
||||
.shift = 16,
|
||||
.set_next_event = score_timer_set_next_event,
|
||||
.set_mode = score_timer_set_mode,
|
||||
.name = "score_clockevent",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC,
|
||||
.shift = 16,
|
||||
.set_next_event = score_timer_set_next_event,
|
||||
.set_state_periodic = score_timer_set_periodic,
|
||||
};
|
||||
|
||||
void __init time_init(void)
|
||||
|
|
|
@ -39,11 +39,6 @@ void local_timer_interrupt(void)
|
|||
irq_exit();
|
||||
}
|
||||
|
||||
static void dummy_timer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *clk)
|
||||
{
|
||||
}
|
||||
|
||||
void local_timer_setup(unsigned int cpu)
|
||||
{
|
||||
struct clock_event_device *clk = &per_cpu(local_clockevent, cpu);
|
||||
|
@ -54,7 +49,6 @@ void local_timer_setup(unsigned int cpu)
|
|||
CLOCK_EVT_FEAT_DUMMY;
|
||||
clk->rating = 400;
|
||||
clk->mult = 1;
|
||||
clk->set_mode = dummy_timer_set_mode;
|
||||
clk->broadcast = smp_timer_broadcast;
|
||||
clk->cpumask = cpumask_of(cpu);
|
||||
|
||||
|
|
|
@ -247,7 +247,7 @@ void smp4m_percpu_timer_interrupt(struct pt_regs *regs)
|
|||
|
||||
ce = &per_cpu(sparc32_clockevent, cpu);
|
||||
|
||||
if (ce->mode & CLOCK_EVT_MODE_PERIODIC)
|
||||
if (clockevent_state_periodic(ce))
|
||||
sun4m_clear_profile_irq(cpu);
|
||||
else
|
||||
sparc_config.load_profile_irq(cpu, 0); /* Is this needless? */
|
||||
|
|
|
@ -101,21 +101,18 @@ irqreturn_t notrace timer_interrupt(int dummy, void *dev_id)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void timer_ce_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static int timer_ce_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
timer_ce_enabled = 1;
|
||||
break;
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
timer_ce_enabled = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
timer_ce_enabled = 0;
|
||||
smp_mb();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int timer_ce_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
timer_ce_enabled = 1;
|
||||
smp_mb();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __init void setup_timer_ce(void)
|
||||
|
@ -127,7 +124,9 @@ static __init void setup_timer_ce(void)
|
|||
ce->name = "timer_ce";
|
||||
ce->rating = 100;
|
||||
ce->features = CLOCK_EVT_FEAT_PERIODIC;
|
||||
ce->set_mode = timer_ce_set_mode;
|
||||
ce->set_state_shutdown = timer_ce_shutdown;
|
||||
ce->set_state_periodic = timer_ce_set_periodic;
|
||||
ce->tick_resume = timer_ce_set_periodic;
|
||||
ce->cpumask = cpu_possible_mask;
|
||||
ce->shift = 32;
|
||||
ce->mult = div_sc(sparc_config.clock_rate, NSEC_PER_SEC,
|
||||
|
@ -183,24 +182,20 @@ static __init int setup_timer_cs(void)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static void percpu_ce_setup(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static int percpu_ce_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
int cpu = cpumask_first(evt->cpumask);
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
sparc_config.load_profile_irq(cpu,
|
||||
SBUS_CLOCK_RATE / HZ);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
sparc_config.load_profile_irq(cpu, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sparc_config.load_profile_irq(cpu, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int percpu_ce_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
int cpu = cpumask_first(evt->cpumask);
|
||||
|
||||
sparc_config.load_profile_irq(cpu, SBUS_CLOCK_RATE / HZ);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int percpu_ce_set_next_event(unsigned long delta,
|
||||
|
@ -224,7 +219,9 @@ void register_percpu_ce(int cpu)
|
|||
ce->name = "percpu_ce";
|
||||
ce->rating = 200;
|
||||
ce->features = features;
|
||||
ce->set_mode = percpu_ce_setup;
|
||||
ce->set_state_shutdown = percpu_ce_shutdown;
|
||||
ce->set_state_periodic = percpu_ce_set_periodic;
|
||||
ce->set_state_oneshot = percpu_ce_shutdown;
|
||||
ce->set_next_event = percpu_ce_set_next_event;
|
||||
ce->cpumask = cpumask_of(cpu);
|
||||
ce->shift = 32;
|
||||
|
|
|
@ -674,32 +674,19 @@ static int sparc64_next_event(unsigned long delta,
|
|||
return tick_ops->add_compare(delta) ? -ETIME : 0;
|
||||
}
|
||||
|
||||
static void sparc64_timer_setup(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static int sparc64_timer_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
break;
|
||||
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
tick_ops->disable_irq();
|
||||
break;
|
||||
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
WARN_ON(1);
|
||||
break;
|
||||
}
|
||||
tick_ops->disable_irq();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clock_event_device sparc64_clockevent = {
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_mode = sparc64_timer_setup,
|
||||
.set_next_event = sparc64_next_event,
|
||||
.rating = 100,
|
||||
.shift = 30,
|
||||
.irq = -1,
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_state_shutdown = sparc64_timer_shutdown,
|
||||
.set_next_event = sparc64_next_event,
|
||||
.rating = 100,
|
||||
.shift = 30,
|
||||
.irq = -1,
|
||||
};
|
||||
static DEFINE_PER_CPU(struct clock_event_device, sparc64_events);
|
||||
|
||||
|
|
|
@ -22,23 +22,16 @@ void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)
|
|||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void itimer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static int itimer_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
set_interval();
|
||||
break;
|
||||
disable_timer();
|
||||
return 0;
|
||||
}
|
||||
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
disable_timer();
|
||||
break;
|
||||
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
break;
|
||||
}
|
||||
static int itimer_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
set_interval();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int itimer_next_event(unsigned long delta,
|
||||
|
@ -48,14 +41,17 @@ static int itimer_next_event(unsigned long delta,
|
|||
}
|
||||
|
||||
static struct clock_event_device itimer_clockevent = {
|
||||
.name = "itimer",
|
||||
.rating = 250,
|
||||
.cpumask = cpu_all_mask,
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_mode = itimer_set_mode,
|
||||
.set_next_event = itimer_next_event,
|
||||
.shift = 32,
|
||||
.irq = 0,
|
||||
.name = "itimer",
|
||||
.rating = 250,
|
||||
.cpumask = cpu_all_mask,
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC |
|
||||
CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_state_shutdown = itimer_shutdown,
|
||||
.set_state_periodic = itimer_set_periodic,
|
||||
.set_state_oneshot = itimer_shutdown,
|
||||
.set_next_event = itimer_next_event,
|
||||
.shift = 32,
|
||||
.irq = 0,
|
||||
};
|
||||
|
||||
static irqreturn_t um_timer(int irq, void *dev)
|
||||
|
|
|
@ -46,29 +46,20 @@ puv3_osmr0_set_next_event(unsigned long delta, struct clock_event_device *c)
|
|||
return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0;
|
||||
}
|
||||
|
||||
static void
|
||||
puv3_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *c)
|
||||
static int puv3_osmr0_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
writel(readl(OST_OIER) & ~OST_OIER_E0, OST_OIER);
|
||||
writel(readl(OST_OSSR) & ~OST_OSSR_M0, OST_OSSR);
|
||||
break;
|
||||
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
break;
|
||||
}
|
||||
writel(readl(OST_OIER) & ~OST_OIER_E0, OST_OIER);
|
||||
writel(readl(OST_OSSR) & ~OST_OSSR_M0, OST_OSSR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clock_event_device ckevt_puv3_osmr0 = {
|
||||
.name = "osmr0",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT,
|
||||
.rating = 200,
|
||||
.set_next_event = puv3_osmr0_set_next_event,
|
||||
.set_mode = puv3_osmr0_set_mode,
|
||||
.name = "osmr0",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT,
|
||||
.rating = 200,
|
||||
.set_next_event = puv3_osmr0_set_next_event,
|
||||
.set_state_shutdown = puv3_osmr0_shutdown,
|
||||
.set_state_oneshot = puv3_osmr0_shutdown,
|
||||
};
|
||||
|
||||
static cycle_t puv3_read_oscr(struct clocksource *cs)
|
||||
|
|
|
@ -34,7 +34,7 @@ static int __init init_pit_clocksource(void)
|
|||
* - when local APIC timer is active (PIT is switched off)
|
||||
*/
|
||||
if (num_possible_cpus() > 1 || is_hpet_enabled() ||
|
||||
i8253_clockevent.mode != CLOCK_EVT_MODE_PERIODIC)
|
||||
!clockevent_state_periodic(&i8253_clockevent))
|
||||
return 0;
|
||||
|
||||
return clocksource_i8253_init();
|
||||
|
|
|
@ -52,8 +52,6 @@ static struct clocksource ccount_clocksource = {
|
|||
|
||||
static int ccount_timer_set_next_event(unsigned long delta,
|
||||
struct clock_event_device *dev);
|
||||
static void ccount_timer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt);
|
||||
struct ccount_timer {
|
||||
struct clock_event_device evt;
|
||||
int irq_enabled;
|
||||
|
@ -77,35 +75,34 @@ static int ccount_timer_set_next_event(unsigned long delta,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void ccount_timer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
/*
|
||||
* There is no way to disable the timer interrupt at the device level,
|
||||
* only at the intenable register itself. Since enable_irq/disable_irq
|
||||
* calls are nested, we need to make sure that these calls are
|
||||
* balanced.
|
||||
*/
|
||||
static int ccount_timer_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
struct ccount_timer *timer =
|
||||
container_of(evt, struct ccount_timer, evt);
|
||||
|
||||
/*
|
||||
* There is no way to disable the timer interrupt at the device level,
|
||||
* only at the intenable register itself. Since enable_irq/disable_irq
|
||||
* calls are nested, we need to make sure that these calls are
|
||||
* balanced.
|
||||
*/
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
if (timer->irq_enabled) {
|
||||
disable_irq(evt->irq);
|
||||
timer->irq_enabled = 0;
|
||||
}
|
||||
break;
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
if (!timer->irq_enabled) {
|
||||
enable_irq(evt->irq);
|
||||
timer->irq_enabled = 1;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
if (timer->irq_enabled) {
|
||||
disable_irq(evt->irq);
|
||||
timer->irq_enabled = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccount_timer_set_oneshot(struct clock_event_device *evt)
|
||||
{
|
||||
struct ccount_timer *timer =
|
||||
container_of(evt, struct ccount_timer, evt);
|
||||
|
||||
if (!timer->irq_enabled) {
|
||||
enable_irq(evt->irq);
|
||||
timer->irq_enabled = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t timer_interrupt(int irq, void *dev_id);
|
||||
|
@ -126,7 +123,9 @@ void local_timer_setup(unsigned cpu)
|
|||
clockevent->features = CLOCK_EVT_FEAT_ONESHOT;
|
||||
clockevent->rating = 300;
|
||||
clockevent->set_next_event = ccount_timer_set_next_event;
|
||||
clockevent->set_mode = ccount_timer_set_mode;
|
||||
clockevent->set_state_shutdown = ccount_timer_shutdown;
|
||||
clockevent->set_state_oneshot = ccount_timer_set_oneshot;
|
||||
clockevent->tick_resume = ccount_timer_set_oneshot;
|
||||
clockevent->cpumask = cpumask_of(cpu);
|
||||
clockevent->irq = irq_create_mapping(NULL, LINUX_TIMER_INT);
|
||||
if (WARN(!clockevent->irq, "error: can't map timer irq"))
|
||||
|
|
|
@ -277,7 +277,7 @@ config CLKSRC_MIPS_GIC
|
|||
|
||||
config CLKSRC_PXA
|
||||
def_bool y if ARCH_PXA || ARCH_SA1100
|
||||
select CLKSRC_OF if USE_OF
|
||||
select CLKSRC_OF if OF
|
||||
help
|
||||
This enables OST0 support available on PXA and SA-11x0
|
||||
platforms.
|
||||
|
|
|
@ -181,44 +181,36 @@ static irqreturn_t arch_timer_handler_virt_mem(int irq, void *dev_id)
|
|||
return timer_handler(ARCH_TIMER_MEM_VIRT_ACCESS, evt);
|
||||
}
|
||||
|
||||
static __always_inline void timer_set_mode(const int access, int mode,
|
||||
struct clock_event_device *clk)
|
||||
static __always_inline int timer_shutdown(const int access,
|
||||
struct clock_event_device *clk)
|
||||
{
|
||||
unsigned long ctrl;
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk);
|
||||
ctrl &= ~ARCH_TIMER_CTRL_ENABLE;
|
||||
arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk);
|
||||
ctrl &= ~ARCH_TIMER_CTRL_ENABLE;
|
||||
arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void arch_timer_set_mode_virt(enum clock_event_mode mode,
|
||||
struct clock_event_device *clk)
|
||||
static int arch_timer_shutdown_virt(struct clock_event_device *clk)
|
||||
{
|
||||
timer_set_mode(ARCH_TIMER_VIRT_ACCESS, mode, clk);
|
||||
return timer_shutdown(ARCH_TIMER_VIRT_ACCESS, clk);
|
||||
}
|
||||
|
||||
static void arch_timer_set_mode_phys(enum clock_event_mode mode,
|
||||
struct clock_event_device *clk)
|
||||
static int arch_timer_shutdown_phys(struct clock_event_device *clk)
|
||||
{
|
||||
timer_set_mode(ARCH_TIMER_PHYS_ACCESS, mode, clk);
|
||||
return timer_shutdown(ARCH_TIMER_PHYS_ACCESS, clk);
|
||||
}
|
||||
|
||||
static void arch_timer_set_mode_virt_mem(enum clock_event_mode mode,
|
||||
struct clock_event_device *clk)
|
||||
static int arch_timer_shutdown_virt_mem(struct clock_event_device *clk)
|
||||
{
|
||||
timer_set_mode(ARCH_TIMER_MEM_VIRT_ACCESS, mode, clk);
|
||||
return timer_shutdown(ARCH_TIMER_MEM_VIRT_ACCESS, clk);
|
||||
}
|
||||
|
||||
static void arch_timer_set_mode_phys_mem(enum clock_event_mode mode,
|
||||
struct clock_event_device *clk)
|
||||
static int arch_timer_shutdown_phys_mem(struct clock_event_device *clk)
|
||||
{
|
||||
timer_set_mode(ARCH_TIMER_MEM_PHYS_ACCESS, mode, clk);
|
||||
return timer_shutdown(ARCH_TIMER_MEM_PHYS_ACCESS, clk);
|
||||
}
|
||||
|
||||
static __always_inline void set_next_event(const int access, unsigned long evt,
|
||||
|
@ -273,11 +265,11 @@ static void __arch_timer_setup(unsigned type,
|
|||
clk->cpumask = cpumask_of(smp_processor_id());
|
||||
if (arch_timer_use_virtual) {
|
||||
clk->irq = arch_timer_ppi[VIRT_PPI];
|
||||
clk->set_mode = arch_timer_set_mode_virt;
|
||||
clk->set_state_shutdown = arch_timer_shutdown_virt;
|
||||
clk->set_next_event = arch_timer_set_next_event_virt;
|
||||
} else {
|
||||
clk->irq = arch_timer_ppi[PHYS_SECURE_PPI];
|
||||
clk->set_mode = arch_timer_set_mode_phys;
|
||||
clk->set_state_shutdown = arch_timer_shutdown_phys;
|
||||
clk->set_next_event = arch_timer_set_next_event_phys;
|
||||
}
|
||||
} else {
|
||||
|
@ -286,17 +278,17 @@ static void __arch_timer_setup(unsigned type,
|
|||
clk->rating = 400;
|
||||
clk->cpumask = cpu_all_mask;
|
||||
if (arch_timer_mem_use_virtual) {
|
||||
clk->set_mode = arch_timer_set_mode_virt_mem;
|
||||
clk->set_state_shutdown = arch_timer_shutdown_virt_mem;
|
||||
clk->set_next_event =
|
||||
arch_timer_set_next_event_virt_mem;
|
||||
} else {
|
||||
clk->set_mode = arch_timer_set_mode_phys_mem;
|
||||
clk->set_state_shutdown = arch_timer_shutdown_phys_mem;
|
||||
clk->set_next_event =
|
||||
arch_timer_set_next_event_phys_mem;
|
||||
}
|
||||
}
|
||||
|
||||
clk->set_mode(CLOCK_EVT_MODE_SHUTDOWN, clk);
|
||||
clk->set_state_shutdown(clk);
|
||||
|
||||
clockevents_config_and_register(clk, arch_timer_rate, 0xf, 0x7fffffff);
|
||||
}
|
||||
|
@ -506,7 +498,7 @@ static void arch_timer_stop(struct clock_event_device *clk)
|
|||
disable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI]);
|
||||
}
|
||||
|
||||
clk->set_mode(CLOCK_EVT_MODE_UNUSED, clk);
|
||||
clk->set_state_shutdown(clk);
|
||||
}
|
||||
|
||||
static int arch_timer_cpu_notify(struct notifier_block *self,
|
||||
|
|
|
@ -107,26 +107,21 @@ static void gt_compare_set(unsigned long delta, int periodic)
|
|||
writel(ctrl, gt_base + GT_CONTROL);
|
||||
}
|
||||
|
||||
static void gt_clockevent_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *clk)
|
||||
static int gt_clockevent_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
unsigned long ctrl;
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
gt_compare_set(DIV_ROUND_CLOSEST(gt_clk_rate, HZ), 1);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
ctrl = readl(gt_base + GT_CONTROL);
|
||||
ctrl &= ~(GT_CONTROL_COMP_ENABLE |
|
||||
GT_CONTROL_IRQ_ENABLE | GT_CONTROL_AUTO_INC);
|
||||
writel(ctrl, gt_base + GT_CONTROL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ctrl = readl(gt_base + GT_CONTROL);
|
||||
ctrl &= ~(GT_CONTROL_COMP_ENABLE | GT_CONTROL_IRQ_ENABLE |
|
||||
GT_CONTROL_AUTO_INC);
|
||||
writel(ctrl, gt_base + GT_CONTROL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gt_clockevent_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
gt_compare_set(DIV_ROUND_CLOSEST(gt_clk_rate, HZ), 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gt_clockevent_set_next_event(unsigned long evt,
|
||||
|
@ -155,7 +150,7 @@ static irqreturn_t gt_clockevent_interrupt(int irq, void *dev_id)
|
|||
* the Global Timer flag _after_ having incremented
|
||||
* the Comparator register value to a higher value.
|
||||
*/
|
||||
if (evt->mode == CLOCK_EVT_MODE_ONESHOT)
|
||||
if (clockevent_state_oneshot(evt))
|
||||
gt_compare_set(ULONG_MAX, 0);
|
||||
|
||||
writel_relaxed(GT_INT_STATUS_EVENT_FLAG, gt_base + GT_INT_STATUS);
|
||||
|
@ -171,7 +166,9 @@ static int gt_clockevents_init(struct clock_event_device *clk)
|
|||
clk->name = "arm_global_timer";
|
||||
clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
|
||||
CLOCK_EVT_FEAT_PERCPU;
|
||||
clk->set_mode = gt_clockevent_set_mode;
|
||||
clk->set_state_shutdown = gt_clockevent_shutdown;
|
||||
clk->set_state_periodic = gt_clockevent_set_periodic;
|
||||
clk->set_state_oneshot = gt_clockevent_shutdown;
|
||||
clk->set_next_event = gt_clockevent_set_next_event;
|
||||
clk->cpumask = cpumask_of(cpu);
|
||||
clk->rating = 300;
|
||||
|
@ -184,7 +181,7 @@ static int gt_clockevents_init(struct clock_event_device *clk)
|
|||
|
||||
static void gt_clockevents_stop(struct clock_event_device *clk)
|
||||
{
|
||||
gt_clockevent_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
|
||||
gt_clockevent_shutdown(clk);
|
||||
disable_percpu_irq(clk->irq);
|
||||
}
|
||||
|
||||
|
|
|
@ -120,38 +120,52 @@ static int asm9260_timer_set_next_event(unsigned long delta,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void asm9260_timer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static inline void __asm9260_timer_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
/* stop timer0 */
|
||||
writel_relaxed(BM_C0_EN, priv.base + HW_TCR + CLR_REG);
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
/* disable reset and stop on match */
|
||||
writel_relaxed(BM_MCR_RES_EN(0) | BM_MCR_STOP_EN(0),
|
||||
priv.base + HW_MCR + CLR_REG);
|
||||
/* configure match count for TC0 */
|
||||
writel_relaxed(priv.ticks_per_jiffy, priv.base + HW_MR0);
|
||||
/* enable TC0 */
|
||||
writel_relaxed(BM_C0_EN, priv.base + HW_TCR + SET_REG);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
/* enable reset and stop on match */
|
||||
writel_relaxed(BM_MCR_RES_EN(0) | BM_MCR_STOP_EN(0),
|
||||
priv.base + HW_MCR + SET_REG);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
static int asm9260_timer_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
__asm9260_timer_shutdown(evt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int asm9260_timer_set_oneshot(struct clock_event_device *evt)
|
||||
{
|
||||
__asm9260_timer_shutdown(evt);
|
||||
|
||||
/* enable reset and stop on match */
|
||||
writel_relaxed(BM_MCR_RES_EN(0) | BM_MCR_STOP_EN(0),
|
||||
priv.base + HW_MCR + SET_REG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int asm9260_timer_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
__asm9260_timer_shutdown(evt);
|
||||
|
||||
/* disable reset and stop on match */
|
||||
writel_relaxed(BM_MCR_RES_EN(0) | BM_MCR_STOP_EN(0),
|
||||
priv.base + HW_MCR + CLR_REG);
|
||||
/* configure match count for TC0 */
|
||||
writel_relaxed(priv.ticks_per_jiffy, priv.base + HW_MR0);
|
||||
/* enable TC0 */
|
||||
writel_relaxed(BM_C0_EN, priv.base + HW_TCR + SET_REG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clock_event_device event_dev = {
|
||||
.name = DRIVER_NAME,
|
||||
.rating = 200,
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_next_event = asm9260_timer_set_next_event,
|
||||
.set_mode = asm9260_timer_set_mode,
|
||||
.name = DRIVER_NAME,
|
||||
.rating = 200,
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC |
|
||||
CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_next_event = asm9260_timer_set_next_event,
|
||||
.set_state_shutdown = asm9260_timer_shutdown,
|
||||
.set_state_periodic = asm9260_timer_set_periodic,
|
||||
.set_state_oneshot = asm9260_timer_set_oneshot,
|
||||
.tick_resume = asm9260_timer_shutdown,
|
||||
};
|
||||
|
||||
static irqreturn_t asm9260_timer_interrupt(int irq, void *dev_id)
|
||||
|
|
|
@ -54,21 +54,6 @@ static u64 notrace bcm2835_sched_read(void)
|
|||
return readl_relaxed(system_clock);
|
||||
}
|
||||
|
||||
static void bcm2835_time_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt_dev)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
break;
|
||||
default:
|
||||
WARN(1, "%s: unhandled event mode %d\n", __func__, mode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int bcm2835_time_set_next_event(unsigned long event,
|
||||
struct clock_event_device *evt_dev)
|
||||
{
|
||||
|
@ -129,7 +114,6 @@ static void __init bcm2835_timer_init(struct device_node *node)
|
|||
timer->evt.name = node->name;
|
||||
timer->evt.rating = 300;
|
||||
timer->evt.features = CLOCK_EVT_FEAT_ONESHOT;
|
||||
timer->evt.set_mode = bcm2835_time_set_mode;
|
||||
timer->evt.set_next_event = bcm2835_time_set_next_event;
|
||||
timer->evt.cpumask = cpumask_of(0);
|
||||
timer->act.name = node->name;
|
||||
|
|
|
@ -127,25 +127,18 @@ static int kona_timer_set_next_event(unsigned long clc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void kona_timer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *unused)
|
||||
static int kona_timer_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
/* by default mode is one shot don't do any thing */
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
default:
|
||||
kona_timer_disable_and_clear(timers.tmr_regs);
|
||||
}
|
||||
kona_timer_disable_and_clear(timers.tmr_regs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clock_event_device kona_clockevent_timer = {
|
||||
.name = "timer 1",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_next_event = kona_timer_set_next_event,
|
||||
.set_mode = kona_timer_set_mode
|
||||
.set_state_shutdown = kona_timer_shutdown,
|
||||
.tick_resume = kona_timer_shutdown,
|
||||
};
|
||||
|
||||
static void __init kona_timer_clockevents_init(void)
|
||||
|
|
|
@ -190,40 +190,42 @@ static int ttc_set_next_event(unsigned long cycles,
|
|||
}
|
||||
|
||||
/**
|
||||
* ttc_set_mode - Sets the mode of timer
|
||||
* ttc_set_{shutdown|oneshot|periodic} - Sets the state of timer
|
||||
*
|
||||
* @mode: Mode to be set
|
||||
* @evt: Address of clock event instance
|
||||
**/
|
||||
static void ttc_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static int ttc_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt);
|
||||
struct ttc_timer *timer = &ttce->ttc;
|
||||
u32 ctrl_reg;
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
ttc_set_interval(timer, DIV_ROUND_CLOSEST(ttce->ttc.freq,
|
||||
PRESCALE * HZ));
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
ctrl_reg = readl_relaxed(timer->base_addr +
|
||||
TTC_CNT_CNTRL_OFFSET);
|
||||
ctrl_reg |= TTC_CNT_CNTRL_DISABLE_MASK;
|
||||
writel_relaxed(ctrl_reg,
|
||||
timer->base_addr + TTC_CNT_CNTRL_OFFSET);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
ctrl_reg = readl_relaxed(timer->base_addr +
|
||||
TTC_CNT_CNTRL_OFFSET);
|
||||
ctrl_reg &= ~TTC_CNT_CNTRL_DISABLE_MASK;
|
||||
writel_relaxed(ctrl_reg,
|
||||
timer->base_addr + TTC_CNT_CNTRL_OFFSET);
|
||||
break;
|
||||
}
|
||||
ctrl_reg = readl_relaxed(timer->base_addr + TTC_CNT_CNTRL_OFFSET);
|
||||
ctrl_reg |= TTC_CNT_CNTRL_DISABLE_MASK;
|
||||
writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ttc_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt);
|
||||
struct ttc_timer *timer = &ttce->ttc;
|
||||
|
||||
ttc_set_interval(timer,
|
||||
DIV_ROUND_CLOSEST(ttce->ttc.freq, PRESCALE * HZ));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ttc_resume(struct clock_event_device *evt)
|
||||
{
|
||||
struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt);
|
||||
struct ttc_timer *timer = &ttce->ttc;
|
||||
u32 ctrl_reg;
|
||||
|
||||
ctrl_reg = readl_relaxed(timer->base_addr + TTC_CNT_CNTRL_OFFSET);
|
||||
ctrl_reg &= ~TTC_CNT_CNTRL_DISABLE_MASK;
|
||||
writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ttc_rate_change_clocksource_cb(struct notifier_block *nb,
|
||||
|
@ -429,7 +431,10 @@ static void __init ttc_setup_clockevent(struct clk *clk,
|
|||
ttcce->ce.name = "ttc_clockevent";
|
||||
ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
|
||||
ttcce->ce.set_next_event = ttc_set_next_event;
|
||||
ttcce->ce.set_mode = ttc_set_mode;
|
||||
ttcce->ce.set_state_shutdown = ttc_shutdown;
|
||||
ttcce->ce.set_state_periodic = ttc_set_periodic;
|
||||
ttcce->ce.set_state_oneshot = ttc_shutdown;
|
||||
ttcce->ce.tick_resume = ttc_resume;
|
||||
ttcce->ce.rating = 200;
|
||||
ttcce->ce.irq = irq;
|
||||
ttcce->ce.cpumask = cpu_possible_mask;
|
||||
|
|
|
@ -61,11 +61,6 @@ static irqreturn_t clps711x_timer_interrupt(int irq, void *dev_id)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void clps711x_clockevent_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
}
|
||||
|
||||
static int __init _clps711x_clkevt_init(struct clk *clock, void __iomem *base,
|
||||
unsigned int irq)
|
||||
{
|
||||
|
@ -91,7 +86,6 @@ static int __init _clps711x_clkevt_init(struct clk *clock, void __iomem *base,
|
|||
clkevt->name = "clps711x-clockevent";
|
||||
clkevt->rating = 300;
|
||||
clkevt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_C3STOP;
|
||||
clkevt->set_mode = clps711x_clockevent_set_mode;
|
||||
clkevt->cpumask = cpumask_of(0);
|
||||
clockevents_config_and_register(clkevt, HZ, 0, 0);
|
||||
|
||||
|
|
|
@ -42,7 +42,6 @@ MODULE_PARM_DESC(irq, "Which IRQ to use for the clock source MFGPT ticks.");
|
|||
* 256 128 .125 512.000
|
||||
*/
|
||||
|
||||
static unsigned int cs5535_tick_mode = CLOCK_EVT_MODE_SHUTDOWN;
|
||||
static struct cs5535_mfgpt_timer *cs5535_event_clock;
|
||||
|
||||
/* Selected from the table above */
|
||||
|
@ -77,15 +76,17 @@ static void start_timer(struct cs5535_mfgpt_timer *timer, uint16_t delta)
|
|||
MFGPT_SETUP_CNTEN | MFGPT_SETUP_CMP2);
|
||||
}
|
||||
|
||||
static void mfgpt_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static int mfgpt_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
disable_timer(cs5535_event_clock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mode == CLOCK_EVT_MODE_PERIODIC)
|
||||
start_timer(cs5535_event_clock, MFGPT_PERIODIC);
|
||||
|
||||
cs5535_tick_mode = mode;
|
||||
static int mfgpt_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
disable_timer(cs5535_event_clock);
|
||||
start_timer(cs5535_event_clock, MFGPT_PERIODIC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mfgpt_next_event(unsigned long delta, struct clock_event_device *evt)
|
||||
|
@ -97,7 +98,10 @@ static int mfgpt_next_event(unsigned long delta, struct clock_event_device *evt)
|
|||
static struct clock_event_device cs5535_clockevent = {
|
||||
.name = DRV_NAME,
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_mode = mfgpt_set_mode,
|
||||
.set_state_shutdown = mfgpt_shutdown,
|
||||
.set_state_periodic = mfgpt_set_periodic,
|
||||
.set_state_oneshot = mfgpt_shutdown,
|
||||
.tick_resume = mfgpt_shutdown,
|
||||
.set_next_event = mfgpt_next_event,
|
||||
.rating = 250,
|
||||
};
|
||||
|
@ -113,7 +117,7 @@ static irqreturn_t mfgpt_tick(int irq, void *dev_id)
|
|||
/* Turn off the clock (and clear the event) */
|
||||
disable_timer(cs5535_event_clock);
|
||||
|
||||
if (cs5535_tick_mode == CLOCK_EVT_MODE_SHUTDOWN)
|
||||
if (clockevent_state_shutdown(&cs5535_clockevent))
|
||||
return IRQ_HANDLED;
|
||||
|
||||
/* Clear the counter */
|
||||
|
@ -121,7 +125,7 @@ static irqreturn_t mfgpt_tick(int irq, void *dev_id)
|
|||
|
||||
/* Restart the clock in periodic mode */
|
||||
|
||||
if (cs5535_tick_mode == CLOCK_EVT_MODE_PERIODIC)
|
||||
if (clockevent_state_periodic(&cs5535_clockevent))
|
||||
cs5535_mfgpt_write(cs5535_event_clock, MFGPT_REG_SETUP,
|
||||
MFGPT_SETUP_CNTEN | MFGPT_SETUP_CMP2);
|
||||
|
||||
|
|
|
@ -16,15 +16,6 @@
|
|||
|
||||
static DEFINE_PER_CPU(struct clock_event_device, dummy_timer_evt);
|
||||
|
||||
static void dummy_timer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
/*
|
||||
* Core clockevents code will call this when exchanging timer devices.
|
||||
* We don't need to do anything here.
|
||||
*/
|
||||
}
|
||||
|
||||
static void dummy_timer_setup(void)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
|
@ -35,7 +26,6 @@ static void dummy_timer_setup(void)
|
|||
CLOCK_EVT_FEAT_ONESHOT |
|
||||
CLOCK_EVT_FEAT_DUMMY;
|
||||
evt->rating = 100;
|
||||
evt->set_mode = dummy_timer_set_mode;
|
||||
evt->cpumask = cpumask_of(cpu);
|
||||
|
||||
clockevents_register_device(evt);
|
||||
|
|
|
@ -110,71 +110,87 @@ static void apbt_enable_int(struct dw_apb_timer *timer)
|
|||
apbt_writel(timer, ctrl, APBTMR_N_CONTROL);
|
||||
}
|
||||
|
||||
static void apbt_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static int apbt_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
|
||||
unsigned long ctrl;
|
||||
unsigned long period;
|
||||
|
||||
pr_debug("%s CPU %d state=shutdown\n", __func__,
|
||||
cpumask_first(evt->cpumask));
|
||||
|
||||
ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
|
||||
ctrl &= ~APBTMR_CONTROL_ENABLE;
|
||||
apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int apbt_set_oneshot(struct clock_event_device *evt)
|
||||
{
|
||||
struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
|
||||
unsigned long ctrl;
|
||||
|
||||
pr_debug("%s CPU %d state=oneshot\n", __func__,
|
||||
cpumask_first(evt->cpumask));
|
||||
|
||||
ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
|
||||
/*
|
||||
* set free running mode, this mode will let timer reload max
|
||||
* timeout which will give time (3min on 25MHz clock) to rearm
|
||||
* the next event, therefore emulate the one-shot mode.
|
||||
*/
|
||||
ctrl &= ~APBTMR_CONTROL_ENABLE;
|
||||
ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC;
|
||||
|
||||
apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
|
||||
/* write again to set free running mode */
|
||||
apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
|
||||
|
||||
/*
|
||||
* DW APB p. 46, load counter with all 1s before starting free
|
||||
* running mode.
|
||||
*/
|
||||
apbt_writel(&dw_ced->timer, ~0, APBTMR_N_LOAD_COUNT);
|
||||
ctrl &= ~APBTMR_CONTROL_INT;
|
||||
ctrl |= APBTMR_CONTROL_ENABLE;
|
||||
apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int apbt_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
|
||||
unsigned long period = DIV_ROUND_UP(dw_ced->timer.freq, HZ);
|
||||
unsigned long ctrl;
|
||||
|
||||
pr_debug("%s CPU %d state=periodic\n", __func__,
|
||||
cpumask_first(evt->cpumask));
|
||||
|
||||
ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
|
||||
ctrl |= APBTMR_CONTROL_MODE_PERIODIC;
|
||||
apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
|
||||
/*
|
||||
* DW APB p. 46, have to disable timer before load counter,
|
||||
* may cause sync problem.
|
||||
*/
|
||||
ctrl &= ~APBTMR_CONTROL_ENABLE;
|
||||
apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
|
||||
udelay(1);
|
||||
pr_debug("Setting clock period %lu for HZ %d\n", period, HZ);
|
||||
apbt_writel(&dw_ced->timer, period, APBTMR_N_LOAD_COUNT);
|
||||
ctrl |= APBTMR_CONTROL_ENABLE;
|
||||
apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int apbt_resume(struct clock_event_device *evt)
|
||||
{
|
||||
struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
|
||||
|
||||
pr_debug("%s CPU %d mode=%d\n", __func__,
|
||||
cpumask_first(evt->cpumask),
|
||||
mode);
|
||||
pr_debug("%s CPU %d state=resume\n", __func__,
|
||||
cpumask_first(evt->cpumask));
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
period = DIV_ROUND_UP(dw_ced->timer.freq, HZ);
|
||||
ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
|
||||
ctrl |= APBTMR_CONTROL_MODE_PERIODIC;
|
||||
apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
|
||||
/*
|
||||
* DW APB p. 46, have to disable timer before load counter,
|
||||
* may cause sync problem.
|
||||
*/
|
||||
ctrl &= ~APBTMR_CONTROL_ENABLE;
|
||||
apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
|
||||
udelay(1);
|
||||
pr_debug("Setting clock period %lu for HZ %d\n", period, HZ);
|
||||
apbt_writel(&dw_ced->timer, period, APBTMR_N_LOAD_COUNT);
|
||||
ctrl |= APBTMR_CONTROL_ENABLE;
|
||||
apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
|
||||
break;
|
||||
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
|
||||
/*
|
||||
* set free running mode, this mode will let timer reload max
|
||||
* timeout which will give time (3min on 25MHz clock) to rearm
|
||||
* the next event, therefore emulate the one-shot mode.
|
||||
*/
|
||||
ctrl &= ~APBTMR_CONTROL_ENABLE;
|
||||
ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC;
|
||||
|
||||
apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
|
||||
/* write again to set free running mode */
|
||||
apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
|
||||
|
||||
/*
|
||||
* DW APB p. 46, load counter with all 1s before starting free
|
||||
* running mode.
|
||||
*/
|
||||
apbt_writel(&dw_ced->timer, ~0, APBTMR_N_LOAD_COUNT);
|
||||
ctrl &= ~APBTMR_CONTROL_INT;
|
||||
ctrl |= APBTMR_CONTROL_ENABLE;
|
||||
apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
|
||||
break;
|
||||
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
|
||||
ctrl &= ~APBTMR_CONTROL_ENABLE;
|
||||
apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
|
||||
break;
|
||||
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
apbt_enable_int(&dw_ced->timer);
|
||||
break;
|
||||
}
|
||||
apbt_enable_int(&dw_ced->timer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int apbt_next_event(unsigned long delta,
|
||||
|
@ -232,8 +248,12 @@ dw_apb_clockevent_init(int cpu, const char *name, unsigned rating,
|
|||
&dw_ced->ced);
|
||||
dw_ced->ced.min_delta_ns = clockevent_delta2ns(5000, &dw_ced->ced);
|
||||
dw_ced->ced.cpumask = cpumask_of(cpu);
|
||||
dw_ced->ced.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
|
||||
dw_ced->ced.set_mode = apbt_set_mode;
|
||||
dw_ced->ced.features = CLOCK_EVT_FEAT_PERIODIC |
|
||||
CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_DYNIRQ;
|
||||
dw_ced->ced.set_state_shutdown = apbt_shutdown;
|
||||
dw_ced->ced.set_state_periodic = apbt_set_periodic;
|
||||
dw_ced->ced.set_state_oneshot = apbt_set_oneshot;
|
||||
dw_ced->ced.tick_resume = apbt_resume;
|
||||
dw_ced->ced.set_next_event = apbt_next_event;
|
||||
dw_ced->ced.irq = dw_ced->timer.irq;
|
||||
dw_ced->ced.rating = rating;
|
||||
|
|
|
@ -251,33 +251,21 @@ static struct em_sti_priv *ced_to_em_sti(struct clock_event_device *ced)
|
|||
return container_of(ced, struct em_sti_priv, ced);
|
||||
}
|
||||
|
||||
static void em_sti_clock_event_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *ced)
|
||||
static int em_sti_clock_event_shutdown(struct clock_event_device *ced)
|
||||
{
|
||||
struct em_sti_priv *p = ced_to_em_sti(ced);
|
||||
em_sti_stop(p, USER_CLOCKEVENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int em_sti_clock_event_set_oneshot(struct clock_event_device *ced)
|
||||
{
|
||||
struct em_sti_priv *p = ced_to_em_sti(ced);
|
||||
|
||||
/* deal with old setting first */
|
||||
switch (ced->mode) {
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
em_sti_stop(p, USER_CLOCKEVENT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
dev_info(&p->pdev->dev, "used for oneshot clock events\n");
|
||||
em_sti_start(p, USER_CLOCKEVENT);
|
||||
clockevents_config(&p->ced, p->rate);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
em_sti_stop(p, USER_CLOCKEVENT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
dev_info(&p->pdev->dev, "used for oneshot clock events\n");
|
||||
em_sti_start(p, USER_CLOCKEVENT);
|
||||
clockevents_config(&p->ced, p->rate);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int em_sti_clock_event_next(unsigned long delta,
|
||||
|
@ -303,11 +291,12 @@ static void em_sti_register_clockevent(struct em_sti_priv *p)
|
|||
ced->rating = 200;
|
||||
ced->cpumask = cpu_possible_mask;
|
||||
ced->set_next_event = em_sti_clock_event_next;
|
||||
ced->set_mode = em_sti_clock_event_mode;
|
||||
ced->set_state_shutdown = em_sti_clock_event_shutdown;
|
||||
ced->set_state_oneshot = em_sti_clock_event_set_oneshot;
|
||||
|
||||
dev_info(&p->pdev->dev, "used for clock events\n");
|
||||
|
||||
/* Register with dummy 1 Hz value, gets updated in ->set_mode() */
|
||||
/* Register with dummy 1 Hz value, gets updated in ->set_state_oneshot() */
|
||||
clockevents_config_and_register(ced, 1, 2, 0xffffffff);
|
||||
}
|
||||
|
||||
|
|
|
@ -257,15 +257,14 @@ static void exynos4_mct_comp0_stop(void)
|
|||
exynos4_mct_write(0, EXYNOS4_MCT_G_INT_ENB);
|
||||
}
|
||||
|
||||
static void exynos4_mct_comp0_start(enum clock_event_mode mode,
|
||||
unsigned long cycles)
|
||||
static void exynos4_mct_comp0_start(bool periodic, unsigned long cycles)
|
||||
{
|
||||
unsigned int tcon;
|
||||
cycle_t comp_cycle;
|
||||
|
||||
tcon = readl_relaxed(reg_base + EXYNOS4_MCT_G_TCON);
|
||||
|
||||
if (mode == CLOCK_EVT_MODE_PERIODIC) {
|
||||
if (periodic) {
|
||||
tcon |= MCT_G_TCON_COMP0_AUTO_INC;
|
||||
exynos4_mct_write(cycles, EXYNOS4_MCT_G_COMP0_ADD_INCR);
|
||||
}
|
||||
|
@ -283,38 +282,38 @@ static void exynos4_mct_comp0_start(enum clock_event_mode mode,
|
|||
static int exynos4_comp_set_next_event(unsigned long cycles,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
exynos4_mct_comp0_start(evt->mode, cycles);
|
||||
exynos4_mct_comp0_start(false, cycles);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void exynos4_comp_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static int mct_set_state_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
exynos4_mct_comp0_stop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mct_set_state_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
unsigned long cycles_per_jiffy;
|
||||
|
||||
cycles_per_jiffy = (((unsigned long long)NSEC_PER_SEC / HZ * evt->mult)
|
||||
>> evt->shift);
|
||||
exynos4_mct_comp0_stop();
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
cycles_per_jiffy =
|
||||
(((unsigned long long) NSEC_PER_SEC / HZ * evt->mult) >> evt->shift);
|
||||
exynos4_mct_comp0_start(mode, cycles_per_jiffy);
|
||||
break;
|
||||
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
break;
|
||||
}
|
||||
exynos4_mct_comp0_start(true, cycles_per_jiffy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clock_event_device mct_comp_device = {
|
||||
.name = "mct-comp",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
||||
.rating = 250,
|
||||
.set_next_event = exynos4_comp_set_next_event,
|
||||
.set_mode = exynos4_comp_set_mode,
|
||||
.name = "mct-comp",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC |
|
||||
CLOCK_EVT_FEAT_ONESHOT,
|
||||
.rating = 250,
|
||||
.set_next_event = exynos4_comp_set_next_event,
|
||||
.set_state_periodic = mct_set_state_periodic,
|
||||
.set_state_shutdown = mct_set_state_shutdown,
|
||||
.set_state_oneshot = mct_set_state_shutdown,
|
||||
.tick_resume = mct_set_state_shutdown,
|
||||
};
|
||||
|
||||
static irqreturn_t exynos4_mct_comp_isr(int irq, void *dev_id)
|
||||
|
@ -390,39 +389,32 @@ static int exynos4_tick_set_next_event(unsigned long cycles,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline void exynos4_tick_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static int set_state_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
exynos4_mct_tick_stop(this_cpu_ptr(&percpu_mct_tick));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_state_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick);
|
||||
unsigned long cycles_per_jiffy;
|
||||
|
||||
cycles_per_jiffy = (((unsigned long long)NSEC_PER_SEC / HZ * evt->mult)
|
||||
>> evt->shift);
|
||||
exynos4_mct_tick_stop(mevt);
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
cycles_per_jiffy =
|
||||
(((unsigned long long) NSEC_PER_SEC / HZ * evt->mult) >> evt->shift);
|
||||
exynos4_mct_tick_start(cycles_per_jiffy, mevt);
|
||||
break;
|
||||
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
break;
|
||||
}
|
||||
exynos4_mct_tick_start(cycles_per_jiffy, mevt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
|
||||
{
|
||||
struct clock_event_device *evt = &mevt->evt;
|
||||
|
||||
/*
|
||||
* This is for supporting oneshot mode.
|
||||
* Mct would generate interrupt periodically
|
||||
* without explicit stopping.
|
||||
*/
|
||||
if (evt->mode != CLOCK_EVT_MODE_PERIODIC)
|
||||
if (!clockevent_state_periodic(&mevt->evt))
|
||||
exynos4_mct_tick_stop(mevt);
|
||||
|
||||
/* Clear the MCT tick interrupt */
|
||||
|
@ -442,20 +434,21 @@ static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int exynos4_local_timer_setup(struct clock_event_device *evt)
|
||||
static int exynos4_local_timer_setup(struct mct_clock_event_device *mevt)
|
||||
{
|
||||
struct mct_clock_event_device *mevt;
|
||||
struct clock_event_device *evt = &mevt->evt;
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
mevt = container_of(evt, struct mct_clock_event_device, evt);
|
||||
|
||||
mevt->base = EXYNOS4_MCT_L_BASE(cpu);
|
||||
snprintf(mevt->name, sizeof(mevt->name), "mct_tick%d", cpu);
|
||||
|
||||
evt->name = mevt->name;
|
||||
evt->cpumask = cpumask_of(cpu);
|
||||
evt->set_next_event = exynos4_tick_set_next_event;
|
||||
evt->set_mode = exynos4_tick_set_mode;
|
||||
evt->set_state_periodic = set_state_periodic;
|
||||
evt->set_state_shutdown = set_state_shutdown;
|
||||
evt->set_state_oneshot = set_state_shutdown;
|
||||
evt->tick_resume = set_state_shutdown;
|
||||
evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
|
||||
evt->rating = 450;
|
||||
|
||||
|
@ -477,9 +470,11 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void exynos4_local_timer_stop(struct clock_event_device *evt)
|
||||
static void exynos4_local_timer_stop(struct mct_clock_event_device *mevt)
|
||||
{
|
||||
evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
|
||||
struct clock_event_device *evt = &mevt->evt;
|
||||
|
||||
evt->set_state_shutdown(evt);
|
||||
if (mct_int_type == MCT_INT_SPI) {
|
||||
if (evt->irq != -1)
|
||||
disable_irq_nosync(evt->irq);
|
||||
|
@ -500,11 +495,11 @@ static int exynos4_mct_cpu_notify(struct notifier_block *self,
|
|||
switch (action & ~CPU_TASKS_FROZEN) {
|
||||
case CPU_STARTING:
|
||||
mevt = this_cpu_ptr(&percpu_mct_tick);
|
||||
exynos4_local_timer_setup(&mevt->evt);
|
||||
exynos4_local_timer_setup(mevt);
|
||||
break;
|
||||
case CPU_DYING:
|
||||
mevt = this_cpu_ptr(&percpu_mct_tick);
|
||||
exynos4_local_timer_stop(&mevt->evt);
|
||||
exynos4_local_timer_stop(mevt);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -570,7 +565,7 @@ static void __init exynos4_timer_resources(struct device_node *np, void __iomem
|
|||
goto out_irq;
|
||||
|
||||
/* Immediately configure the timer on the boot CPU */
|
||||
exynos4_local_timer_setup(&mevt->evt);
|
||||
exynos4_local_timer_setup(mevt);
|
||||
return;
|
||||
|
||||
out_irq:
|
||||
|
|
|
@ -153,19 +153,16 @@ static int ftm_set_next_event(unsigned long delta,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void ftm_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static int ftm_set_oneshot(struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
ftm_set_next_event(priv->periodic_cyc, evt);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
ftm_counter_disable(priv->clkevt_base);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
ftm_counter_disable(priv->clkevt_base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ftm_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
ftm_set_next_event(priv->periodic_cyc, evt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t ftm_evt_interrupt(int irq, void *dev_id)
|
||||
|
@ -174,7 +171,7 @@ static irqreturn_t ftm_evt_interrupt(int irq, void *dev_id)
|
|||
|
||||
ftm_irq_acknowledge(priv->clkevt_base);
|
||||
|
||||
if (likely(evt->mode == CLOCK_EVT_MODE_ONESHOT)) {
|
||||
if (likely(clockevent_state_oneshot(evt))) {
|
||||
ftm_irq_disable(priv->clkevt_base);
|
||||
ftm_counter_disable(priv->clkevt_base);
|
||||
}
|
||||
|
@ -185,11 +182,13 @@ static irqreturn_t ftm_evt_interrupt(int irq, void *dev_id)
|
|||
}
|
||||
|
||||
static struct clock_event_device ftm_clockevent = {
|
||||
.name = "Freescale ftm timer",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_mode = ftm_set_mode,
|
||||
.set_next_event = ftm_set_next_event,
|
||||
.rating = 300,
|
||||
.name = "Freescale ftm timer",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC |
|
||||
CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_state_periodic = ftm_set_periodic,
|
||||
.set_state_oneshot = ftm_set_oneshot,
|
||||
.set_next_event = ftm_set_next_event,
|
||||
.rating = 300,
|
||||
};
|
||||
|
||||
static struct irqaction ftm_timer_irq = {
|
||||
|
|
|
@ -81,7 +81,7 @@ static irqreturn_t timer8_interrupt(int irq, void *dev_id)
|
|||
p->flags |= FLAG_IRQCONTEXT;
|
||||
ctrl_outw(p->tcora, p->mapbase + TCORA);
|
||||
if (!(p->flags & FLAG_SKIPEVENT)) {
|
||||
if (p->ced.mode == CLOCK_EVT_MODE_ONESHOT)
|
||||
if (clockevent_state_oneshot(&p->ced))
|
||||
ctrl_outw(0x0000, p->mapbase + _8TCR);
|
||||
p->ced.event_handler(&p->ced);
|
||||
}
|
||||
|
@ -169,29 +169,32 @@ static void timer8_clock_event_start(struct timer8_priv *p, int periodic)
|
|||
timer8_set_next(p, periodic?(p->rate + HZ/2) / HZ:0x10000);
|
||||
}
|
||||
|
||||
static void timer8_clock_event_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *ced)
|
||||
static int timer8_clock_event_shutdown(struct clock_event_device *ced)
|
||||
{
|
||||
timer8_stop(ced_to_priv(ced));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int timer8_clock_event_periodic(struct clock_event_device *ced)
|
||||
{
|
||||
struct timer8_priv *p = ced_to_priv(ced);
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
dev_info(&p->pdev->dev, "used for periodic clock events\n");
|
||||
timer8_stop(p);
|
||||
timer8_clock_event_start(p, PERIODIC);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
dev_info(&p->pdev->dev, "used for oneshot clock events\n");
|
||||
timer8_stop(p);
|
||||
timer8_clock_event_start(p, ONESHOT);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
timer8_stop(p);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
dev_info(&p->pdev->dev, "used for periodic clock events\n");
|
||||
timer8_stop(p);
|
||||
timer8_clock_event_start(p, PERIODIC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int timer8_clock_event_oneshot(struct clock_event_device *ced)
|
||||
{
|
||||
struct timer8_priv *p = ced_to_priv(ced);
|
||||
|
||||
dev_info(&p->pdev->dev, "used for oneshot clock events\n");
|
||||
timer8_stop(p);
|
||||
timer8_clock_event_start(p, ONESHOT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int timer8_clock_event_next(unsigned long delta,
|
||||
|
@ -199,7 +202,7 @@ static int timer8_clock_event_next(unsigned long delta,
|
|||
{
|
||||
struct timer8_priv *p = ced_to_priv(ced);
|
||||
|
||||
BUG_ON(ced->mode != CLOCK_EVT_MODE_ONESHOT);
|
||||
BUG_ON(!clockevent_state_oneshot(ced));
|
||||
timer8_set_next(p, delta - 1);
|
||||
|
||||
return 0;
|
||||
|
@ -246,7 +249,9 @@ static int timer8_setup(struct timer8_priv *p,
|
|||
p->ced.rating = 200;
|
||||
p->ced.cpumask = cpumask_of(0);
|
||||
p->ced.set_next_event = timer8_clock_event_next;
|
||||
p->ced.set_mode = timer8_clock_event_mode;
|
||||
p->ced.set_state_shutdown = timer8_clock_event_shutdown;
|
||||
p->ced.set_state_periodic = timer8_clock_event_periodic;
|
||||
p->ced.set_state_oneshot = timer8_clock_event_oneshot;
|
||||
|
||||
ret = setup_irq(irq, &p->irqaction);
|
||||
if (ret < 0) {
|
||||
|
|
|
@ -100,44 +100,40 @@ int __init clocksource_i8253_init(void)
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_CLKEVT_I8253
|
||||
/*
|
||||
* Initialize the PIT timer.
|
||||
*
|
||||
* This is also called after resume to bring the PIT into operation again.
|
||||
*/
|
||||
static void init_pit_timer(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static int pit_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
if (!clockevent_state_oneshot(evt) && !clockevent_state_periodic(evt))
|
||||
return 0;
|
||||
|
||||
raw_spin_lock(&i8253_lock);
|
||||
|
||||
outb_p(0x30, PIT_MODE);
|
||||
outb_p(0, PIT_CH0);
|
||||
outb_p(0, PIT_CH0);
|
||||
|
||||
raw_spin_unlock(&i8253_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pit_set_oneshot(struct clock_event_device *evt)
|
||||
{
|
||||
raw_spin_lock(&i8253_lock);
|
||||
outb_p(0x38, PIT_MODE);
|
||||
raw_spin_unlock(&i8253_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pit_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
raw_spin_lock(&i8253_lock);
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
/* binary, mode 2, LSB/MSB, ch 0 */
|
||||
outb_p(0x34, PIT_MODE);
|
||||
outb_p(PIT_LATCH & 0xff , PIT_CH0); /* LSB */
|
||||
outb_p(PIT_LATCH >> 8 , PIT_CH0); /* MSB */
|
||||
break;
|
||||
/* binary, mode 2, LSB/MSB, ch 0 */
|
||||
outb_p(0x34, PIT_MODE);
|
||||
outb_p(PIT_LATCH & 0xff, PIT_CH0); /* LSB */
|
||||
outb_p(PIT_LATCH >> 8, PIT_CH0); /* MSB */
|
||||
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
if (evt->mode == CLOCK_EVT_MODE_PERIODIC ||
|
||||
evt->mode == CLOCK_EVT_MODE_ONESHOT) {
|
||||
outb_p(0x30, PIT_MODE);
|
||||
outb_p(0, PIT_CH0);
|
||||
outb_p(0, PIT_CH0);
|
||||
}
|
||||
break;
|
||||
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
/* One shot setup */
|
||||
outb_p(0x38, PIT_MODE);
|
||||
break;
|
||||
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
/* Nothing to do here */
|
||||
break;
|
||||
}
|
||||
raw_spin_unlock(&i8253_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -160,10 +156,11 @@ static int pit_next_event(unsigned long delta, struct clock_event_device *evt)
|
|||
* it can be solely used for the global tick.
|
||||
*/
|
||||
struct clock_event_device i8253_clockevent = {
|
||||
.name = "pit",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC,
|
||||
.set_mode = init_pit_timer,
|
||||
.set_next_event = pit_next_event,
|
||||
.name = "pit",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC,
|
||||
.set_state_shutdown = pit_shutdown,
|
||||
.set_state_periodic = pit_set_periodic,
|
||||
.set_next_event = pit_next_event,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -172,8 +169,10 @@ struct clock_event_device i8253_clockevent = {
|
|||
*/
|
||||
void __init clockevent_i8253_init(bool oneshot)
|
||||
{
|
||||
if (oneshot)
|
||||
if (oneshot) {
|
||||
i8253_clockevent.features |= CLOCK_EVT_FEAT_ONESHOT;
|
||||
i8253_clockevent.set_state_oneshot = pit_set_oneshot;
|
||||
}
|
||||
/*
|
||||
* Start pit with the boot cpu mask. x86 might make it global
|
||||
* when it is used as broadcast device later.
|
||||
|
|
|
@ -67,25 +67,25 @@ static void meson6_clkevt_time_start(unsigned char timer, bool periodic)
|
|||
writel(val | TIMER_ENABLE_BIT(timer), timer_base + TIMER_ISA_MUX);
|
||||
}
|
||||
|
||||
static void meson6_clkevt_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *clk)
|
||||
static int meson6_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
meson6_clkevt_time_stop(CED_ID);
|
||||
meson6_clkevt_time_setup(CED_ID, USEC_PER_SEC/HZ - 1);
|
||||
meson6_clkevt_time_start(CED_ID, true);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
meson6_clkevt_time_stop(CED_ID);
|
||||
meson6_clkevt_time_start(CED_ID, false);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
default:
|
||||
meson6_clkevt_time_stop(CED_ID);
|
||||
break;
|
||||
}
|
||||
meson6_clkevt_time_stop(CED_ID);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int meson6_set_oneshot(struct clock_event_device *evt)
|
||||
{
|
||||
meson6_clkevt_time_stop(CED_ID);
|
||||
meson6_clkevt_time_start(CED_ID, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int meson6_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
meson6_clkevt_time_stop(CED_ID);
|
||||
meson6_clkevt_time_setup(CED_ID, USEC_PER_SEC / HZ - 1);
|
||||
meson6_clkevt_time_start(CED_ID, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int meson6_clkevt_next_event(unsigned long evt,
|
||||
|
@ -99,11 +99,15 @@ static int meson6_clkevt_next_event(unsigned long evt,
|
|||
}
|
||||
|
||||
static struct clock_event_device meson6_clockevent = {
|
||||
.name = "meson6_tick",
|
||||
.rating = 400,
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_mode = meson6_clkevt_mode,
|
||||
.set_next_event = meson6_clkevt_next_event,
|
||||
.name = "meson6_tick",
|
||||
.rating = 400,
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC |
|
||||
CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_state_shutdown = meson6_shutdown,
|
||||
.set_state_periodic = meson6_set_periodic,
|
||||
.set_state_oneshot = meson6_set_oneshot,
|
||||
.tick_resume = meson6_shutdown,
|
||||
.set_next_event = meson6_clkevt_next_event,
|
||||
};
|
||||
|
||||
static irqreturn_t meson6_timer_interrupt(int irq, void *dev_id)
|
||||
|
|
|
@ -56,25 +56,6 @@ static int metag_timer_set_next_event(unsigned long delta,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void metag_timer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
break;
|
||||
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
/* We should disable the IRQ here */
|
||||
break;
|
||||
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
WARN_ON(1);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
static cycle_t metag_clocksource_read(struct clocksource *cs)
|
||||
{
|
||||
return __core_reg_get(TXTIMER);
|
||||
|
@ -129,7 +110,6 @@ static void arch_timer_setup(unsigned int cpu)
|
|||
clk->rating = 200,
|
||||
clk->shift = 12,
|
||||
clk->irq = tbisig_map(TBID_SIGNUM_TRT),
|
||||
clk->set_mode = metag_timer_set_mode,
|
||||
clk->set_next_event = metag_timer_set_next_event,
|
||||
|
||||
clk->mult = div_sc(hwtimer_freq, NSEC_PER_SEC, clk->shift);
|
||||
|
|
|
@ -33,12 +33,6 @@ static int gic_next_event(unsigned long delta, struct clock_event_device *evt)
|
|||
return res;
|
||||
}
|
||||
|
||||
static void gic_set_clock_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
/* Nothing to do ... */
|
||||
}
|
||||
|
||||
static irqreturn_t gic_compare_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct clock_event_device *cd = dev_id;
|
||||
|
@ -67,7 +61,6 @@ static void gic_clockevent_cpu_init(struct clock_event_device *cd)
|
|||
cd->irq = gic_timer_irq;
|
||||
cd->cpumask = cpumask_of(cpu);
|
||||
cd->set_next_event = gic_next_event;
|
||||
cd->set_mode = gic_set_clock_mode;
|
||||
|
||||
clockevents_config_and_register(cd, gic_frequency, 0x300, 0x7fffffff);
|
||||
|
||||
|
|
|
@ -58,25 +58,24 @@
|
|||
static void __iomem *base;
|
||||
static unsigned int clock_count_per_tick;
|
||||
|
||||
static void moxart_clkevt_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *clk)
|
||||
static int moxart_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
writel(TIMER1_DISABLE, base + TIMER_CR);
|
||||
writel(~0, base + TIMER1_BASE + REG_LOAD);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
writel(clock_count_per_tick, base + TIMER1_BASE + REG_LOAD);
|
||||
writel(TIMER1_ENABLE, base + TIMER_CR);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
default:
|
||||
writel(TIMER1_DISABLE, base + TIMER_CR);
|
||||
break;
|
||||
}
|
||||
writel(TIMER1_DISABLE, base + TIMER_CR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int moxart_set_oneshot(struct clock_event_device *evt)
|
||||
{
|
||||
writel(TIMER1_DISABLE, base + TIMER_CR);
|
||||
writel(~0, base + TIMER1_BASE + REG_LOAD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int moxart_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
writel(clock_count_per_tick, base + TIMER1_BASE + REG_LOAD);
|
||||
writel(TIMER1_ENABLE, base + TIMER_CR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int moxart_clkevt_next_event(unsigned long cycles,
|
||||
|
@ -95,11 +94,15 @@ static int moxart_clkevt_next_event(unsigned long cycles,
|
|||
}
|
||||
|
||||
static struct clock_event_device moxart_clockevent = {
|
||||
.name = "moxart_timer",
|
||||
.rating = 200,
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_mode = moxart_clkevt_mode,
|
||||
.set_next_event = moxart_clkevt_next_event,
|
||||
.name = "moxart_timer",
|
||||
.rating = 200,
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC |
|
||||
CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_state_shutdown = moxart_shutdown,
|
||||
.set_state_periodic = moxart_set_periodic,
|
||||
.set_state_oneshot = moxart_set_oneshot,
|
||||
.tick_resume = moxart_set_oneshot,
|
||||
.set_next_event = moxart_clkevt_next_event,
|
||||
};
|
||||
|
||||
static irqreturn_t moxart_timer_interrupt(int irq, void *dev_id)
|
||||
|
|
|
@ -102,27 +102,20 @@ static void mtk_clkevt_time_start(struct mtk_clock_event_device *evt,
|
|||
evt->gpt_base + TIMER_CTRL_REG(timer));
|
||||
}
|
||||
|
||||
static void mtk_clkevt_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *clk)
|
||||
static int mtk_clkevt_shutdown(struct clock_event_device *clk)
|
||||
{
|
||||
mtk_clkevt_time_stop(to_mtk_clk(clk), GPT_CLK_EVT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_clkevt_set_periodic(struct clock_event_device *clk)
|
||||
{
|
||||
struct mtk_clock_event_device *evt = to_mtk_clk(clk);
|
||||
|
||||
mtk_clkevt_time_stop(evt, GPT_CLK_EVT);
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
mtk_clkevt_time_setup(evt, evt->ticks_per_jiffy, GPT_CLK_EVT);
|
||||
mtk_clkevt_time_start(evt, true, GPT_CLK_EVT);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
/* Timer is enabled in set_next_event */
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
default:
|
||||
/* No more interrupts will occur as source is disabled */
|
||||
break;
|
||||
}
|
||||
mtk_clkevt_time_setup(evt, evt->ticks_per_jiffy, GPT_CLK_EVT);
|
||||
mtk_clkevt_time_start(evt, true, GPT_CLK_EVT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_clkevt_next_event(unsigned long event,
|
||||
|
@ -196,7 +189,10 @@ static void __init mtk_timer_init(struct device_node *node)
|
|||
evt->dev.name = "mtk_tick";
|
||||
evt->dev.rating = 300;
|
||||
evt->dev.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
|
||||
evt->dev.set_mode = mtk_clkevt_mode;
|
||||
evt->dev.set_state_shutdown = mtk_clkevt_shutdown;
|
||||
evt->dev.set_state_periodic = mtk_clkevt_set_periodic;
|
||||
evt->dev.set_state_oneshot = mtk_clkevt_shutdown;
|
||||
evt->dev.tick_resume = mtk_clkevt_shutdown;
|
||||
evt->dev.set_next_event = mtk_clkevt_next_event;
|
||||
evt->dev.cpumask = cpu_possible_mask;
|
||||
|
||||
|
|
|
@ -77,7 +77,6 @@
|
|||
#define BV_TIMROTv2_TIMCTRLn_SELECT__TICK_ALWAYS 0xf
|
||||
|
||||
static struct clock_event_device mxs_clockevent_device;
|
||||
static enum clock_event_mode mxs_clockevent_mode = CLOCK_EVT_MODE_UNUSED;
|
||||
|
||||
static void __iomem *mxs_timrot_base;
|
||||
static u32 timrot_major_version;
|
||||
|
@ -141,64 +140,49 @@ static struct irqaction mxs_timer_irq = {
|
|||
.handler = mxs_timer_interrupt,
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char *clock_event_mode_label[] const = {
|
||||
[CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC",
|
||||
[CLOCK_EVT_MODE_ONESHOT] = "CLOCK_EVT_MODE_ONESHOT",
|
||||
[CLOCK_EVT_MODE_SHUTDOWN] = "CLOCK_EVT_MODE_SHUTDOWN",
|
||||
[CLOCK_EVT_MODE_UNUSED] = "CLOCK_EVT_MODE_UNUSED"
|
||||
};
|
||||
#endif /* DEBUG */
|
||||
|
||||
static void mxs_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static void mxs_irq_clear(char *state)
|
||||
{
|
||||
/* Disable interrupt in timer module */
|
||||
timrot_irq_disable();
|
||||
|
||||
if (mode != mxs_clockevent_mode) {
|
||||
/* Set event time into the furthest future */
|
||||
if (timrot_is_v1())
|
||||
__raw_writel(0xffff,
|
||||
mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1));
|
||||
else
|
||||
__raw_writel(0xffffffff,
|
||||
mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(1));
|
||||
/* Set event time into the furthest future */
|
||||
if (timrot_is_v1())
|
||||
__raw_writel(0xffff, mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1));
|
||||
else
|
||||
__raw_writel(0xffffffff,
|
||||
mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(1));
|
||||
|
||||
/* Clear pending interrupt */
|
||||
timrot_irq_acknowledge();
|
||||
}
|
||||
/* Clear pending interrupt */
|
||||
timrot_irq_acknowledge();
|
||||
|
||||
#ifdef DEBUG
|
||||
pr_info("%s: changing mode from %s to %s\n", __func__,
|
||||
clock_event_mode_label[mxs_clockevent_mode],
|
||||
clock_event_mode_label[mode]);
|
||||
pr_info("%s: changing mode to %s\n", __func__, state)
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
|
||||
/* Remember timer mode */
|
||||
mxs_clockevent_mode = mode;
|
||||
static int mxs_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
mxs_irq_clear("shutdown");
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
pr_err("%s: Periodic mode is not implemented\n", __func__);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
timrot_irq_enable();
|
||||
break;
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
/* Left event sources disabled, no more interrupts appear */
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxs_set_oneshot(struct clock_event_device *evt)
|
||||
{
|
||||
if (clockevent_state_oneshot(evt))
|
||||
mxs_irq_clear("oneshot");
|
||||
timrot_irq_enable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clock_event_device mxs_clockevent_device = {
|
||||
.name = "mxs_timrot",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_mode = mxs_set_mode,
|
||||
.set_next_event = timrotv2_set_next_event,
|
||||
.rating = 200,
|
||||
.name = "mxs_timrot",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_state_shutdown = mxs_shutdown,
|
||||
.set_state_oneshot = mxs_set_oneshot,
|
||||
.tick_resume = mxs_shutdown,
|
||||
.set_next_event = timrotv2_set_next_event,
|
||||
.rating = 200,
|
||||
};
|
||||
|
||||
static int __init mxs_clockevent_init(struct clk *timer_clk)
|
||||
|
|
|
@ -119,28 +119,27 @@ static void nmdk_clkevt_reset(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void nmdk_clkevt_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *dev)
|
||||
static int nmdk_clkevt_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
clkevt_periodic = true;
|
||||
nmdk_clkevt_reset();
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
clkevt_periodic = false;
|
||||
break;
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
writel(0, mtu_base + MTU_IMSC);
|
||||
/* disable timer */
|
||||
writel(0, mtu_base + MTU_CR(1));
|
||||
/* load some high default value */
|
||||
writel(0xffffffff, mtu_base + MTU_LR(1));
|
||||
break;
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
break;
|
||||
}
|
||||
writel(0, mtu_base + MTU_IMSC);
|
||||
/* disable timer */
|
||||
writel(0, mtu_base + MTU_CR(1));
|
||||
/* load some high default value */
|
||||
writel(0xffffffff, mtu_base + MTU_LR(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nmdk_clkevt_set_oneshot(struct clock_event_device *evt)
|
||||
{
|
||||
clkevt_periodic = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nmdk_clkevt_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
clkevt_periodic = true;
|
||||
nmdk_clkevt_reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nmdk_clksrc_reset(void)
|
||||
|
@ -163,13 +162,16 @@ static void nmdk_clkevt_resume(struct clock_event_device *cedev)
|
|||
}
|
||||
|
||||
static struct clock_event_device nmdk_clkevt = {
|
||||
.name = "mtu_1",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC |
|
||||
CLOCK_EVT_FEAT_DYNIRQ,
|
||||
.rating = 200,
|
||||
.set_mode = nmdk_clkevt_mode,
|
||||
.set_next_event = nmdk_clkevt_next,
|
||||
.resume = nmdk_clkevt_resume,
|
||||
.name = "mtu_1",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT |
|
||||
CLOCK_EVT_FEAT_PERIODIC |
|
||||
CLOCK_EVT_FEAT_DYNIRQ,
|
||||
.rating = 200,
|
||||
.set_state_shutdown = nmdk_clkevt_shutdown,
|
||||
.set_state_periodic = nmdk_clkevt_set_periodic,
|
||||
.set_state_oneshot = nmdk_clkevt_set_oneshot,
|
||||
.set_next_event = nmdk_clkevt_next,
|
||||
.resume = nmdk_clkevt_resume,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -88,26 +88,12 @@ pxa_osmr0_set_next_event(unsigned long delta, struct clock_event_device *dev)
|
|||
return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0;
|
||||
}
|
||||
|
||||
static void
|
||||
pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev)
|
||||
static int pxa_osmr0_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
timer_writel(timer_readl(OIER) & ~OIER_E0, OIER);
|
||||
timer_writel(OSSR_M0, OSSR);
|
||||
break;
|
||||
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
/* initializing, released, or preparing for suspend */
|
||||
timer_writel(timer_readl(OIER) & ~OIER_E0, OIER);
|
||||
timer_writel(OSSR_M0, OSSR);
|
||||
break;
|
||||
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
break;
|
||||
}
|
||||
/* initializing, released, or preparing for suspend */
|
||||
timer_writel(timer_readl(OIER) & ~OIER_E0, OIER);
|
||||
timer_writel(OSSR_M0, OSSR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
@ -147,13 +133,14 @@ static void pxa_timer_resume(struct clock_event_device *cedev)
|
|||
#endif
|
||||
|
||||
static struct clock_event_device ckevt_pxa_osmr0 = {
|
||||
.name = "osmr0",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT,
|
||||
.rating = 200,
|
||||
.set_next_event = pxa_osmr0_set_next_event,
|
||||
.set_mode = pxa_osmr0_set_mode,
|
||||
.suspend = pxa_timer_suspend,
|
||||
.resume = pxa_timer_resume,
|
||||
.name = "osmr0",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT,
|
||||
.rating = 200,
|
||||
.set_next_event = pxa_osmr0_set_next_event,
|
||||
.set_state_shutdown = pxa_osmr0_shutdown,
|
||||
.set_state_oneshot = pxa_osmr0_shutdown,
|
||||
.suspend = pxa_timer_suspend,
|
||||
.resume = pxa_timer_resume,
|
||||
};
|
||||
|
||||
static struct irqaction pxa_ost0_irq = {
|
||||
|
|
|
@ -47,7 +47,7 @@ static irqreturn_t msm_timer_interrupt(int irq, void *dev_id)
|
|||
{
|
||||
struct clock_event_device *evt = dev_id;
|
||||
/* Stop the timer tick */
|
||||
if (evt->mode == CLOCK_EVT_MODE_ONESHOT) {
|
||||
if (clockevent_state_oneshot(evt)) {
|
||||
u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE);
|
||||
ctrl &= ~TIMER_ENABLE_EN;
|
||||
writel_relaxed(ctrl, event_base + TIMER_ENABLE);
|
||||
|
@ -75,26 +75,14 @@ static int msm_timer_set_next_event(unsigned long cycles,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void msm_timer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static int msm_timer_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
u32 ctrl;
|
||||
|
||||
ctrl = readl_relaxed(event_base + TIMER_ENABLE);
|
||||
ctrl &= ~(TIMER_ENABLE_EN | TIMER_ENABLE_CLR_ON_MATCH_EN);
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
/* Timer is enabled in set_next_event */
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
break;
|
||||
}
|
||||
writel_relaxed(ctrl, event_base + TIMER_ENABLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clock_event_device __percpu *msm_evt;
|
||||
|
@ -126,7 +114,9 @@ static int msm_local_timer_setup(struct clock_event_device *evt)
|
|||
evt->name = "msm_timer";
|
||||
evt->features = CLOCK_EVT_FEAT_ONESHOT;
|
||||
evt->rating = 200;
|
||||
evt->set_mode = msm_timer_set_mode;
|
||||
evt->set_state_shutdown = msm_timer_shutdown;
|
||||
evt->set_state_oneshot = msm_timer_shutdown;
|
||||
evt->tick_resume = msm_timer_shutdown;
|
||||
evt->set_next_event = msm_timer_set_next_event;
|
||||
evt->cpumask = cpumask_of(cpu);
|
||||
|
||||
|
@ -147,7 +137,7 @@ static int msm_local_timer_setup(struct clock_event_device *evt)
|
|||
|
||||
static void msm_local_timer_stop(struct clock_event_device *evt)
|
||||
{
|
||||
evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
|
||||
evt->set_state_shutdown(evt);
|
||||
disable_percpu_irq(evt->irq);
|
||||
}
|
||||
|
||||
|
|
|
@ -82,23 +82,18 @@ static inline int rk_timer_set_next_event(unsigned long cycles,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline void rk_timer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *ce)
|
||||
static int rk_timer_shutdown(struct clock_event_device *ce)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
rk_timer_disable(ce);
|
||||
rk_timer_update_counter(rk_timer(ce)->freq / HZ - 1, ce);
|
||||
rk_timer_enable(ce, TIMER_MODE_FREE_RUNNING);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
rk_timer_disable(ce);
|
||||
break;
|
||||
}
|
||||
rk_timer_disable(ce);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk_timer_set_periodic(struct clock_event_device *ce)
|
||||
{
|
||||
rk_timer_disable(ce);
|
||||
rk_timer_update_counter(rk_timer(ce)->freq / HZ - 1, ce);
|
||||
rk_timer_enable(ce, TIMER_MODE_FREE_RUNNING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t rk_timer_interrupt(int irq, void *dev_id)
|
||||
|
@ -107,7 +102,7 @@ static irqreturn_t rk_timer_interrupt(int irq, void *dev_id)
|
|||
|
||||
rk_timer_interrupt_clear(ce);
|
||||
|
||||
if (ce->mode == CLOCK_EVT_MODE_ONESHOT)
|
||||
if (clockevent_state_oneshot(ce))
|
||||
rk_timer_disable(ce);
|
||||
|
||||
ce->event_handler(ce);
|
||||
|
@ -161,7 +156,8 @@ static void __init rk_timer_init(struct device_node *np)
|
|||
ce->name = TIMER_NAME;
|
||||
ce->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
|
||||
ce->set_next_event = rk_timer_set_next_event;
|
||||
ce->set_mode = rk_timer_set_mode;
|
||||
ce->set_state_shutdown = rk_timer_shutdown;
|
||||
ce->set_state_periodic = rk_timer_set_periodic;
|
||||
ce->irq = irq;
|
||||
ce->cpumask = cpumask_of(0);
|
||||
ce->rating = 250;
|
||||
|
|
|
@ -207,25 +207,18 @@ static int samsung_set_next_event(unsigned long cycles,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void samsung_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static int samsung_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
samsung_time_stop(pwm.event_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
samsung_time_setup(pwm.event_id, pwm.clock_count_per_tick - 1);
|
||||
samsung_time_start(pwm.event_id, true);
|
||||
break;
|
||||
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
break;
|
||||
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
break;
|
||||
}
|
||||
static int samsung_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
samsung_time_stop(pwm.event_id);
|
||||
samsung_time_setup(pwm.event_id, pwm.clock_count_per_tick - 1);
|
||||
samsung_time_start(pwm.event_id, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void samsung_clockevent_resume(struct clock_event_device *cev)
|
||||
|
@ -240,12 +233,16 @@ static void samsung_clockevent_resume(struct clock_event_device *cev)
|
|||
}
|
||||
|
||||
static struct clock_event_device time_event_device = {
|
||||
.name = "samsung_event_timer",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
||||
.rating = 200,
|
||||
.set_next_event = samsung_set_next_event,
|
||||
.set_mode = samsung_set_mode,
|
||||
.resume = samsung_clockevent_resume,
|
||||
.name = "samsung_event_timer",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC |
|
||||
CLOCK_EVT_FEAT_ONESHOT,
|
||||
.rating = 200,
|
||||
.set_next_event = samsung_set_next_event,
|
||||
.set_state_shutdown = samsung_shutdown,
|
||||
.set_state_periodic = samsung_set_periodic,
|
||||
.set_state_oneshot = samsung_shutdown,
|
||||
.tick_resume = samsung_shutdown,
|
||||
.resume = samsung_clockevent_resume,
|
||||
};
|
||||
|
||||
static irqreturn_t samsung_clock_event_isr(int irq, void *dev_id)
|
||||
|
|
|
@ -538,7 +538,7 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
|
|||
|
||||
if (ch->flags & FLAG_CLOCKEVENT) {
|
||||
if (!(ch->flags & FLAG_SKIPEVENT)) {
|
||||
if (ch->ced.mode == CLOCK_EVT_MODE_ONESHOT) {
|
||||
if (clockevent_state_oneshot(&ch->ced)) {
|
||||
ch->next_match_value = ch->max_match_value;
|
||||
ch->flags |= FLAG_REPROGRAM;
|
||||
}
|
||||
|
@ -554,7 +554,7 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
|
|||
sh_cmt_clock_event_program_verify(ch, 1);
|
||||
|
||||
if (ch->flags & FLAG_CLOCKEVENT)
|
||||
if ((ch->ced.mode == CLOCK_EVT_MODE_SHUTDOWN)
|
||||
if ((clockevent_state_shutdown(&ch->ced))
|
||||
|| (ch->match_value == ch->next_match_value))
|
||||
ch->flags &= ~FLAG_REPROGRAM;
|
||||
}
|
||||
|
@ -726,39 +726,37 @@ static void sh_cmt_clock_event_start(struct sh_cmt_channel *ch, int periodic)
|
|||
sh_cmt_set_next(ch, ch->max_match_value);
|
||||
}
|
||||
|
||||
static void sh_cmt_clock_event_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *ced)
|
||||
static int sh_cmt_clock_event_shutdown(struct clock_event_device *ced)
|
||||
{
|
||||
struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
|
||||
|
||||
sh_cmt_stop(ch, FLAG_CLOCKEVENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sh_cmt_clock_event_set_state(struct clock_event_device *ced,
|
||||
int periodic)
|
||||
{
|
||||
struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
|
||||
|
||||
/* deal with old setting first */
|
||||
switch (ced->mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
if (clockevent_state_oneshot(ced) || clockevent_state_periodic(ced))
|
||||
sh_cmt_stop(ch, FLAG_CLOCKEVENT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
dev_info(&ch->cmt->pdev->dev,
|
||||
"ch%u: used for periodic clock events\n", ch->index);
|
||||
sh_cmt_clock_event_start(ch, 1);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
dev_info(&ch->cmt->pdev->dev,
|
||||
"ch%u: used for oneshot clock events\n", ch->index);
|
||||
sh_cmt_clock_event_start(ch, 0);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
sh_cmt_stop(ch, FLAG_CLOCKEVENT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
dev_info(&ch->cmt->pdev->dev, "ch%u: used for %s clock events\n",
|
||||
ch->index, periodic ? "periodic" : "oneshot");
|
||||
sh_cmt_clock_event_start(ch, periodic);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sh_cmt_clock_event_set_oneshot(struct clock_event_device *ced)
|
||||
{
|
||||
return sh_cmt_clock_event_set_state(ced, 0);
|
||||
}
|
||||
|
||||
static int sh_cmt_clock_event_set_periodic(struct clock_event_device *ced)
|
||||
{
|
||||
return sh_cmt_clock_event_set_state(ced, 1);
|
||||
}
|
||||
|
||||
static int sh_cmt_clock_event_next(unsigned long delta,
|
||||
|
@ -766,7 +764,7 @@ static int sh_cmt_clock_event_next(unsigned long delta,
|
|||
{
|
||||
struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
|
||||
|
||||
BUG_ON(ced->mode != CLOCK_EVT_MODE_ONESHOT);
|
||||
BUG_ON(!clockevent_state_oneshot(ced));
|
||||
if (likely(ch->flags & FLAG_IRQCONTEXT))
|
||||
ch->next_match_value = delta - 1;
|
||||
else
|
||||
|
@ -820,7 +818,9 @@ static int sh_cmt_register_clockevent(struct sh_cmt_channel *ch,
|
|||
ced->rating = 125;
|
||||
ced->cpumask = cpu_possible_mask;
|
||||
ced->set_next_event = sh_cmt_clock_event_next;
|
||||
ced->set_mode = sh_cmt_clock_event_mode;
|
||||
ced->set_state_shutdown = sh_cmt_clock_event_shutdown;
|
||||
ced->set_state_periodic = sh_cmt_clock_event_set_periodic;
|
||||
ced->set_state_oneshot = sh_cmt_clock_event_set_oneshot;
|
||||
ced->suspend = sh_cmt_clock_event_suspend;
|
||||
ced->resume = sh_cmt_clock_event_resume;
|
||||
|
||||
|
@ -935,9 +935,6 @@ static int sh_cmt_map_memory(struct sh_cmt_device *cmt)
|
|||
static const struct platform_device_id sh_cmt_id_table[] = {
|
||||
{ "sh-cmt-16", (kernel_ulong_t)&sh_cmt_info[SH_CMT_16BIT] },
|
||||
{ "sh-cmt-32", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT] },
|
||||
{ "sh-cmt-32-fast", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT_FAST] },
|
||||
{ "sh-cmt-48", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT] },
|
||||
{ "sh-cmt-48-gen2", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT_GEN2] },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, sh_cmt_id_table);
|
||||
|
|
|
@ -276,36 +276,25 @@ static struct sh_mtu2_channel *ced_to_sh_mtu2(struct clock_event_device *ced)
|
|||
return container_of(ced, struct sh_mtu2_channel, ced);
|
||||
}
|
||||
|
||||
static void sh_mtu2_clock_event_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *ced)
|
||||
static int sh_mtu2_clock_event_shutdown(struct clock_event_device *ced)
|
||||
{
|
||||
struct sh_mtu2_channel *ch = ced_to_sh_mtu2(ced);
|
||||
int disabled = 0;
|
||||
|
||||
/* deal with old setting first */
|
||||
switch (ced->mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
sh_mtu2_disable(ch);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sh_mtu2_clock_event_set_periodic(struct clock_event_device *ced)
|
||||
{
|
||||
struct sh_mtu2_channel *ch = ced_to_sh_mtu2(ced);
|
||||
|
||||
if (clockevent_state_periodic(ced))
|
||||
sh_mtu2_disable(ch);
|
||||
disabled = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
dev_info(&ch->mtu->pdev->dev,
|
||||
"ch%u: used for periodic clock events\n", ch->index);
|
||||
sh_mtu2_enable(ch);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
if (!disabled)
|
||||
sh_mtu2_disable(ch);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
dev_info(&ch->mtu->pdev->dev, "ch%u: used for periodic clock events\n",
|
||||
ch->index);
|
||||
sh_mtu2_enable(ch);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sh_mtu2_clock_event_suspend(struct clock_event_device *ced)
|
||||
|
@ -327,7 +316,8 @@ static void sh_mtu2_register_clockevent(struct sh_mtu2_channel *ch,
|
|||
ced->features = CLOCK_EVT_FEAT_PERIODIC;
|
||||
ced->rating = 200;
|
||||
ced->cpumask = cpu_possible_mask;
|
||||
ced->set_mode = sh_mtu2_clock_event_mode;
|
||||
ced->set_state_shutdown = sh_mtu2_clock_event_shutdown;
|
||||
ced->set_state_periodic = sh_mtu2_clock_event_set_periodic;
|
||||
ced->suspend = sh_mtu2_clock_event_suspend;
|
||||
ced->resume = sh_mtu2_clock_event_resume;
|
||||
|
||||
|
|
|
@ -240,7 +240,7 @@ static irqreturn_t sh_tmu_interrupt(int irq, void *dev_id)
|
|||
struct sh_tmu_channel *ch = dev_id;
|
||||
|
||||
/* disable or acknowledge interrupt */
|
||||
if (ch->ced.mode == CLOCK_EVT_MODE_ONESHOT)
|
||||
if (clockevent_state_oneshot(&ch->ced))
|
||||
sh_tmu_write(ch, TCR, TCR_TPSC_CLK4);
|
||||
else
|
||||
sh_tmu_write(ch, TCR, TCR_UNIE | TCR_TPSC_CLK4);
|
||||
|
@ -358,42 +358,38 @@ static void sh_tmu_clock_event_start(struct sh_tmu_channel *ch, int periodic)
|
|||
}
|
||||
}
|
||||
|
||||
static void sh_tmu_clock_event_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *ced)
|
||||
static int sh_tmu_clock_event_shutdown(struct clock_event_device *ced)
|
||||
{
|
||||
struct sh_tmu_channel *ch = ced_to_sh_tmu(ced);
|
||||
|
||||
if (clockevent_state_oneshot(ced) || clockevent_state_periodic(ced))
|
||||
sh_tmu_disable(ch);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sh_tmu_clock_event_set_state(struct clock_event_device *ced,
|
||||
int periodic)
|
||||
{
|
||||
struct sh_tmu_channel *ch = ced_to_sh_tmu(ced);
|
||||
int disabled = 0;
|
||||
|
||||
/* deal with old setting first */
|
||||
switch (ced->mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
if (clockevent_state_oneshot(ced) || clockevent_state_periodic(ced))
|
||||
sh_tmu_disable(ch);
|
||||
disabled = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
dev_info(&ch->tmu->pdev->dev,
|
||||
"ch%u: used for periodic clock events\n", ch->index);
|
||||
sh_tmu_clock_event_start(ch, 1);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
dev_info(&ch->tmu->pdev->dev,
|
||||
"ch%u: used for oneshot clock events\n", ch->index);
|
||||
sh_tmu_clock_event_start(ch, 0);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
if (!disabled)
|
||||
sh_tmu_disable(ch);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
dev_info(&ch->tmu->pdev->dev, "ch%u: used for %s clock events\n",
|
||||
ch->index, periodic ? "periodic" : "oneshot");
|
||||
sh_tmu_clock_event_start(ch, periodic);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sh_tmu_clock_event_set_oneshot(struct clock_event_device *ced)
|
||||
{
|
||||
return sh_tmu_clock_event_set_state(ced, 0);
|
||||
}
|
||||
|
||||
static int sh_tmu_clock_event_set_periodic(struct clock_event_device *ced)
|
||||
{
|
||||
return sh_tmu_clock_event_set_state(ced, 1);
|
||||
}
|
||||
|
||||
static int sh_tmu_clock_event_next(unsigned long delta,
|
||||
|
@ -401,7 +397,7 @@ static int sh_tmu_clock_event_next(unsigned long delta,
|
|||
{
|
||||
struct sh_tmu_channel *ch = ced_to_sh_tmu(ced);
|
||||
|
||||
BUG_ON(ced->mode != CLOCK_EVT_MODE_ONESHOT);
|
||||
BUG_ON(!clockevent_state_oneshot(ced));
|
||||
|
||||
/* program new delta value */
|
||||
sh_tmu_set_next(ch, delta, 0);
|
||||
|
@ -430,7 +426,9 @@ static void sh_tmu_register_clockevent(struct sh_tmu_channel *ch,
|
|||
ced->rating = 200;
|
||||
ced->cpumask = cpu_possible_mask;
|
||||
ced->set_next_event = sh_tmu_clock_event_next;
|
||||
ced->set_mode = sh_tmu_clock_event_mode;
|
||||
ced->set_state_shutdown = sh_tmu_clock_event_shutdown;
|
||||
ced->set_state_periodic = sh_tmu_clock_event_set_periodic;
|
||||
ced->set_state_oneshot = sh_tmu_clock_event_set_oneshot;
|
||||
ced->suspend = sh_tmu_clock_event_suspend;
|
||||
ced->resume = sh_tmu_clock_event_resume;
|
||||
|
||||
|
|
|
@ -81,25 +81,25 @@ static void sun4i_clkevt_time_start(u8 timer, bool periodic)
|
|||
timer_base + TIMER_CTL_REG(timer));
|
||||
}
|
||||
|
||||
static void sun4i_clkevt_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *clk)
|
||||
static int sun4i_clkevt_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
sun4i_clkevt_time_stop(0);
|
||||
sun4i_clkevt_time_setup(0, ticks_per_jiffy);
|
||||
sun4i_clkevt_time_start(0, true);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
sun4i_clkevt_time_stop(0);
|
||||
sun4i_clkevt_time_start(0, false);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
default:
|
||||
sun4i_clkevt_time_stop(0);
|
||||
break;
|
||||
}
|
||||
sun4i_clkevt_time_stop(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sun4i_clkevt_set_oneshot(struct clock_event_device *evt)
|
||||
{
|
||||
sun4i_clkevt_time_stop(0);
|
||||
sun4i_clkevt_time_start(0, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sun4i_clkevt_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
sun4i_clkevt_time_stop(0);
|
||||
sun4i_clkevt_time_setup(0, ticks_per_jiffy);
|
||||
sun4i_clkevt_time_start(0, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sun4i_clkevt_next_event(unsigned long evt,
|
||||
|
@ -116,7 +116,10 @@ static struct clock_event_device sun4i_clockevent = {
|
|||
.name = "sun4i_tick",
|
||||
.rating = 350,
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_mode = sun4i_clkevt_mode,
|
||||
.set_state_shutdown = sun4i_clkevt_shutdown,
|
||||
.set_state_periodic = sun4i_clkevt_set_periodic,
|
||||
.set_state_oneshot = sun4i_clkevt_set_oneshot,
|
||||
.tick_resume = sun4i_clkevt_shutdown,
|
||||
.set_next_event = sun4i_clkevt_next_event,
|
||||
};
|
||||
|
||||
|
|
|
@ -91,55 +91,62 @@ static struct tc_clkevt_device *to_tc_clkevt(struct clock_event_device *clkevt)
|
|||
*/
|
||||
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);
|
||||
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(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR));
|
||||
clk_disable(tcd->clk);
|
||||
}
|
||||
__raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR));
|
||||
__raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR));
|
||||
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
|
||||
* 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 */
|
||||
__raw_writel(timer_clock
|
||||
| ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO,
|
||||
regs + ATMEL_TC_REG(2, CMR));
|
||||
__raw_writel((32768 + HZ/2) / HZ, tcaddr + ATMEL_TC_REG(2, RC));
|
||||
/* slow clock, count up to RC, then irq and restart */
|
||||
__raw_writel(timer_clock | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO,
|
||||
regs + ATMEL_TC_REG(2, CMR));
|
||||
__raw_writel((32768 + HZ / 2) / HZ, tcaddr + ATMEL_TC_REG(2, RC));
|
||||
|
||||
/* Enable clock and interrupts on RC compare */
|
||||
__raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
|
||||
/* Enable clock and interrupts on RC compare */
|
||||
__raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
|
||||
|
||||
/* go go gadget! */
|
||||
__raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG,
|
||||
regs + ATMEL_TC_REG(2, CCR));
|
||||
break;
|
||||
|
||||
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;
|
||||
}
|
||||
/* go go gadget! */
|
||||
__raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG, regs +
|
||||
ATMEL_TC_REG(2, CCR));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tc_next_event(unsigned long delta, struct clock_event_device *d)
|
||||
|
@ -154,13 +161,15 @@ static int tc_next_event(unsigned long delta, struct clock_event_device *d)
|
|||
|
||||
static struct tc_clkevt_device clkevt = {
|
||||
.clkevt = {
|
||||
.name = "tc_clkevt",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC
|
||||
| CLOCK_EVT_FEAT_ONESHOT,
|
||||
.name = "tc_clkevt",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC |
|
||||
CLOCK_EVT_FEAT_ONESHOT,
|
||||
/* Should be lower than at91rm9200's system timer */
|
||||
.rating = 125,
|
||||
.set_next_event = tc_next_event,
|
||||
.set_mode = tc_mode,
|
||||
.rating = 125,
|
||||
.set_next_event = tc_next_event,
|
||||
.set_state_shutdown = tc_shutdown,
|
||||
.set_state_periodic = tc_set_periodic,
|
||||
.set_state_oneshot = tc_set_oneshot,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -72,33 +72,36 @@ static int tegra_timer_set_next_event(unsigned long cycles,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void tegra_timer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static inline void timer_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
timer_writel(0, TIMER3_BASE + TIMER_PTV);
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
reg = 0xC0000000 | ((1000000/HZ)-1);
|
||||
timer_writel(reg, TIMER3_BASE + TIMER_PTV);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
break;
|
||||
}
|
||||
static int tegra_timer_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
timer_shutdown(evt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_timer_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
u32 reg = 0xC0000000 | ((1000000 / HZ) - 1);
|
||||
|
||||
timer_shutdown(evt);
|
||||
timer_writel(reg, TIMER3_BASE + TIMER_PTV);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clock_event_device tegra_clockevent = {
|
||||
.name = "timer0",
|
||||
.rating = 300,
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
|
||||
.set_next_event = tegra_timer_set_next_event,
|
||||
.set_mode = tegra_timer_set_mode,
|
||||
.name = "timer0",
|
||||
.rating = 300,
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT |
|
||||
CLOCK_EVT_FEAT_PERIODIC,
|
||||
.set_next_event = tegra_timer_set_next_event,
|
||||
.set_state_shutdown = tegra_timer_shutdown,
|
||||
.set_state_periodic = tegra_timer_set_periodic,
|
||||
.set_state_oneshot = tegra_timer_shutdown,
|
||||
.tick_resume = tegra_timer_shutdown,
|
||||
};
|
||||
|
||||
static u64 notrace tegra_read_sched_clock(void)
|
||||
|
|
|
@ -121,33 +121,33 @@ armada_370_xp_clkevt_next_event(unsigned long delta,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
armada_370_xp_clkevt_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *dev)
|
||||
static int armada_370_xp_clkevt_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
if (mode == CLOCK_EVT_MODE_PERIODIC) {
|
||||
/*
|
||||
* Disable timer.
|
||||
*/
|
||||
local_timer_ctrl_clrset(TIMER0_EN, 0);
|
||||
|
||||
/*
|
||||
* Setup timer to fire at 1/HZ intervals.
|
||||
*/
|
||||
writel(ticks_per_jiffy - 1, local_base + TIMER0_RELOAD_OFF);
|
||||
writel(ticks_per_jiffy - 1, local_base + TIMER0_VAL_OFF);
|
||||
/*
|
||||
* ACK pending timer interrupt.
|
||||
*/
|
||||
writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable timer.
|
||||
*/
|
||||
local_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | enable_mask);
|
||||
} else {
|
||||
/*
|
||||
* Disable timer.
|
||||
*/
|
||||
local_timer_ctrl_clrset(TIMER0_EN, 0);
|
||||
static int armada_370_xp_clkevt_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
/*
|
||||
* Setup timer to fire at 1/HZ intervals.
|
||||
*/
|
||||
writel(ticks_per_jiffy - 1, local_base + TIMER0_RELOAD_OFF);
|
||||
writel(ticks_per_jiffy - 1, local_base + TIMER0_VAL_OFF);
|
||||
|
||||
/*
|
||||
* ACK pending timer interrupt.
|
||||
*/
|
||||
writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS);
|
||||
}
|
||||
/*
|
||||
* Enable timer.
|
||||
*/
|
||||
local_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | enable_mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int armada_370_xp_clkevt_irq;
|
||||
|
@ -185,7 +185,10 @@ static int armada_370_xp_timer_setup(struct clock_event_device *evt)
|
|||
evt->shift = 32,
|
||||
evt->rating = 300,
|
||||
evt->set_next_event = armada_370_xp_clkevt_next_event,
|
||||
evt->set_mode = armada_370_xp_clkevt_mode,
|
||||
evt->set_state_shutdown = armada_370_xp_clkevt_shutdown;
|
||||
evt->set_state_periodic = armada_370_xp_clkevt_set_periodic;
|
||||
evt->set_state_oneshot = armada_370_xp_clkevt_shutdown;
|
||||
evt->tick_resume = armada_370_xp_clkevt_shutdown;
|
||||
evt->irq = armada_370_xp_clkevt_irq;
|
||||
evt->cpumask = cpumask_of(cpu);
|
||||
|
||||
|
@ -197,7 +200,7 @@ static int armada_370_xp_timer_setup(struct clock_event_device *evt)
|
|||
|
||||
static void armada_370_xp_timer_stop(struct clock_event_device *evt)
|
||||
{
|
||||
evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
|
||||
evt->set_state_shutdown(evt);
|
||||
disable_percpu_irq(evt->irq);
|
||||
}
|
||||
|
||||
|
|
|
@ -48,40 +48,42 @@ struct efm32_clock_event_ddata {
|
|||
unsigned periodic_top;
|
||||
};
|
||||
|
||||
static void efm32_clock_event_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evtdev)
|
||||
static int efm32_clock_event_shutdown(struct clock_event_device *evtdev)
|
||||
{
|
||||
struct efm32_clock_event_ddata *ddata =
|
||||
container_of(evtdev, struct efm32_clock_event_ddata, evtdev);
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD);
|
||||
writel_relaxed(ddata->periodic_top, ddata->base + TIMERn_TOP);
|
||||
writel_relaxed(TIMERn_CTRL_PRESC_1024 |
|
||||
TIMERn_CTRL_CLKSEL_PRESCHFPERCLK |
|
||||
TIMERn_CTRL_MODE_DOWN,
|
||||
ddata->base + TIMERn_CTRL);
|
||||
writel_relaxed(TIMERn_CMD_START, ddata->base + TIMERn_CMD);
|
||||
break;
|
||||
writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD);
|
||||
writel_relaxed(TIMERn_CTRL_PRESC_1024 |
|
||||
TIMERn_CTRL_CLKSEL_PRESCHFPERCLK |
|
||||
TIMERn_CTRL_OSMEN |
|
||||
TIMERn_CTRL_MODE_DOWN,
|
||||
ddata->base + TIMERn_CTRL);
|
||||
break;
|
||||
static int efm32_clock_event_set_oneshot(struct clock_event_device *evtdev)
|
||||
{
|
||||
struct efm32_clock_event_ddata *ddata =
|
||||
container_of(evtdev, struct efm32_clock_event_ddata, evtdev);
|
||||
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD);
|
||||
break;
|
||||
writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD);
|
||||
writel_relaxed(TIMERn_CTRL_PRESC_1024 |
|
||||
TIMERn_CTRL_CLKSEL_PRESCHFPERCLK |
|
||||
TIMERn_CTRL_OSMEN |
|
||||
TIMERn_CTRL_MODE_DOWN,
|
||||
ddata->base + TIMERn_CTRL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
break;
|
||||
}
|
||||
static int efm32_clock_event_set_periodic(struct clock_event_device *evtdev)
|
||||
{
|
||||
struct efm32_clock_event_ddata *ddata =
|
||||
container_of(evtdev, struct efm32_clock_event_ddata, evtdev);
|
||||
|
||||
writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD);
|
||||
writel_relaxed(ddata->periodic_top, ddata->base + TIMERn_TOP);
|
||||
writel_relaxed(TIMERn_CTRL_PRESC_1024 |
|
||||
TIMERn_CTRL_CLKSEL_PRESCHFPERCLK |
|
||||
TIMERn_CTRL_MODE_DOWN,
|
||||
ddata->base + TIMERn_CTRL);
|
||||
writel_relaxed(TIMERn_CMD_START, ddata->base + TIMERn_CMD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int efm32_clock_event_set_next_event(unsigned long evt,
|
||||
|
@ -112,7 +114,9 @@ static struct efm32_clock_event_ddata clock_event_ddata = {
|
|||
.evtdev = {
|
||||
.name = "efm32 clockevent",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
|
||||
.set_mode = efm32_clock_event_set_mode,
|
||||
.set_state_shutdown = efm32_clock_event_shutdown,
|
||||
.set_state_periodic = efm32_clock_event_set_periodic,
|
||||
.set_state_oneshot = efm32_clock_event_set_oneshot,
|
||||
.set_next_event = efm32_clock_event_set_next_event,
|
||||
.rating = 200,
|
||||
},
|
||||
|
|
|
@ -60,30 +60,36 @@ static int orion_clkevt_next_event(unsigned long delta,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void orion_clkevt_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *dev)
|
||||
static int orion_clkevt_shutdown(struct clock_event_device *dev)
|
||||
{
|
||||
if (mode == CLOCK_EVT_MODE_PERIODIC) {
|
||||
/* setup and enable periodic timer at 1/HZ intervals */
|
||||
writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD);
|
||||
writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL);
|
||||
atomic_io_modify(timer_base + TIMER_CTRL,
|
||||
TIMER1_RELOAD_EN | TIMER1_EN,
|
||||
TIMER1_RELOAD_EN | TIMER1_EN);
|
||||
} else {
|
||||
/* disable timer */
|
||||
atomic_io_modify(timer_base + TIMER_CTRL,
|
||||
TIMER1_RELOAD_EN | TIMER1_EN, 0);
|
||||
}
|
||||
/* disable timer */
|
||||
atomic_io_modify(timer_base + TIMER_CTRL,
|
||||
TIMER1_RELOAD_EN | TIMER1_EN, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int orion_clkevt_set_periodic(struct clock_event_device *dev)
|
||||
{
|
||||
/* setup and enable periodic timer at 1/HZ intervals */
|
||||
writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD);
|
||||
writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL);
|
||||
atomic_io_modify(timer_base + TIMER_CTRL,
|
||||
TIMER1_RELOAD_EN | TIMER1_EN,
|
||||
TIMER1_RELOAD_EN | TIMER1_EN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clock_event_device orion_clkevt = {
|
||||
.name = "orion_event",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
|
||||
.shift = 32,
|
||||
.rating = 300,
|
||||
.set_next_event = orion_clkevt_next_event,
|
||||
.set_mode = orion_clkevt_mode,
|
||||
.name = "orion_event",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT |
|
||||
CLOCK_EVT_FEAT_PERIODIC,
|
||||
.shift = 32,
|
||||
.rating = 300,
|
||||
.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_clkevt_irq_handler(int irq, void *dev_id)
|
||||
|
|
|
@ -76,7 +76,7 @@ static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id)
|
|||
/* clear timer interrupt */
|
||||
writel_relaxed(BIT(cpu), sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS);
|
||||
|
||||
if (ce->mode == CLOCK_EVT_MODE_ONESHOT)
|
||||
if (clockevent_state_oneshot(ce))
|
||||
sirfsoc_timer_count_disable(cpu);
|
||||
|
||||
ce->event_handler(ce);
|
||||
|
@ -117,18 +117,11 @@ static int sirfsoc_timer_set_next_event(unsigned long delta,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void sirfsoc_timer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *ce)
|
||||
/* Oneshot is enabled in set_next_event */
|
||||
static int sirfsoc_timer_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
/* enable in set_next_event */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
sirfsoc_timer_count_disable(smp_processor_id());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sirfsoc_clocksource_suspend(struct clocksource *cs)
|
||||
|
@ -193,7 +186,9 @@ static int sirfsoc_local_timer_setup(struct clock_event_device *ce)
|
|||
ce->name = "local_timer";
|
||||
ce->features = CLOCK_EVT_FEAT_ONESHOT;
|
||||
ce->rating = 200;
|
||||
ce->set_mode = sirfsoc_timer_set_mode;
|
||||
ce->set_state_shutdown = sirfsoc_timer_shutdown;
|
||||
ce->set_state_oneshot = sirfsoc_timer_shutdown;
|
||||
ce->tick_resume = sirfsoc_timer_shutdown;
|
||||
ce->set_next_event = sirfsoc_timer_set_next_event;
|
||||
clockevents_calc_mult_shift(ce, atlas7_timer_rate, 60);
|
||||
ce->max_delta_ns = clockevent_delta2ns(-2, ce);
|
||||
|
|
|
@ -90,33 +90,27 @@ static cycle_t read_pit_clk(struct clocksource *cs)
|
|||
return elapsed;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clockevent device: interrupts every 1/HZ (== pit_cycles * MCK/16)
|
||||
*/
|
||||
static void
|
||||
pit_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
|
||||
static int pit_clkevt_shutdown(struct clock_event_device *dev)
|
||||
{
|
||||
struct pit_data *data = clkevt_to_pit_data(dev);
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
/* update clocksource counter */
|
||||
data->cnt += data->cycle * PIT_PICNT(pit_read(data->base, AT91_PIT_PIVR));
|
||||
pit_write(data->base, AT91_PIT_MR,
|
||||
(data->cycle - 1) | AT91_PIT_PITEN | AT91_PIT_PITIEN);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
BUG();
|
||||
/* FALLTHROUGH */
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
/* disable irq, leaving the clocksource active */
|
||||
pit_write(data->base, AT91_PIT_MR,
|
||||
(data->cycle - 1) | AT91_PIT_PITEN);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
break;
|
||||
}
|
||||
/* disable irq, leaving the clocksource active */
|
||||
pit_write(data->base, AT91_PIT_MR, (data->cycle - 1) | AT91_PIT_PITEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clockevent device: interrupts every 1/HZ (== pit_cycles * MCK/16)
|
||||
*/
|
||||
static int pit_clkevt_set_periodic(struct clock_event_device *dev)
|
||||
{
|
||||
struct pit_data *data = clkevt_to_pit_data(dev);
|
||||
|
||||
/* update clocksource counter */
|
||||
data->cnt += data->cycle * PIT_PICNT(pit_read(data->base, AT91_PIT_PIVR));
|
||||
pit_write(data->base, AT91_PIT_MR,
|
||||
(data->cycle - 1) | AT91_PIT_PITEN | AT91_PIT_PITIEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void at91sam926x_pit_suspend(struct clock_event_device *cedev)
|
||||
|
@ -162,7 +156,7 @@ static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id)
|
|||
WARN_ON_ONCE(!irqs_disabled());
|
||||
|
||||
/* The PIT interrupt may be disabled, and is shared */
|
||||
if ((data->clkevt.mode == CLOCK_EVT_MODE_PERIODIC) &&
|
||||
if (clockevent_state_periodic(&data->clkevt) &&
|
||||
(pit_read(data->base, AT91_PIT_SR) & AT91_PIT_PITS)) {
|
||||
unsigned nr_ticks;
|
||||
|
||||
|
@ -208,8 +202,8 @@ static void __init at91sam926x_pit_common_init(struct pit_data *data)
|
|||
data->clksrc.mask = CLOCKSOURCE_MASK(bits);
|
||||
data->clksrc.name = "pit";
|
||||
data->clksrc.rating = 175;
|
||||
data->clksrc.read = read_pit_clk,
|
||||
data->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
data->clksrc.read = read_pit_clk;
|
||||
data->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS;
|
||||
clocksource_register_hz(&data->clksrc, pit_rate);
|
||||
|
||||
/* Set up irq handler */
|
||||
|
@ -227,7 +221,8 @@ static void __init at91sam926x_pit_common_init(struct pit_data *data)
|
|||
data->clkevt.rating = 100;
|
||||
data->clkevt.cpumask = cpumask_of(0);
|
||||
|
||||
data->clkevt.set_mode = pit_clkevt_mode;
|
||||
data->clkevt.set_state_shutdown = pit_clkevt_shutdown;
|
||||
data->clkevt.set_state_periodic = pit_clkevt_set_periodic;
|
||||
data->clkevt.resume = at91sam926x_pit_resume;
|
||||
data->clkevt.suspend = at91sam926x_pit_suspend;
|
||||
clockevents_register_device(&data->clkevt);
|
||||
|
|
|
@ -106,36 +106,47 @@ static struct clocksource clk32k = {
|
|||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
};
|
||||
|
||||
static void
|
||||
clkevt32k_mode(enum clock_event_mode mode, struct clock_event_device *dev)
|
||||
static void clkdev32k_disable_and_flush_irq(void)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
/* Disable and flush pending timer interrupts */
|
||||
regmap_write(regmap_st, AT91_ST_IDR, AT91_ST_PITS | AT91_ST_ALMS);
|
||||
regmap_read(regmap_st, AT91_ST_SR, &val);
|
||||
|
||||
last_crtr = read_CRTR();
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
/* PIT for periodic irqs; fixed rate of 1/HZ */
|
||||
irqmask = AT91_ST_PITS;
|
||||
regmap_write(regmap_st, AT91_ST_PIMR, RM9200_TIMER_LATCH);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
/* ALM for oneshot irqs, set by next_event()
|
||||
* before 32 seconds have passed
|
||||
*/
|
||||
irqmask = AT91_ST_ALMS;
|
||||
regmap_write(regmap_st, AT91_ST_RTAR, last_crtr);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
irqmask = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int clkevt32k_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
clkdev32k_disable_and_flush_irq();
|
||||
irqmask = 0;
|
||||
regmap_write(regmap_st, AT91_ST_IER, irqmask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clkevt32k_set_oneshot(struct clock_event_device *dev)
|
||||
{
|
||||
clkdev32k_disable_and_flush_irq();
|
||||
|
||||
/*
|
||||
* ALM for oneshot irqs, set by next_event()
|
||||
* before 32 seconds have passed.
|
||||
*/
|
||||
irqmask = AT91_ST_ALMS;
|
||||
regmap_write(regmap_st, AT91_ST_RTAR, last_crtr);
|
||||
regmap_write(regmap_st, AT91_ST_IER, irqmask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clkevt32k_set_periodic(struct clock_event_device *dev)
|
||||
{
|
||||
clkdev32k_disable_and_flush_irq();
|
||||
|
||||
/* PIT for periodic irqs; fixed rate of 1/HZ */
|
||||
irqmask = AT91_ST_PITS;
|
||||
regmap_write(regmap_st, AT91_ST_PIMR, RM9200_TIMER_LATCH);
|
||||
regmap_write(regmap_st, AT91_ST_IER, irqmask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -170,11 +181,15 @@ clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
|
|||
}
|
||||
|
||||
static struct clock_event_device clkevt = {
|
||||
.name = "at91_tick",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
||||
.rating = 150,
|
||||
.set_next_event = clkevt32k_next_event,
|
||||
.set_mode = clkevt32k_mode,
|
||||
.name = "at91_tick",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC |
|
||||
CLOCK_EVT_FEAT_ONESHOT,
|
||||
.rating = 150,
|
||||
.set_next_event = clkevt32k_next_event,
|
||||
.set_state_shutdown = clkevt32k_shutdown,
|
||||
.set_state_periodic = clkevt32k_set_periodic,
|
||||
.set_state_oneshot = clkevt32k_set_oneshot,
|
||||
.tick_resume = clkevt32k_shutdown,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -87,27 +87,27 @@ static inline void dc_timer_set_count(struct clock_event_device *ce,
|
|||
writel(count, dt->base + COUNT(dt->timer_id));
|
||||
}
|
||||
|
||||
static void digicolor_clkevt_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *ce)
|
||||
static int digicolor_clkevt_shutdown(struct clock_event_device *ce)
|
||||
{
|
||||
dc_timer_disable(ce);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int digicolor_clkevt_set_oneshot(struct clock_event_device *ce)
|
||||
{
|
||||
dc_timer_disable(ce);
|
||||
dc_timer_enable(ce, CONTROL_MODE_ONESHOT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int digicolor_clkevt_set_periodic(struct clock_event_device *ce)
|
||||
{
|
||||
struct digicolor_timer *dt = dc_timer(ce);
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
dc_timer_disable(ce);
|
||||
dc_timer_set_count(ce, dt->ticks_per_jiffy);
|
||||
dc_timer_enable(ce, CONTROL_MODE_PERIODIC);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
dc_timer_disable(ce);
|
||||
dc_timer_enable(ce, CONTROL_MODE_ONESHOT);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
default:
|
||||
dc_timer_disable(ce);
|
||||
break;
|
||||
}
|
||||
dc_timer_disable(ce);
|
||||
dc_timer_set_count(ce, dt->ticks_per_jiffy);
|
||||
dc_timer_enable(ce, CONTROL_MODE_PERIODIC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int digicolor_clkevt_next_event(unsigned long evt,
|
||||
|
@ -125,7 +125,10 @@ static struct digicolor_timer dc_timer_dev = {
|
|||
.name = "digicolor_tick",
|
||||
.rating = 340,
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_mode = digicolor_clkevt_mode,
|
||||
.set_state_shutdown = digicolor_clkevt_shutdown,
|
||||
.set_state_periodic = digicolor_clkevt_set_periodic,
|
||||
.set_state_oneshot = digicolor_clkevt_set_oneshot,
|
||||
.tick_resume = digicolor_clkevt_shutdown,
|
||||
.set_next_event = digicolor_clkevt_next_event,
|
||||
},
|
||||
.timer_id = TIMER_C,
|
||||
|
|
|
@ -83,7 +83,6 @@ struct imx_timer {
|
|||
struct clk *clk_ipg;
|
||||
const struct imx_gpt_data *gpt;
|
||||
struct clock_event_device ced;
|
||||
enum clock_event_mode cem;
|
||||
struct irqaction act;
|
||||
};
|
||||
|
||||
|
@ -212,18 +211,38 @@ static int v2_set_next_event(unsigned long evt,
|
|||
-ETIME : 0;
|
||||
}
|
||||
|
||||
static int mxc_shutdown(struct clock_event_device *ced)
|
||||
{
|
||||
struct imx_timer *imxtm = to_imx_timer(ced);
|
||||
unsigned long flags;
|
||||
u32 tcn;
|
||||
|
||||
/*
|
||||
* The timer interrupt generation is disabled at least
|
||||
* for enough time to call mxc_set_next_event()
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
|
||||
/* Disable interrupt in GPT module */
|
||||
imxtm->gpt->gpt_irq_disable(imxtm);
|
||||
|
||||
tcn = readl_relaxed(imxtm->base + imxtm->gpt->reg_tcn);
|
||||
/* Set event time into far-far future */
|
||||
writel_relaxed(tcn - 3, imxtm->base + imxtm->gpt->reg_tcmp);
|
||||
|
||||
/* Clear pending interrupt */
|
||||
imxtm->gpt->gpt_irq_acknowledge(imxtm);
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char *clock_event_mode_label[] = {
|
||||
[CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC",
|
||||
[CLOCK_EVT_MODE_ONESHOT] = "CLOCK_EVT_MODE_ONESHOT",
|
||||
[CLOCK_EVT_MODE_SHUTDOWN] = "CLOCK_EVT_MODE_SHUTDOWN",
|
||||
[CLOCK_EVT_MODE_UNUSED] = "CLOCK_EVT_MODE_UNUSED",
|
||||
[CLOCK_EVT_MODE_RESUME] = "CLOCK_EVT_MODE_RESUME",
|
||||
};
|
||||
printk(KERN_INFO "%s: changing mode\n", __func__);
|
||||
#endif /* DEBUG */
|
||||
|
||||
static void mxc_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *ced)
|
||||
local_irq_restore(flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxc_set_oneshot(struct clock_event_device *ced)
|
||||
{
|
||||
struct imx_timer *imxtm = to_imx_timer(ced);
|
||||
unsigned long flags;
|
||||
|
@ -237,7 +256,7 @@ static void mxc_set_mode(enum clock_event_mode mode,
|
|||
/* Disable interrupt in GPT module */
|
||||
imxtm->gpt->gpt_irq_disable(imxtm);
|
||||
|
||||
if (mode != imxtm->cem) {
|
||||
if (!clockevent_state_oneshot(ced)) {
|
||||
u32 tcn = readl_relaxed(imxtm->base + imxtm->gpt->reg_tcn);
|
||||
/* Set event time into far-far future */
|
||||
writel_relaxed(tcn - 3, imxtm->base + imxtm->gpt->reg_tcmp);
|
||||
|
@ -247,37 +266,19 @@ static void mxc_set_mode(enum clock_event_mode mode,
|
|||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printk(KERN_INFO "mxc_set_mode: changing mode from %s to %s\n",
|
||||
clock_event_mode_label[imxtm->cem],
|
||||
clock_event_mode_label[mode]);
|
||||
printk(KERN_INFO "%s: changing mode\n", __func__);
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* Remember timer mode */
|
||||
imxtm->cem = mode;
|
||||
local_irq_restore(flags);
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
printk(KERN_ERR"mxc_set_mode: Periodic mode is not "
|
||||
"supported for i.MX\n");
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
/*
|
||||
* Do not put overhead of interrupt enable/disable into
|
||||
* mxc_set_next_event(), the core has about 4 minutes
|
||||
* to call mxc_set_next_event() or shutdown clock after
|
||||
* mode switching
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
imxtm->gpt->gpt_irq_enable(imxtm);
|
||||
local_irq_restore(flags);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
/* Left event sources disabled, no more interrupts appear */
|
||||
break;
|
||||
}
|
||||
imxtm->gpt->gpt_irq_enable(imxtm);
|
||||
local_irq_restore(flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -303,11 +304,11 @@ static int __init mxc_clockevent_init(struct imx_timer *imxtm)
|
|||
struct clock_event_device *ced = &imxtm->ced;
|
||||
struct irqaction *act = &imxtm->act;
|
||||
|
||||
imxtm->cem = CLOCK_EVT_MODE_UNUSED;
|
||||
|
||||
ced->name = "mxc_timer1";
|
||||
ced->features = CLOCK_EVT_FEAT_ONESHOT;
|
||||
ced->set_mode = mxc_set_mode;
|
||||
ced->set_state_shutdown = mxc_shutdown;
|
||||
ced->set_state_oneshot = mxc_set_oneshot;
|
||||
ced->tick_resume = mxc_shutdown;
|
||||
ced->set_next_event = imxtm->gpt->set_next_event;
|
||||
ced->rating = 200;
|
||||
ced->cpumask = cpumask_of(0);
|
||||
|
|
|
@ -75,33 +75,37 @@ static irqreturn_t integrator_timer_interrupt(int irq, void *dev_id)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void clkevt_set_mode(enum clock_event_mode mode, struct clock_event_device *evt)
|
||||
static int clkevt_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE;
|
||||
|
||||
/* Disable timer */
|
||||
writel(ctrl, clkevt_base + TIMER_CTRL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clkevt_set_oneshot(struct clock_event_device *evt)
|
||||
{
|
||||
u32 ctrl = readl(clkevt_base + TIMER_CTRL) &
|
||||
~(TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC);
|
||||
|
||||
/* Leave the timer disabled, .set_next_event will enable it */
|
||||
writel(ctrl, clkevt_base + TIMER_CTRL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clkevt_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE;
|
||||
|
||||
/* Disable timer */
|
||||
writel(ctrl, clkevt_base + TIMER_CTRL);
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
/* Enable the timer and start the periodic tick */
|
||||
writel(timer_reload, clkevt_base + TIMER_LOAD);
|
||||
ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
|
||||
writel(ctrl, clkevt_base + TIMER_CTRL);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
/* Leave the timer disabled, .set_next_event will enable it */
|
||||
ctrl &= ~TIMER_CTRL_PERIODIC;
|
||||
writel(ctrl, clkevt_base + TIMER_CTRL);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
default:
|
||||
/* Just leave in disabled state */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Enable the timer and start the periodic tick */
|
||||
writel(timer_reload, clkevt_base + TIMER_LOAD);
|
||||
ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
|
||||
writel(ctrl, clkevt_base + TIMER_CTRL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clkevt_set_next_event(unsigned long next, struct clock_event_device *evt)
|
||||
|
@ -116,11 +120,15 @@ static int clkevt_set_next_event(unsigned long next, struct clock_event_device *
|
|||
}
|
||||
|
||||
static struct clock_event_device integrator_clockevent = {
|
||||
.name = "timer1",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_mode = clkevt_set_mode,
|
||||
.set_next_event = clkevt_set_next_event,
|
||||
.rating = 300,
|
||||
.name = "timer1",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC |
|
||||
CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_state_shutdown = clkevt_shutdown,
|
||||
.set_state_periodic = clkevt_set_periodic,
|
||||
.set_state_oneshot = clkevt_set_oneshot,
|
||||
.tick_resume = clkevt_shutdown,
|
||||
.set_next_event = clkevt_set_next_event,
|
||||
.rating = 300,
|
||||
};
|
||||
|
||||
static struct irqaction integrator_timer_irq = {
|
||||
|
|
|
@ -72,10 +72,10 @@ static inline void keystone_timer_barrier(void)
|
|||
|
||||
/**
|
||||
* keystone_timer_config: configures timer to work in oneshot/periodic modes.
|
||||
* @ mode: mode to configure
|
||||
* @ mask: mask of the mode to configure
|
||||
* @ period: cycles number to configure for
|
||||
*/
|
||||
static int keystone_timer_config(u64 period, enum clock_event_mode mode)
|
||||
static int keystone_timer_config(u64 period, int mask)
|
||||
{
|
||||
u32 tcr;
|
||||
u32 off;
|
||||
|
@ -84,16 +84,7 @@ static int keystone_timer_config(u64 period, enum clock_event_mode mode)
|
|||
off = tcr & ~(TCR_ENAMODE_MASK);
|
||||
|
||||
/* set enable mode */
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
tcr |= TCR_ENAMODE_ONESHOT_MASK;
|
||||
break;
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
tcr |= TCR_ENAMODE_PERIODIC_MASK;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
tcr |= mask;
|
||||
|
||||
/* disable timer */
|
||||
keystone_timer_writel(off, TCR);
|
||||
|
@ -138,24 +129,19 @@ static irqreturn_t keystone_timer_interrupt(int irq, void *dev_id)
|
|||
static int keystone_set_next_event(unsigned long cycles,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
return keystone_timer_config(cycles, evt->mode);
|
||||
return keystone_timer_config(cycles, TCR_ENAMODE_ONESHOT_MASK);
|
||||
}
|
||||
|
||||
static void keystone_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static int keystone_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
keystone_timer_config(timer.hz_period, CLOCK_EVT_MODE_PERIODIC);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
keystone_timer_disable();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
keystone_timer_disable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int keystone_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
keystone_timer_config(timer.hz_period, TCR_ENAMODE_PERIODIC_MASK);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init keystone_timer_init(struct device_node *np)
|
||||
|
@ -222,7 +208,9 @@ static void __init keystone_timer_init(struct device_node *np)
|
|||
/* setup clockevent */
|
||||
event_dev->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
|
||||
event_dev->set_next_event = keystone_set_next_event;
|
||||
event_dev->set_mode = keystone_set_mode;
|
||||
event_dev->set_state_shutdown = keystone_shutdown;
|
||||
event_dev->set_state_periodic = keystone_set_periodic;
|
||||
event_dev->set_state_oneshot = keystone_shutdown;
|
||||
event_dev->cpumask = cpu_all_mask;
|
||||
event_dev->owner = THIS_MODULE;
|
||||
event_dev->name = TIMER_NAME;
|
||||
|
|
|
@ -104,26 +104,21 @@ static int sirfsoc_timer_set_next_event(unsigned long delta,
|
|||
return next - now > delta ? -ETIME : 0;
|
||||
}
|
||||
|
||||
static void sirfsoc_timer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *ce)
|
||||
static int sirfsoc_timer_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
u32 val = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
WARN_ON(1);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
writel_relaxed(val | BIT(0),
|
||||
sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
writel_relaxed(val & ~BIT(0),
|
||||
sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
break;
|
||||
}
|
||||
|
||||
writel_relaxed(val & ~BIT(0),
|
||||
sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sirfsoc_timer_set_oneshot(struct clock_event_device *evt)
|
||||
{
|
||||
u32 val = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
|
||||
|
||||
writel_relaxed(val | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sirfsoc_clocksource_suspend(struct clocksource *cs)
|
||||
|
@ -157,7 +152,8 @@ static struct clock_event_device sirfsoc_clockevent = {
|
|||
.name = "sirfsoc_clockevent",
|
||||
.rating = 200,
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_mode = sirfsoc_timer_set_mode,
|
||||
.set_state_shutdown = sirfsoc_timer_shutdown,
|
||||
.set_state_oneshot = sirfsoc_timer_set_oneshot,
|
||||
.set_next_event = sirfsoc_timer_set_next_event,
|
||||
};
|
||||
|
||||
|
|
|
@ -133,50 +133,50 @@ static irqreturn_t sp804_timer_interrupt(int irq, void *dev_id)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void sp804_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static inline void timer_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE;
|
||||
|
||||
writel(ctrl, clkevt_base + TIMER_CTRL);
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
writel(clkevt_reload, clkevt_base + TIMER_LOAD);
|
||||
ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
|
||||
break;
|
||||
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
/* period set, and timer enabled in 'next_event' hook */
|
||||
ctrl |= TIMER_CTRL_ONESHOT;
|
||||
break;
|
||||
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
writel(0, clkevt_base + TIMER_CTRL);
|
||||
}
|
||||
|
||||
static int sp804_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
timer_shutdown(evt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sp804_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE |
|
||||
TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
|
||||
|
||||
timer_shutdown(evt);
|
||||
writel(clkevt_reload, clkevt_base + TIMER_LOAD);
|
||||
writel(ctrl, clkevt_base + TIMER_CTRL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sp804_set_next_event(unsigned long next,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
unsigned long ctrl = readl(clkevt_base + TIMER_CTRL);
|
||||
unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE |
|
||||
TIMER_CTRL_ONESHOT | TIMER_CTRL_ENABLE;
|
||||
|
||||
writel(next, clkevt_base + TIMER_LOAD);
|
||||
writel(ctrl | TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
|
||||
writel(ctrl, clkevt_base + TIMER_CTRL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clock_event_device sp804_clockevent = {
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
|
||||
CLOCK_EVT_FEAT_DYNIRQ,
|
||||
.set_mode = sp804_set_mode,
|
||||
.set_next_event = sp804_set_next_event,
|
||||
.rating = 300,
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC |
|
||||
CLOCK_EVT_FEAT_ONESHOT |
|
||||
CLOCK_EVT_FEAT_DYNIRQ,
|
||||
.set_state_shutdown = sp804_shutdown,
|
||||
.set_state_periodic = sp804_set_periodic,
|
||||
.set_state_oneshot = sp804_shutdown,
|
||||
.tick_resume = sp804_shutdown,
|
||||
.set_next_event = sp804_set_next_event,
|
||||
.rating = 300,
|
||||
};
|
||||
|
||||
static struct irqaction sp804_timer_irq = {
|
||||
|
|
|
@ -40,24 +40,25 @@ struct stm32_clock_event_ddata {
|
|||
void __iomem *base;
|
||||
};
|
||||
|
||||
static void stm32_clock_event_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evtdev)
|
||||
static int stm32_clock_event_shutdown(struct clock_event_device *evtdev)
|
||||
{
|
||||
struct stm32_clock_event_ddata *data =
|
||||
container_of(evtdev, struct stm32_clock_event_ddata, evtdev);
|
||||
void *base = data->base;
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
writel_relaxed(data->periodic_top, base + TIM_ARR);
|
||||
writel_relaxed(TIM_CR1_ARPE | TIM_CR1_CEN, base + TIM_CR1);
|
||||
break;
|
||||
writel_relaxed(0, base + TIM_CR1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
default:
|
||||
writel_relaxed(0, base + TIM_CR1);
|
||||
break;
|
||||
}
|
||||
static int stm32_clock_event_set_periodic(struct clock_event_device *evtdev)
|
||||
{
|
||||
struct stm32_clock_event_ddata *data =
|
||||
container_of(evtdev, struct stm32_clock_event_ddata, evtdev);
|
||||
void *base = data->base;
|
||||
|
||||
writel_relaxed(data->periodic_top, base + TIM_ARR);
|
||||
writel_relaxed(TIM_CR1_ARPE | TIM_CR1_CEN, base + TIM_CR1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_clock_event_set_next_event(unsigned long evt,
|
||||
|
@ -88,7 +89,10 @@ static struct stm32_clock_event_ddata clock_event_ddata = {
|
|||
.evtdev = {
|
||||
.name = "stm32 clockevent",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
|
||||
.set_mode = stm32_clock_event_set_mode,
|
||||
.set_state_shutdown = stm32_clock_event_shutdown,
|
||||
.set_state_periodic = stm32_clock_event_set_periodic,
|
||||
.set_state_oneshot = stm32_clock_event_shutdown,
|
||||
.tick_resume = stm32_clock_event_shutdown,
|
||||
.set_next_event = stm32_clock_event_set_next_event,
|
||||
.rating = 200,
|
||||
},
|
||||
|
|
|
@ -103,27 +103,31 @@ static void sun5i_clkevt_time_start(struct sun5i_timer_clkevt *ce, u8 timer, boo
|
|||
ce->timer.base + TIMER_CTL_REG(timer));
|
||||
}
|
||||
|
||||
static void sun5i_clkevt_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *clkevt)
|
||||
static int sun5i_clkevt_shutdown(struct clock_event_device *clkevt)
|
||||
{
|
||||
struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
sun5i_clkevt_time_stop(ce, 0);
|
||||
sun5i_clkevt_time_setup(ce, 0, ce->timer.ticks_per_jiffy);
|
||||
sun5i_clkevt_time_start(ce, 0, true);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
sun5i_clkevt_time_stop(ce, 0);
|
||||
sun5i_clkevt_time_start(ce, 0, false);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
default:
|
||||
sun5i_clkevt_time_stop(ce, 0);
|
||||
break;
|
||||
}
|
||||
sun5i_clkevt_time_stop(ce, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sun5i_clkevt_set_oneshot(struct clock_event_device *clkevt)
|
||||
{
|
||||
struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
|
||||
|
||||
sun5i_clkevt_time_stop(ce, 0);
|
||||
sun5i_clkevt_time_start(ce, 0, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sun5i_clkevt_set_periodic(struct clock_event_device *clkevt)
|
||||
{
|
||||
struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
|
||||
|
||||
sun5i_clkevt_time_stop(ce, 0);
|
||||
sun5i_clkevt_time_setup(ce, 0, ce->timer.ticks_per_jiffy);
|
||||
sun5i_clkevt_time_start(ce, 0, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sun5i_clkevt_next_event(unsigned long evt,
|
||||
|
@ -286,7 +290,10 @@ static int __init sun5i_setup_clockevent(struct device_node *node, void __iomem
|
|||
ce->clkevt.name = node->name;
|
||||
ce->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
|
||||
ce->clkevt.set_next_event = sun5i_clkevt_next_event;
|
||||
ce->clkevt.set_mode = sun5i_clkevt_mode;
|
||||
ce->clkevt.set_state_shutdown = sun5i_clkevt_shutdown;
|
||||
ce->clkevt.set_state_periodic = sun5i_clkevt_set_periodic;
|
||||
ce->clkevt.set_state_oneshot = sun5i_clkevt_set_oneshot;
|
||||
ce->clkevt.tick_resume = sun5i_clkevt_shutdown;
|
||||
ce->clkevt.rating = 340;
|
||||
ce->clkevt.irq = irq;
|
||||
ce->clkevt.cpumask = cpu_possible_mask;
|
||||
|
|
|
@ -187,85 +187,82 @@ struct u300_clockevent_data {
|
|||
unsigned ticks_per_jiffy;
|
||||
};
|
||||
|
||||
static int u300_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
/* Disable interrupts on GP1 */
|
||||
writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
|
||||
u300_timer_base + U300_TIMER_APP_GPT1IE);
|
||||
/* Disable GP1 */
|
||||
writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
|
||||
u300_timer_base + U300_TIMER_APP_DGPT1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The u300_set_mode() function is always called first, if we
|
||||
* have oneshot timer active, the oneshot scheduling function
|
||||
* If we have oneshot timer active, the oneshot scheduling function
|
||||
* u300_set_next_event() is called immediately after.
|
||||
*/
|
||||
static void u300_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static int u300_set_oneshot(struct clock_event_device *evt)
|
||||
{
|
||||
/* Just return; here? */
|
||||
/*
|
||||
* The actual event will be programmed by the next event hook,
|
||||
* so we just set a dummy value somewhere at the end of the
|
||||
* universe here.
|
||||
*/
|
||||
/* Disable interrupts on GPT1 */
|
||||
writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
|
||||
u300_timer_base + U300_TIMER_APP_GPT1IE);
|
||||
/* Disable GP1 while we're reprogramming it. */
|
||||
writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
|
||||
u300_timer_base + U300_TIMER_APP_DGPT1);
|
||||
/*
|
||||
* Expire far in the future, u300_set_next_event() will be
|
||||
* called soon...
|
||||
*/
|
||||
writel(0xFFFFFFFF, u300_timer_base + U300_TIMER_APP_GPT1TC);
|
||||
/* We run one shot per tick here! */
|
||||
writel(U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT,
|
||||
u300_timer_base + U300_TIMER_APP_SGPT1M);
|
||||
/* Enable interrupts for this timer */
|
||||
writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE,
|
||||
u300_timer_base + U300_TIMER_APP_GPT1IE);
|
||||
/* Enable timer */
|
||||
writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE,
|
||||
u300_timer_base + U300_TIMER_APP_EGPT1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int u300_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
struct u300_clockevent_data *cevdata =
|
||||
container_of(evt, struct u300_clockevent_data, cevd);
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
/* Disable interrupts on GPT1 */
|
||||
writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
|
||||
u300_timer_base + U300_TIMER_APP_GPT1IE);
|
||||
/* Disable GP1 while we're reprogramming it. */
|
||||
writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
|
||||
u300_timer_base + U300_TIMER_APP_DGPT1);
|
||||
/*
|
||||
* Set the periodic mode to a certain number of ticks per
|
||||
* jiffy.
|
||||
*/
|
||||
writel(cevdata->ticks_per_jiffy,
|
||||
u300_timer_base + U300_TIMER_APP_GPT1TC);
|
||||
/*
|
||||
* Set continuous mode, so the timer keeps triggering
|
||||
* interrupts.
|
||||
*/
|
||||
writel(U300_TIMER_APP_SGPT1M_MODE_CONTINUOUS,
|
||||
u300_timer_base + U300_TIMER_APP_SGPT1M);
|
||||
/* Enable timer interrupts */
|
||||
writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE,
|
||||
u300_timer_base + U300_TIMER_APP_GPT1IE);
|
||||
/* Then enable the OS timer again */
|
||||
writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE,
|
||||
u300_timer_base + U300_TIMER_APP_EGPT1);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
/* Just break; here? */
|
||||
/*
|
||||
* The actual event will be programmed by the next event hook,
|
||||
* so we just set a dummy value somewhere at the end of the
|
||||
* universe here.
|
||||
*/
|
||||
/* Disable interrupts on GPT1 */
|
||||
writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
|
||||
u300_timer_base + U300_TIMER_APP_GPT1IE);
|
||||
/* Disable GP1 while we're reprogramming it. */
|
||||
writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
|
||||
u300_timer_base + U300_TIMER_APP_DGPT1);
|
||||
/*
|
||||
* Expire far in the future, u300_set_next_event() will be
|
||||
* called soon...
|
||||
*/
|
||||
writel(0xFFFFFFFF, u300_timer_base + U300_TIMER_APP_GPT1TC);
|
||||
/* We run one shot per tick here! */
|
||||
writel(U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT,
|
||||
u300_timer_base + U300_TIMER_APP_SGPT1M);
|
||||
/* Enable interrupts for this timer */
|
||||
writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE,
|
||||
u300_timer_base + U300_TIMER_APP_GPT1IE);
|
||||
/* Enable timer */
|
||||
writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE,
|
||||
u300_timer_base + U300_TIMER_APP_EGPT1);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
/* Disable interrupts on GP1 */
|
||||
writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
|
||||
u300_timer_base + U300_TIMER_APP_GPT1IE);
|
||||
/* Disable GP1 */
|
||||
writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
|
||||
u300_timer_base + U300_TIMER_APP_DGPT1);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
/* Ignore this call */
|
||||
break;
|
||||
}
|
||||
/* Disable interrupts on GPT1 */
|
||||
writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
|
||||
u300_timer_base + U300_TIMER_APP_GPT1IE);
|
||||
/* Disable GP1 while we're reprogramming it. */
|
||||
writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
|
||||
u300_timer_base + U300_TIMER_APP_DGPT1);
|
||||
/*
|
||||
* Set the periodic mode to a certain number of ticks per
|
||||
* jiffy.
|
||||
*/
|
||||
writel(cevdata->ticks_per_jiffy,
|
||||
u300_timer_base + U300_TIMER_APP_GPT1TC);
|
||||
/*
|
||||
* Set continuous mode, so the timer keeps triggering
|
||||
* interrupts.
|
||||
*/
|
||||
writel(U300_TIMER_APP_SGPT1M_MODE_CONTINUOUS,
|
||||
u300_timer_base + U300_TIMER_APP_SGPT1M);
|
||||
/* Enable timer interrupts */
|
||||
writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE,
|
||||
u300_timer_base + U300_TIMER_APP_GPT1IE);
|
||||
/* Then enable the OS timer again */
|
||||
writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE,
|
||||
u300_timer_base + U300_TIMER_APP_EGPT1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -309,13 +306,15 @@ static int u300_set_next_event(unsigned long cycles,
|
|||
static struct u300_clockevent_data u300_clockevent_data = {
|
||||
/* Use general purpose timer 1 as clock event */
|
||||
.cevd = {
|
||||
.name = "GPT1",
|
||||
.name = "GPT1",
|
||||
/* Reasonably fast and accurate clock event */
|
||||
.rating = 300,
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC |
|
||||
CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_next_event = u300_set_next_event,
|
||||
.set_mode = u300_set_mode,
|
||||
.rating = 300,
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC |
|
||||
CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_next_event = u300_set_next_event,
|
||||
.set_state_shutdown = u300_shutdown,
|
||||
.set_state_periodic = u300_set_periodic,
|
||||
.set_state_oneshot = u300_set_oneshot,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -86,20 +86,16 @@ static int pit_set_next_event(unsigned long delta,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void pit_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static int pit_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
pit_set_next_event(cycle_per_jiffy, evt);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
pit_timer_disable();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pit_timer_disable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pit_set_periodic(struct clock_event_device *evt)
|
||||
{
|
||||
pit_set_next_event(cycle_per_jiffy, evt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t pit_timer_interrupt(int irq, void *dev_id)
|
||||
|
@ -114,7 +110,7 @@ static irqreturn_t pit_timer_interrupt(int irq, void *dev_id)
|
|||
* and start the counter again. So software need to disable the timer
|
||||
* to stop the counter loop in ONESHOT mode.
|
||||
*/
|
||||
if (likely(evt->mode == CLOCK_EVT_MODE_ONESHOT))
|
||||
if (likely(clockevent_state_oneshot(evt)))
|
||||
pit_timer_disable();
|
||||
|
||||
evt->event_handler(evt);
|
||||
|
@ -125,7 +121,8 @@ static irqreturn_t pit_timer_interrupt(int irq, void *dev_id)
|
|||
static struct clock_event_device clockevent_pit = {
|
||||
.name = "VF pit timer",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_mode = pit_set_mode,
|
||||
.set_state_shutdown = pit_shutdown,
|
||||
.set_state_periodic = pit_set_periodic,
|
||||
.set_next_event = pit_set_next_event,
|
||||
.rating = 300,
|
||||
};
|
||||
|
|
|
@ -88,29 +88,20 @@ static int vt8500_timer_set_next_event(unsigned long cycles,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void vt8500_timer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
static int vt8500_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
writel(readl(regbase + TIMER_CTRL_VAL) | 1,
|
||||
regbase + TIMER_CTRL_VAL);
|
||||
writel(0, regbase + TIMER_IER_VAL);
|
||||
break;
|
||||
}
|
||||
writel(readl(regbase + TIMER_CTRL_VAL) | 1, regbase + TIMER_CTRL_VAL);
|
||||
writel(0, regbase + TIMER_IER_VAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clock_event_device clockevent = {
|
||||
.name = "vt8500_timer",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT,
|
||||
.rating = 200,
|
||||
.set_next_event = vt8500_timer_set_next_event,
|
||||
.set_mode = vt8500_timer_set_mode,
|
||||
.name = "vt8500_timer",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT,
|
||||
.rating = 200,
|
||||
.set_next_event = vt8500_timer_set_next_event,
|
||||
.set_state_shutdown = vt8500_shutdown,
|
||||
.set_state_oneshot = vt8500_shutdown,
|
||||
};
|
||||
|
||||
static irqreturn_t vt8500_timer_interrupt(int irq, void *dev_id)
|
||||
|
|
|
@ -76,32 +76,28 @@ static int zevio_timer_set_event(unsigned long delta,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void zevio_timer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *dev)
|
||||
static int zevio_timer_shutdown(struct clock_event_device *dev)
|
||||
{
|
||||
struct zevio_timer *timer = container_of(dev, struct zevio_timer,
|
||||
clkevt);
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
/* Enable timer interrupts */
|
||||
writel(TIMER_INTR_MSK, timer->interrupt_regs + IO_INTR_MSK);
|
||||
writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
/* Disable timer interrupts */
|
||||
writel(0, timer->interrupt_regs + IO_INTR_MSK);
|
||||
writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK);
|
||||
/* Stop timer */
|
||||
writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
default:
|
||||
/* Unsupported */
|
||||
break;
|
||||
}
|
||||
/* Disable timer interrupts */
|
||||
writel(0, timer->interrupt_regs + IO_INTR_MSK);
|
||||
writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK);
|
||||
/* Stop timer */
|
||||
writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zevio_timer_set_oneshot(struct clock_event_device *dev)
|
||||
{
|
||||
struct zevio_timer *timer = container_of(dev, struct zevio_timer,
|
||||
clkevt);
|
||||
|
||||
/* Enable timer interrupts */
|
||||
writel(TIMER_INTR_MSK, timer->interrupt_regs + IO_INTR_MSK);
|
||||
writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t zevio_timer_interrupt(int irq, void *dev_id)
|
||||
|
@ -162,7 +158,9 @@ static int __init zevio_timer_add(struct device_node *node)
|
|||
if (timer->interrupt_regs && irqnr) {
|
||||
timer->clkevt.name = timer->clockevent_name;
|
||||
timer->clkevt.set_next_event = zevio_timer_set_event;
|
||||
timer->clkevt.set_mode = zevio_timer_set_mode;
|
||||
timer->clkevt.set_state_shutdown = zevio_timer_shutdown;
|
||||
timer->clkevt.set_state_oneshot = zevio_timer_set_oneshot;
|
||||
timer->clkevt.tick_resume = zevio_timer_set_oneshot;
|
||||
timer->clkevt.rating = 200;
|
||||
timer->clkevt.cpumask = cpu_all_mask;
|
||||
timer->clkevt.features = CLOCK_EVT_FEAT_ONESHOT;
|
||||
|
|
|
@ -234,13 +234,10 @@ static inline int tick_check_broadcast_expired(void) { return 0; }
|
|||
static inline void tick_setup_hrtimer_broadcast(void) { }
|
||||
# endif
|
||||
|
||||
extern int clockevents_notify(unsigned long reason, void *arg);
|
||||
|
||||
#else /* !CONFIG_GENERIC_CLOCKEVENTS: */
|
||||
|
||||
static inline void clockevents_suspend(void) { }
|
||||
static inline void clockevents_resume(void) { }
|
||||
static inline int clockevents_notify(unsigned long reason, void *arg) { return 0; }
|
||||
static inline int tick_check_broadcast_expired(void) { return 0; }
|
||||
static inline void tick_setup_hrtimer_broadcast(void) { }
|
||||
|
||||
|
|
|
@ -409,9 +409,25 @@ static __always_inline unsigned long usecs_to_jiffies(const unsigned int u)
|
|||
}
|
||||
}
|
||||
|
||||
extern unsigned long timespec_to_jiffies(const struct timespec *value);
|
||||
extern void jiffies_to_timespec(const unsigned long jiffies,
|
||||
struct timespec *value);
|
||||
extern unsigned long timespec64_to_jiffies(const struct timespec64 *value);
|
||||
extern void jiffies_to_timespec64(const unsigned long jiffies,
|
||||
struct timespec64 *value);
|
||||
static inline unsigned long timespec_to_jiffies(const struct timespec *value)
|
||||
{
|
||||
struct timespec64 ts = timespec_to_timespec64(*value);
|
||||
|
||||
return timespec64_to_jiffies(&ts);
|
||||
}
|
||||
|
||||
static inline void jiffies_to_timespec(const unsigned long jiffies,
|
||||
struct timespec *value)
|
||||
{
|
||||
struct timespec64 ts;
|
||||
|
||||
jiffies_to_timespec64(jiffies, &ts);
|
||||
*value = timespec64_to_timespec(ts);
|
||||
}
|
||||
|
||||
extern unsigned long timeval_to_jiffies(const struct timeval *value);
|
||||
extern void jiffies_to_timeval(const unsigned long jiffies,
|
||||
struct timeval *value);
|
||||
|
|
|
@ -12,11 +12,18 @@ typedef __s64 time64_t;
|
|||
*/
|
||||
#if __BITS_PER_LONG == 64
|
||||
# define timespec64 timespec
|
||||
#define itimerspec64 itimerspec
|
||||
#else
|
||||
struct timespec64 {
|
||||
time64_t tv_sec; /* seconds */
|
||||
long tv_nsec; /* nanoseconds */
|
||||
};
|
||||
|
||||
struct itimerspec64 {
|
||||
struct timespec64 it_interval;
|
||||
struct timespec64 it_value;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* Parameters used to convert the timespec values: */
|
||||
|
@ -45,6 +52,16 @@ static inline struct timespec64 timespec_to_timespec64(const struct timespec ts)
|
|||
return ts;
|
||||
}
|
||||
|
||||
static inline struct itimerspec itimerspec64_to_itimerspec(struct itimerspec64 *its64)
|
||||
{
|
||||
return *its64;
|
||||
}
|
||||
|
||||
static inline struct itimerspec64 itimerspec_to_itimerspec64(struct itimerspec *its)
|
||||
{
|
||||
return *its;
|
||||
}
|
||||
|
||||
# define timespec64_equal timespec_equal
|
||||
# define timespec64_compare timespec_compare
|
||||
# define set_normalized_timespec64 set_normalized_timespec
|
||||
|
@ -77,6 +94,24 @@ static inline struct timespec64 timespec_to_timespec64(const struct timespec ts)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static inline struct itimerspec itimerspec64_to_itimerspec(struct itimerspec64 *its64)
|
||||
{
|
||||
struct itimerspec ret;
|
||||
|
||||
ret.it_interval = timespec64_to_timespec(its64->it_interval);
|
||||
ret.it_value = timespec64_to_timespec(its64->it_value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline struct itimerspec64 itimerspec_to_itimerspec64(struct itimerspec *its)
|
||||
{
|
||||
struct itimerspec64 ret;
|
||||
|
||||
ret.it_interval = timespec_to_timespec64(its->it_interval);
|
||||
ret.it_value = timespec_to_timespec64(its->it_value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int timespec64_equal(const struct timespec64 *a,
|
||||
const struct timespec64 *b)
|
||||
{
|
||||
|
|
|
@ -18,10 +18,17 @@ extern int do_sys_settimeofday(const struct timespec *tv,
|
|||
* Kernel time accessors
|
||||
*/
|
||||
unsigned long get_seconds(void);
|
||||
struct timespec current_kernel_time(void);
|
||||
struct timespec64 current_kernel_time64(void);
|
||||
/* does not take xtime_lock */
|
||||
struct timespec __current_kernel_time(void);
|
||||
|
||||
static inline struct timespec current_kernel_time(void)
|
||||
{
|
||||
struct timespec64 now = current_kernel_time64();
|
||||
|
||||
return timespec64_to_timespec(now);
|
||||
}
|
||||
|
||||
/*
|
||||
* timespec based interfaces
|
||||
*/
|
||||
|
|
|
@ -183,7 +183,7 @@ struct hrtimer_cpu_base *get_target_base(struct hrtimer_cpu_base *base,
|
|||
int pinned)
|
||||
{
|
||||
if (pinned || !base->migration_enabled)
|
||||
return this_cpu_ptr(&hrtimer_bases);
|
||||
return base;
|
||||
return &per_cpu(hrtimer_bases, get_nohz_timer_target());
|
||||
}
|
||||
#else
|
||||
|
@ -191,23 +191,32 @@ static inline
|
|||
struct hrtimer_cpu_base *get_target_base(struct hrtimer_cpu_base *base,
|
||||
int pinned)
|
||||
{
|
||||
return this_cpu_ptr(&hrtimer_bases);
|
||||
return base;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Switch the timer base to the current CPU when possible.
|
||||
* We switch the timer base to a power-optimized selected CPU target,
|
||||
* if:
|
||||
* - NO_HZ_COMMON is enabled
|
||||
* - timer migration is enabled
|
||||
* - the timer callback is not running
|
||||
* - the timer is not the first expiring timer on the new target
|
||||
*
|
||||
* If one of the above requirements is not fulfilled we move the timer
|
||||
* to the current CPU or leave it on the previously assigned CPU if
|
||||
* the timer callback is currently running.
|
||||
*/
|
||||
static inline struct hrtimer_clock_base *
|
||||
switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base,
|
||||
int pinned)
|
||||
{
|
||||
struct hrtimer_cpu_base *new_cpu_base, *this_base;
|
||||
struct hrtimer_cpu_base *new_cpu_base, *this_cpu_base;
|
||||
struct hrtimer_clock_base *new_base;
|
||||
int basenum = base->index;
|
||||
|
||||
this_base = this_cpu_ptr(&hrtimer_bases);
|
||||
new_cpu_base = get_target_base(this_base, pinned);
|
||||
this_cpu_base = this_cpu_ptr(&hrtimer_bases);
|
||||
new_cpu_base = get_target_base(this_cpu_base, pinned);
|
||||
again:
|
||||
new_base = &new_cpu_base->clock_base[basenum];
|
||||
|
||||
|
@ -229,19 +238,19 @@ again:
|
|||
raw_spin_unlock(&base->cpu_base->lock);
|
||||
raw_spin_lock(&new_base->cpu_base->lock);
|
||||
|
||||
if (new_cpu_base != this_base &&
|
||||
if (new_cpu_base != this_cpu_base &&
|
||||
hrtimer_check_target(timer, new_base)) {
|
||||
raw_spin_unlock(&new_base->cpu_base->lock);
|
||||
raw_spin_lock(&base->cpu_base->lock);
|
||||
new_cpu_base = this_base;
|
||||
new_cpu_base = this_cpu_base;
|
||||
timer->base = base;
|
||||
goto again;
|
||||
}
|
||||
timer->base = new_base;
|
||||
} else {
|
||||
if (new_cpu_base != this_base &&
|
||||
if (new_cpu_base != this_cpu_base &&
|
||||
hrtimer_check_target(timer, new_base)) {
|
||||
new_cpu_base = this_base;
|
||||
new_cpu_base = this_cpu_base;
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
|
@ -679,14 +688,14 @@ static void retrigger_next_event(void *arg)
|
|||
/*
|
||||
* Switch to high resolution mode
|
||||
*/
|
||||
static int hrtimer_switch_to_hres(void)
|
||||
static void hrtimer_switch_to_hres(void)
|
||||
{
|
||||
struct hrtimer_cpu_base *base = this_cpu_ptr(&hrtimer_bases);
|
||||
|
||||
if (tick_init_highres()) {
|
||||
printk(KERN_WARNING "Could not switch to high resolution "
|
||||
"mode on CPU %d\n", base->cpu);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
base->hres_active = 1;
|
||||
hrtimer_resolution = HIGH_RES_NSEC;
|
||||
|
@ -694,7 +703,6 @@ static int hrtimer_switch_to_hres(void)
|
|||
tick_setup_sched_timer();
|
||||
/* "Retrigger" the interrupt to get things going */
|
||||
retrigger_next_event(NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void clock_was_set_work(struct work_struct *work)
|
||||
|
@ -718,7 +726,7 @@ void clock_was_set_delayed(void)
|
|||
static inline int __hrtimer_hres_active(struct hrtimer_cpu_base *b) { return 0; }
|
||||
static inline int hrtimer_hres_active(void) { return 0; }
|
||||
static inline int hrtimer_is_hres_enabled(void) { return 0; }
|
||||
static inline int hrtimer_switch_to_hres(void) { return 0; }
|
||||
static inline void hrtimer_switch_to_hres(void) { }
|
||||
static inline void
|
||||
hrtimer_force_reprogram(struct hrtimer_cpu_base *base, int skip_equal) { }
|
||||
static inline int hrtimer_reprogram(struct hrtimer *timer,
|
||||
|
|
|
@ -487,6 +487,11 @@ out:
|
|||
}
|
||||
|
||||
#ifdef CONFIG_GENERIC_CMOS_UPDATE
|
||||
int __weak update_persistent_clock(struct timespec now)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int __weak update_persistent_clock64(struct timespec64 now64)
|
||||
{
|
||||
struct timespec now;
|
||||
|
|
|
@ -18,30 +18,23 @@
|
|||
|
||||
static struct hrtimer bctimer;
|
||||
|
||||
static void bc_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *bc)
|
||||
static int bc_shutdown(struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
/*
|
||||
* Note, we cannot cancel the timer here as we might
|
||||
* run into the following live lock scenario:
|
||||
*
|
||||
* cpu 0 cpu1
|
||||
* lock(broadcast_lock);
|
||||
* hrtimer_interrupt()
|
||||
* bc_handler()
|
||||
* tick_handle_oneshot_broadcast();
|
||||
* lock(broadcast_lock);
|
||||
* hrtimer_cancel()
|
||||
* wait_for_callback()
|
||||
*/
|
||||
hrtimer_try_to_cancel(&bctimer);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Note, we cannot cancel the timer here as we might
|
||||
* run into the following live lock scenario:
|
||||
*
|
||||
* cpu 0 cpu1
|
||||
* lock(broadcast_lock);
|
||||
* hrtimer_interrupt()
|
||||
* bc_handler()
|
||||
* tick_handle_oneshot_broadcast();
|
||||
* lock(broadcast_lock);
|
||||
* hrtimer_cancel()
|
||||
* wait_for_callback()
|
||||
*/
|
||||
hrtimer_try_to_cancel(&bctimer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -82,7 +75,7 @@ static int bc_set_next(ktime_t expires, struct clock_event_device *bc)
|
|||
}
|
||||
|
||||
static struct clock_event_device ce_broadcast_hrtimer = {
|
||||
.set_mode = bc_set_mode,
|
||||
.set_state_shutdown = bc_shutdown,
|
||||
.set_next_ktime = bc_set_next,
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT |
|
||||
CLOCK_EVT_FEAT_KTIME |
|
||||
|
@ -102,13 +95,11 @@ static enum hrtimer_restart bc_handler(struct hrtimer *t)
|
|||
{
|
||||
ce_broadcast_hrtimer.event_handler(&ce_broadcast_hrtimer);
|
||||
|
||||
switch (ce_broadcast_hrtimer.mode) {
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
if (clockevent_state_oneshot(&ce_broadcast_hrtimer))
|
||||
if (ce_broadcast_hrtimer.next_event.tv64 != KTIME_MAX)
|
||||
return HRTIMER_RESTART;
|
||||
default:
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
void tick_setup_hrtimer_broadcast(void)
|
||||
|
|
|
@ -304,9 +304,6 @@ void tick_check_new_device(struct clock_event_device *newdev)
|
|||
int cpu;
|
||||
|
||||
cpu = smp_processor_id();
|
||||
if (!cpumask_test_cpu(cpu, newdev->cpumask))
|
||||
goto out_bc;
|
||||
|
||||
td = &per_cpu(tick_cpu_device, cpu);
|
||||
curdev = td->evtdev;
|
||||
|
||||
|
|
|
@ -291,26 +291,20 @@ EXPORT_SYMBOL(jiffies_to_usecs);
|
|||
* @t: Timespec
|
||||
* @gran: Granularity in ns.
|
||||
*
|
||||
* Truncate a timespec to a granularity. gran must be smaller than a second.
|
||||
* Always rounds down.
|
||||
*
|
||||
* This function should be only used for timestamps returned by
|
||||
* current_kernel_time() or CURRENT_TIME, not with do_gettimeofday() because
|
||||
* it doesn't handle the better resolution of the latter.
|
||||
* Truncate a timespec to a granularity. Always rounds down. gran must
|
||||
* not be 0 nor greater than a second (NSEC_PER_SEC, or 10^9 ns).
|
||||
*/
|
||||
struct timespec timespec_trunc(struct timespec t, unsigned gran)
|
||||
{
|
||||
/*
|
||||
* Division is pretty slow so avoid it for common cases.
|
||||
* Currently current_kernel_time() never returns better than
|
||||
* jiffies resolution. Exploit that.
|
||||
*/
|
||||
if (gran <= jiffies_to_usecs(1) * 1000) {
|
||||
/* Avoid division in the common cases 1 ns and 1 s. */
|
||||
if (gran == 1) {
|
||||
/* nothing */
|
||||
} else if (gran == 1000000000) {
|
||||
} else if (gran == NSEC_PER_SEC) {
|
||||
t.tv_nsec = 0;
|
||||
} else {
|
||||
} else if (gran > 1 && gran < NSEC_PER_SEC) {
|
||||
t.tv_nsec -= t.tv_nsec % gran;
|
||||
} else {
|
||||
WARN(1, "illegal file time granularity: %u", gran);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
@ -550,7 +544,7 @@ EXPORT_SYMBOL(__usecs_to_jiffies);
|
|||
* value to a scaled second value.
|
||||
*/
|
||||
static unsigned long
|
||||
__timespec_to_jiffies(unsigned long sec, long nsec)
|
||||
__timespec64_to_jiffies(u64 sec, long nsec)
|
||||
{
|
||||
nsec = nsec + TICK_NSEC - 1;
|
||||
|
||||
|
@ -558,22 +552,27 @@ __timespec_to_jiffies(unsigned long sec, long nsec)
|
|||
sec = MAX_SEC_IN_JIFFIES;
|
||||
nsec = 0;
|
||||
}
|
||||
return (((u64)sec * SEC_CONVERSION) +
|
||||
return ((sec * SEC_CONVERSION) +
|
||||
(((u64)nsec * NSEC_CONVERSION) >>
|
||||
(NSEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC;
|
||||
|
||||
}
|
||||
|
||||
unsigned long
|
||||
timespec_to_jiffies(const struct timespec *value)
|
||||
static unsigned long
|
||||
__timespec_to_jiffies(unsigned long sec, long nsec)
|
||||
{
|
||||
return __timespec_to_jiffies(value->tv_sec, value->tv_nsec);
|
||||
return __timespec64_to_jiffies((u64)sec, nsec);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(timespec_to_jiffies);
|
||||
unsigned long
|
||||
timespec64_to_jiffies(const struct timespec64 *value)
|
||||
{
|
||||
return __timespec64_to_jiffies(value->tv_sec, value->tv_nsec);
|
||||
}
|
||||
EXPORT_SYMBOL(timespec64_to_jiffies);
|
||||
|
||||
void
|
||||
jiffies_to_timespec(const unsigned long jiffies, struct timespec *value)
|
||||
jiffies_to_timespec64(const unsigned long jiffies, struct timespec64 *value)
|
||||
{
|
||||
/*
|
||||
* Convert jiffies to nanoseconds and separate with
|
||||
|
@ -584,7 +583,7 @@ jiffies_to_timespec(const unsigned long jiffies, struct timespec *value)
|
|||
NSEC_PER_SEC, &rem);
|
||||
value->tv_nsec = rem;
|
||||
}
|
||||
EXPORT_SYMBOL(jiffies_to_timespec);
|
||||
EXPORT_SYMBOL(jiffies_to_timespec64);
|
||||
|
||||
/*
|
||||
* We could use a similar algorithm to timespec_to_jiffies (with a
|
||||
|
|
|
@ -911,6 +911,7 @@ int do_settimeofday64(const struct timespec64 *ts)
|
|||
struct timekeeper *tk = &tk_core.timekeeper;
|
||||
struct timespec64 ts_delta, xt;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
if (!timespec64_valid_strict(ts))
|
||||
return -EINVAL;
|
||||
|
@ -924,10 +925,15 @@ int do_settimeofday64(const struct timespec64 *ts)
|
|||
ts_delta.tv_sec = ts->tv_sec - xt.tv_sec;
|
||||
ts_delta.tv_nsec = ts->tv_nsec - xt.tv_nsec;
|
||||
|
||||
if (timespec64_compare(&tk->wall_to_monotonic, &ts_delta) > 0) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
tk_set_wall_to_mono(tk, timespec64_sub(tk->wall_to_monotonic, ts_delta));
|
||||
|
||||
tk_set_xtime(tk, ts);
|
||||
|
||||
out:
|
||||
timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);
|
||||
|
||||
write_seqcount_end(&tk_core.seq);
|
||||
|
@ -936,7 +942,7 @@ int do_settimeofday64(const struct timespec64 *ts)
|
|||
/* signal hrtimers about time change */
|
||||
clock_was_set();
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(do_settimeofday64);
|
||||
|
||||
|
@ -965,7 +971,8 @@ int timekeeping_inject_offset(struct timespec *ts)
|
|||
|
||||
/* Make sure the proposed value is valid */
|
||||
tmp = timespec64_add(tk_xtime(tk), ts64);
|
||||
if (!timespec64_valid_strict(&tmp)) {
|
||||
if (timespec64_compare(&tk->wall_to_monotonic, &ts64) > 0 ||
|
||||
!timespec64_valid_strict(&tmp)) {
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
@ -1874,7 +1881,7 @@ struct timespec __current_kernel_time(void)
|
|||
return timespec64_to_timespec(tk_xtime(tk));
|
||||
}
|
||||
|
||||
struct timespec current_kernel_time(void)
|
||||
struct timespec64 current_kernel_time64(void)
|
||||
{
|
||||
struct timekeeper *tk = &tk_core.timekeeper;
|
||||
struct timespec64 now;
|
||||
|
@ -1886,9 +1893,9 @@ struct timespec current_kernel_time(void)
|
|||
now = tk_xtime(tk);
|
||||
} while (read_seqcount_retry(&tk_core.seq, seq));
|
||||
|
||||
return timespec64_to_timespec(now);
|
||||
return now;
|
||||
}
|
||||
EXPORT_SYMBOL(current_kernel_time);
|
||||
EXPORT_SYMBOL(current_kernel_time64);
|
||||
|
||||
struct timespec64 get_monotonic_coarse64(void)
|
||||
{
|
||||
|
|
|
@ -137,7 +137,7 @@ print_base(struct seq_file *m, struct hrtimer_clock_base *base, u64 now)
|
|||
(unsigned long long) ktime_to_ns(base->offset));
|
||||
#endif
|
||||
SEQ_printf(m, "active timers:\n");
|
||||
print_active_timers(m, base, now);
|
||||
print_active_timers(m, base, now + ktime_to_ns(base->offset));
|
||||
}
|
||||
|
||||
static void print_cpu(struct seq_file *m, int cpu, u64 now)
|
||||
|
|
Loading…
Reference in New Issue