hw/timer/arm_mptimer.c: Switch to transaction-based ptimer API
Switch the arm_mptimer.c code away from bottom-half based ptimers to the new transaction-based ptimer API. This just requires adding begin/commit calls around the various places that modify the ptimer state, and using the new ptimer_init() function to create the timer. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191008171740.9679-8-peter.maydell@linaro.org
This commit is contained in:
parent
827c421492
commit
581b088035
@ -27,7 +27,6 @@
|
|||||||
#include "hw/timer/arm_mptimer.h"
|
#include "hw/timer/arm_mptimer.h"
|
||||||
#include "migration/vmstate.h"
|
#include "migration/vmstate.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu/main-loop.h"
|
|
||||||
#include "qemu/module.h"
|
#include "qemu/module.h"
|
||||||
#include "hw/core/cpu.h"
|
#include "hw/core/cpu.h"
|
||||||
|
|
||||||
@ -65,6 +64,7 @@ static inline uint32_t timerblock_scale(uint32_t control)
|
|||||||
return (((control >> 8) & 0xff) + 1) * 10;
|
return (((control >> 8) & 0xff) + 1) * 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Must be called within a ptimer transaction block */
|
||||||
static inline void timerblock_set_count(struct ptimer_state *timer,
|
static inline void timerblock_set_count(struct ptimer_state *timer,
|
||||||
uint32_t control, uint64_t *count)
|
uint32_t control, uint64_t *count)
|
||||||
{
|
{
|
||||||
@ -77,6 +77,7 @@ static inline void timerblock_set_count(struct ptimer_state *timer,
|
|||||||
ptimer_set_count(timer, *count);
|
ptimer_set_count(timer, *count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Must be called within a ptimer transaction block */
|
||||||
static inline void timerblock_run(struct ptimer_state *timer,
|
static inline void timerblock_run(struct ptimer_state *timer,
|
||||||
uint32_t control, uint32_t load)
|
uint32_t control, uint32_t load)
|
||||||
{
|
{
|
||||||
@ -124,6 +125,7 @@ static void timerblock_write(void *opaque, hwaddr addr,
|
|||||||
uint32_t control = tb->control;
|
uint32_t control = tb->control;
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case 0: /* Load */
|
case 0: /* Load */
|
||||||
|
ptimer_transaction_begin(tb->timer);
|
||||||
/* Setting load to 0 stops the timer without doing the tick if
|
/* Setting load to 0 stops the timer without doing the tick if
|
||||||
* prescaler = 0.
|
* prescaler = 0.
|
||||||
*/
|
*/
|
||||||
@ -132,8 +134,10 @@ static void timerblock_write(void *opaque, hwaddr addr,
|
|||||||
}
|
}
|
||||||
ptimer_set_limit(tb->timer, value, 1);
|
ptimer_set_limit(tb->timer, value, 1);
|
||||||
timerblock_run(tb->timer, control, value);
|
timerblock_run(tb->timer, control, value);
|
||||||
|
ptimer_transaction_commit(tb->timer);
|
||||||
break;
|
break;
|
||||||
case 4: /* Counter. */
|
case 4: /* Counter. */
|
||||||
|
ptimer_transaction_begin(tb->timer);
|
||||||
/* Setting counter to 0 stops the one-shot timer, or periodic with
|
/* Setting counter to 0 stops the one-shot timer, or periodic with
|
||||||
* load = 0, without doing the tick if prescaler = 0.
|
* load = 0, without doing the tick if prescaler = 0.
|
||||||
*/
|
*/
|
||||||
@ -143,8 +147,10 @@ static void timerblock_write(void *opaque, hwaddr addr,
|
|||||||
}
|
}
|
||||||
timerblock_set_count(tb->timer, control, &value);
|
timerblock_set_count(tb->timer, control, &value);
|
||||||
timerblock_run(tb->timer, control, value);
|
timerblock_run(tb->timer, control, value);
|
||||||
|
ptimer_transaction_commit(tb->timer);
|
||||||
break;
|
break;
|
||||||
case 8: /* Control. */
|
case 8: /* Control. */
|
||||||
|
ptimer_transaction_begin(tb->timer);
|
||||||
if ((control & 3) != (value & 3)) {
|
if ((control & 3) != (value & 3)) {
|
||||||
ptimer_stop(tb->timer);
|
ptimer_stop(tb->timer);
|
||||||
}
|
}
|
||||||
@ -160,6 +166,7 @@ static void timerblock_write(void *opaque, hwaddr addr,
|
|||||||
timerblock_run(tb->timer, value, count);
|
timerblock_run(tb->timer, value, count);
|
||||||
}
|
}
|
||||||
tb->control = value;
|
tb->control = value;
|
||||||
|
ptimer_transaction_commit(tb->timer);
|
||||||
break;
|
break;
|
||||||
case 12: /* Interrupt status. */
|
case 12: /* Interrupt status. */
|
||||||
tb->status &= ~value;
|
tb->status &= ~value;
|
||||||
@ -212,9 +219,11 @@ static void timerblock_reset(TimerBlock *tb)
|
|||||||
tb->control = 0;
|
tb->control = 0;
|
||||||
tb->status = 0;
|
tb->status = 0;
|
||||||
if (tb->timer) {
|
if (tb->timer) {
|
||||||
|
ptimer_transaction_begin(tb->timer);
|
||||||
ptimer_stop(tb->timer);
|
ptimer_stop(tb->timer);
|
||||||
ptimer_set_limit(tb->timer, 0, 1);
|
ptimer_set_limit(tb->timer, 0, 1);
|
||||||
ptimer_set_period(tb->timer, timerblock_scale(0));
|
ptimer_set_period(tb->timer, timerblock_scale(0));
|
||||||
|
ptimer_transaction_commit(tb->timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,8 +269,7 @@ static void arm_mptimer_realize(DeviceState *dev, Error **errp)
|
|||||||
*/
|
*/
|
||||||
for (i = 0; i < s->num_cpu; i++) {
|
for (i = 0; i < s->num_cpu; i++) {
|
||||||
TimerBlock *tb = &s->timerblock[i];
|
TimerBlock *tb = &s->timerblock[i];
|
||||||
QEMUBH *bh = qemu_bh_new(timerblock_tick, tb);
|
tb->timer = ptimer_init(timerblock_tick, tb, PTIMER_POLICY);
|
||||||
tb->timer = ptimer_init_with_bh(bh, PTIMER_POLICY);
|
|
||||||
sysbus_init_irq(sbd, &tb->irq);
|
sysbus_init_irq(sbd, &tb->irq);
|
||||||
memory_region_init_io(&tb->iomem, OBJECT(s), &timerblock_ops, tb,
|
memory_region_init_io(&tb->iomem, OBJECT(s), &timerblock_ops, tb,
|
||||||
"arm_mptimer_timerblock", 0x20);
|
"arm_mptimer_timerblock", 0x20);
|
||||||
|
Loading…
Reference in New Issue
Block a user