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 ...
このコミットが含まれているのは:
@@ -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;
|
||||
|
新しいイシューから参照
ユーザーをブロックする