Source
x
sun4i_clkevt_time_setup(timer_of_base(to), 0, evt - TIMER_SYNC_TICKS);
/*
* Allwinner A1X SoCs timer handling.
*
* Copyright (C) 2012 Maxime Ripard
*
* Maxime Ripard <maxime.ripard@free-electrons.com>
*
* Based on code from
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
* Benn Huang <benn@allwinnertech.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
/*
* When we disable a timer, we need to wait at least for 2 cycles of
* the timer source clock. We will use for that the clocksource timer
* that is already setup and runs at the same frequency than the other
* timers, and we never will be disabled.
*/
static void sun4i_clkevt_sync(void __iomem *base)
{
u32 old = readl(base + TIMER_CNTVAL_REG(1));
while ((old - readl(base + TIMER_CNTVAL_REG(1))) < TIMER_SYNC_TICKS)
cpu_relax();
}
static void sun4i_clkevt_time_stop(void __iomem *base, u8 timer)
{
u32 val = readl(base + TIMER_CTL_REG(timer));
writel(val & ~TIMER_CTL_ENABLE, base + TIMER_CTL_REG(timer));
sun4i_clkevt_sync(base);
}
static void sun4i_clkevt_time_setup(void __iomem *base, u8 timer,
unsigned long delay)
{
writel(delay, base + TIMER_INTVAL_REG(timer));
}
static void sun4i_clkevt_time_start(void __iomem *base, u8 timer,
bool periodic)
{
u32 val = readl(base + TIMER_CTL_REG(timer));
if (periodic)
val &= ~TIMER_CTL_ONESHOT;
else
val |= TIMER_CTL_ONESHOT;
writel(val | TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
base + TIMER_CTL_REG(timer));
}
static int sun4i_clkevt_shutdown(struct clock_event_device *evt)
{
struct timer_of *to = to_timer_of(evt);
sun4i_clkevt_time_stop(timer_of_base(to), 0);
return 0;
}