hw/timer/exynos4210_mct.c: Switch GFRC to transaction-based ptimer API

We want to switch the exynos MCT code away from bottom-half based ptimers to
the new transaction-based ptimer API. The MCT is complicated
and uses multiple different ptimers, so it's clearer to switch
it a piece at a time. Here we change over only the GFRC.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20191008171740.9679-12-peter.maydell@linaro.org
This commit is contained in:
Peter Maydell 2019-10-08 18:17:30 +01:00
parent 30e22c8733
commit 9ede4ec094

View file

@ -364,6 +364,7 @@ static void exynos4210_mct_update_freq(Exynos4210MCTState *s);
/*
* Set counter of FRC global timer.
* Must be called within exynos4210_gfrc_tx_begin/commit block.
*/
static void exynos4210_gfrc_set_count(Exynos4210MCTGT *s, uint64_t count)
{
@ -385,6 +386,7 @@ static uint64_t exynos4210_gfrc_get_count(Exynos4210MCTGT *s)
/*
* Stop global FRC timer
* Must be called within exynos4210_gfrc_tx_begin/commit block.
*/
static void exynos4210_gfrc_stop(Exynos4210MCTGT *s)
{
@ -395,6 +397,7 @@ static void exynos4210_gfrc_stop(Exynos4210MCTGT *s)
/*
* Start global FRC timer
* Must be called within exynos4210_gfrc_tx_begin/commit block.
*/
static void exynos4210_gfrc_start(Exynos4210MCTGT *s)
{
@ -403,6 +406,21 @@ static void exynos4210_gfrc_start(Exynos4210MCTGT *s)
ptimer_run(s->ptimer_frc, 1);
}
/*
* Start ptimer transaction for global FRC timer; this is just for
* consistency with the way we wrap operations like stop and run.
*/
static void exynos4210_gfrc_tx_begin(Exynos4210MCTGT *s)
{
ptimer_transaction_begin(s->ptimer_frc);
}
/* Commit ptimer transaction for global FRC timer. */
static void exynos4210_gfrc_tx_commit(Exynos4210MCTGT *s)
{
ptimer_transaction_commit(s->ptimer_frc);
}
/*
* Find next nearest Comparator. If current Comparator value equals to other
* Comparator value, skip them both
@ -492,6 +510,7 @@ static uint64_t exynos4210_gcomp_get_distance(Exynos4210MCTState *s, int32_t id)
/*
* Restart global FRC timer
* Must be called within exynos4210_gfrc_tx_begin/commit block.
*/
static void exynos4210_gfrc_restart(Exynos4210MCTState *s)
{
@ -933,6 +952,19 @@ static void exynos4210_ltick_event(void *opaque)
exynos4210_ltick_int_start(&s->tick_timer);
}
static void tx_ptimer_set_freq(ptimer_state *s, uint32_t freq)
{
/*
* callers of exynos4210_mct_update_freq() never do anything
* else that needs to be in the same ptimer transaction, so
* to avoid a lot of repetition we have a convenience function
* for begin/set_freq/commit.
*/
ptimer_transaction_begin(s);
ptimer_set_freq(s, freq);
ptimer_transaction_commit(s);
}
/* update timer frequency */
static void exynos4210_mct_update_freq(Exynos4210MCTState *s)
{
@ -945,7 +977,7 @@ static void exynos4210_mct_update_freq(Exynos4210MCTState *s)
DPRINTF("freq=%dHz\n", s->freq);
/* global timer */
ptimer_set_freq(s->g_timer.ptimer_frc, s->freq);
tx_ptimer_set_freq(s->g_timer.ptimer_frc, s->freq);
/* local timer */
ptimer_set_freq(s->l_timer[0].tick_timer.ptimer_tick, s->freq);
@ -965,7 +997,9 @@ static void exynos4210_mct_reset(DeviceState *d)
/* global timer */
memset(&s->g_timer.reg, 0, sizeof(s->g_timer.reg));
exynos4210_gfrc_tx_begin(&s->g_timer);
exynos4210_gfrc_stop(&s->g_timer);
exynos4210_gfrc_tx_commit(&s->g_timer);
/* local timer */
memset(s->l_timer[0].reg.cnt, 0, sizeof(s->l_timer[0].reg.cnt));
@ -1144,7 +1178,9 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
}
s->g_timer.reg.cnt = new_frc;
exynos4210_gfrc_tx_begin(&s->g_timer);
exynos4210_gfrc_restart(s);
exynos4210_gfrc_tx_commit(&s->g_timer);
break;
case G_CNT_WSTAT:
@ -1168,7 +1204,9 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
s->g_timer.reg.wstat |= G_WSTAT_COMP_L(index);
}
exynos4210_gfrc_tx_begin(&s->g_timer);
exynos4210_gfrc_restart(s);
exynos4210_gfrc_tx_commit(&s->g_timer);
break;
case G_TCON:
@ -1178,6 +1216,8 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
DPRINTF("global timer write to reg.g_tcon %llx\n", value);
exynos4210_gfrc_tx_begin(&s->g_timer);
/* Start FRC if transition from disabled to enabled */
if ((value & G_TCON_TIMER_ENABLE) > (old_val &
G_TCON_TIMER_ENABLE)) {
@ -1195,6 +1235,8 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
exynos4210_gfrc_restart(s);
}
}
exynos4210_gfrc_tx_commit(&s->g_timer);
break;
case G_INT_CSTAT:
@ -1428,8 +1470,8 @@ static void exynos4210_mct_init(Object *obj)
QEMUBH *bh[2];
/* Global timer */
bh[0] = qemu_bh_new(exynos4210_gfrc_event, s);
s->g_timer.ptimer_frc = ptimer_init_with_bh(bh[0], PTIMER_POLICY_DEFAULT);
s->g_timer.ptimer_frc = ptimer_init(exynos4210_gfrc_event, s,
PTIMER_POLICY_DEFAULT);
memset(&s->g_timer.reg, 0, sizeof(struct gregs));
/* Local timers */