hw/timer: fix reset/default value for register SYSTIMER_CONF on ESP targets
* Fixes https://github.com/espressif/qemu/issues/120
This commit is contained in:
@@ -20,13 +20,20 @@ static uint64_t esp32c3_systimer_read(void *opaque, hwaddr addr, unsigned int si
|
||||
uint64_t r = 0;
|
||||
|
||||
switch (addr) {
|
||||
case A_SYSTIMER_CONF:
|
||||
/* On the C3, bit 27 is always 0, bit 25 is always high */
|
||||
r = class->parent_systimer_read(opaque, addr, size);
|
||||
r &= ~BIT(27);
|
||||
r |= BIT(25);
|
||||
break;
|
||||
|
||||
case A_SYSTIMER_REAL_TARGET0_LO:
|
||||
case A_SYSTIMER_REAL_TARGET0_HI:
|
||||
case A_SYSTIMER_REAL_TARGET1_LO:
|
||||
case A_SYSTIMER_REAL_TARGET1_HI:
|
||||
case A_SYSTIMER_REAL_TARGET2_LO:
|
||||
case A_SYSTIMER_REAL_TARGET2_HI:
|
||||
/* These registers are not supported on the C3 hardware, so nothing! */
|
||||
/* These registers are not supported on the C3 hardware, do nothing! */
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
+19
-3
@@ -381,8 +381,10 @@ static void esp_systimer_conf_set(ESPSysTimerState *s, uint64_t value)
|
||||
}
|
||||
s->counter[0].enabled = (value & R_SYSTIMER_CONF_TIMER_UNIT0_WORK_EN_MASK) ? 1 : 0;
|
||||
s->counter[1].enabled = (value & R_SYSTIMER_CONF_TIMER_UNIT1_WORK_EN_MASK) ? 1 : 0;
|
||||
s->counter[0].enabled_on_stall = (value & R_SYSTIMER_CONF_TIMER_UNIT0_CORE0_STALL_EN_MASK) ? 1 : 0;
|
||||
s->counter[1].enabled_on_stall = (value & R_SYSTIMER_CONF_TIMER_UNIT1_CORE0_STALL_EN_MASK) ? 1 : 0;
|
||||
s->counter[0].core0_stall_en = (value & R_SYSTIMER_CONF_TIMER_UNIT0_CORE0_STALL_EN_MASK) ? 1 : 0;
|
||||
s->counter[1].core0_stall_en = (value & R_SYSTIMER_CONF_TIMER_UNIT1_CORE0_STALL_EN_MASK) ? 1 : 0;
|
||||
s->counter[0].core1_stall_en = (value & R_SYSTIMER_CONF_TIMER_UNIT0_CORE1_STALL_EN_MASK) ? 1 : 0;
|
||||
s->counter[1].core1_stall_en = (value & R_SYSTIMER_CONF_TIMER_UNIT1_CORE1_STALL_EN_MASK) ? 1 : 0;
|
||||
|
||||
/* If the state of the counter changed while one of the comparator depends on it, reload it */
|
||||
for (int i = 0; i < ESP_SYSTIMER_COMP_COUNT; i++) {
|
||||
@@ -558,10 +560,22 @@ static void esp_systimer_cb(void* opaque)
|
||||
}
|
||||
|
||||
|
||||
static void esp_systimer_default_conf(ESPSysTimerState *s)
|
||||
{
|
||||
/* According to the TRM, on dual-core targets, counter 1 stalls with core 1 */
|
||||
s->counter[1].core0_stall_en = true;
|
||||
s->counter[1].core1_stall_en = true;
|
||||
/* Counter 0 is marked as enabled (no comparator enabled though) */
|
||||
s->counter[0].enabled = true;
|
||||
s->conf = R_SYSTIMER_CONF_TIMER_UNIT0_WORK_EN_MASK |
|
||||
R_SYSTIMER_CONF_TIMER_UNIT1_CORE0_STALL_EN_MASK |
|
||||
R_SYSTIMER_CONF_TIMER_UNIT1_CORE1_STALL_EN_MASK;
|
||||
}
|
||||
|
||||
|
||||
static void esp_systimer_reset(DeviceState* ts)
|
||||
{
|
||||
ESPSysTimerState *s = ESP_SYSTIMER(ts);
|
||||
s->conf = 0;
|
||||
for (int i = 0; i < ESP_SYSTIMER_COMP_COUNT; i++) {
|
||||
ESPSysTimerComp* comp = &s->comparators[i];
|
||||
QEMUTimer qtimer = comp->qtimer;
|
||||
@@ -579,6 +593,7 @@ static void esp_systimer_reset(DeviceState* ts)
|
||||
comp->irq = irq;
|
||||
comp->systimer = s;
|
||||
}
|
||||
esp_systimer_default_conf(s);
|
||||
}
|
||||
|
||||
|
||||
@@ -602,6 +617,7 @@ static void esp_systimer_init(Object *obj)
|
||||
sysbus_init_irq(sbd, &s->comparators[i].irq);
|
||||
timer_init_ns(&s->comparators[i].qtimer, QEMU_CLOCK_VIRTUAL, esp_systimer_cb, &s->comparators[i]);
|
||||
}
|
||||
esp_systimer_default_conf(s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -69,7 +69,8 @@ static inline void systimer_set_reg(uint64_t* reg, uint64_t value, uint64_t mask
|
||||
typedef struct {
|
||||
bool enabled;
|
||||
/* Enabled on CPU stall */
|
||||
bool enabled_on_stall;
|
||||
bool core0_stall_en;
|
||||
bool core1_stall_en;
|
||||
uint64_t value; // Internal counter that should be updated as often as possible
|
||||
uint64_t toload; // Counter that can be loaded by the guest program
|
||||
uint64_t flushed; // Mirror of the internal counter that can be seen by the guest program
|
||||
|
||||
Reference in New Issue
Block a user