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;
|
uint64_t r = 0;
|
||||||
|
|
||||||
switch (addr) {
|
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_LO:
|
||||||
case A_SYSTIMER_REAL_TARGET0_HI:
|
case A_SYSTIMER_REAL_TARGET0_HI:
|
||||||
case A_SYSTIMER_REAL_TARGET1_LO:
|
case A_SYSTIMER_REAL_TARGET1_LO:
|
||||||
case A_SYSTIMER_REAL_TARGET1_HI:
|
case A_SYSTIMER_REAL_TARGET1_HI:
|
||||||
case A_SYSTIMER_REAL_TARGET2_LO:
|
case A_SYSTIMER_REAL_TARGET2_LO:
|
||||||
case A_SYSTIMER_REAL_TARGET2_HI:
|
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;
|
break;
|
||||||
|
|
||||||
default:
|
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[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[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[0].core0_stall_en = (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[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 */
|
/* 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++) {
|
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)
|
static void esp_systimer_reset(DeviceState* ts)
|
||||||
{
|
{
|
||||||
ESPSysTimerState *s = ESP_SYSTIMER(ts);
|
ESPSysTimerState *s = ESP_SYSTIMER(ts);
|
||||||
s->conf = 0;
|
|
||||||
for (int i = 0; i < ESP_SYSTIMER_COMP_COUNT; i++) {
|
for (int i = 0; i < ESP_SYSTIMER_COMP_COUNT; i++) {
|
||||||
ESPSysTimerComp* comp = &s->comparators[i];
|
ESPSysTimerComp* comp = &s->comparators[i];
|
||||||
QEMUTimer qtimer = comp->qtimer;
|
QEMUTimer qtimer = comp->qtimer;
|
||||||
@@ -579,6 +593,7 @@ static void esp_systimer_reset(DeviceState* ts)
|
|||||||
comp->irq = irq;
|
comp->irq = irq;
|
||||||
comp->systimer = s;
|
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);
|
sysbus_init_irq(sbd, &s->comparators[i].irq);
|
||||||
timer_init_ns(&s->comparators[i].qtimer, QEMU_CLOCK_VIRTUAL, esp_systimer_cb, &s->comparators[i]);
|
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 {
|
typedef struct {
|
||||||
bool enabled;
|
bool enabled;
|
||||||
/* Enabled on CPU stall */
|
/* 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 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 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
|
uint64_t flushed; // Mirror of the internal counter that can be seen by the guest program
|
||||||
|
|||||||
Reference in New Issue
Block a user