Skip to content

Commit e0bca2c

Browse files
committed
[ot] hw/opentitan: ot_aon_timer: Make wakeup timer 64 bits
For earlgrey-1.0.0, OpenTitan's aon_timer has been updated so that it's wakeup timer is now a 64-bit counter rather than a 32-bit counter (whereas the watchdog timer remains 32-bit). This requires the implementation of register mapping changes with each wakeup count / threshold register now having a HI/LO counterpart. Signed-off-by: Alex Jones <alex.jones@lowrisc.org>
1 parent 3059172 commit e0bca2c

File tree

1 file changed

+53
-33
lines changed

1 file changed

+53
-33
lines changed

hw/opentitan/ot_aon_timer.c

Lines changed: 53 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -47,21 +47,23 @@ REG32(ALERT_TEST, 0x00u)
4747
REG32(WKUP_CTRL, 0x04u)
4848
FIELD(WKUP_CTRL, ENABLE, 0u, 1u)
4949
FIELD(WKUP_CTRL, PRESCALER, 1u, 12u)
50-
REG32(WKUP_THOLD, 0x08)
51-
REG32(WKUP_COUNT, 0x0cu)
52-
REG32(WDOG_REGWEN, 0x10u)
50+
REG32(WKUP_THOLD_HI, 0x08u)
51+
REG32(WKUP_THOLD_LO, 0x0cu)
52+
REG32(WKUP_COUNT_HI, 0x10u)
53+
REG32(WKUP_COUNT_LO, 0x14u)
54+
REG32(WDOG_REGWEN, 0x18u)
5355
FIELD(WDOG_REGWEN, REGWEN, 0u, 1u)
54-
REG32(WDOG_CTRL, 0x14u)
56+
REG32(WDOG_CTRL, 0x1cu)
5557
FIELD(WDOG_CTRL, ENABLE, 0u, 1u)
56-
FIELD(WDOG_CTRL, PAUSE_IN_SLEEP, 0u, 1u)
57-
REG32(WDOG_BARK_THOLD, 0x18u)
58-
REG32(WDOG_BITE_THOLD, 0x1cu)
59-
REG32(WDOG_COUNT, 0x20u)
60-
REG32(INTR_STATE, 0x24u)
58+
FIELD(WDOG_CTRL, PAUSE_IN_SLEEP, 1u, 1u)
59+
REG32(WDOG_BARK_THOLD, 0x20u)
60+
REG32(WDOG_BITE_THOLD, 0x24u)
61+
REG32(WDOG_COUNT, 0x28u)
62+
REG32(INTR_STATE, 0x2cu)
6163
SHARED_FIELD(INTR_WKUP_TIMER_EXPIRED, 0u, 1u)
6264
SHARED_FIELD(INTR_WDOG_TIMER_BARK, 1u, 1u)
63-
REG32(INTR_TEST, 0x28u)
64-
REG32(WKUP_CAUSE, 0x2cu)
65+
REG32(INTR_TEST, 0x30u)
66+
REG32(WKUP_CAUSE, 0x34u)
6567
FIELD(WKUP_CAUSE, CAUSE, 0u, 1u)
6668
/* clang-format on */
6769

@@ -80,8 +82,10 @@ static const char REG_NAMES[REGS_COUNT][20u] = {
8082
/* clang-format off */
8183
REG_NAME_ENTRY(ALERT_TEST),
8284
REG_NAME_ENTRY(WKUP_CTRL),
83-
REG_NAME_ENTRY(WKUP_THOLD),
84-
REG_NAME_ENTRY(WKUP_COUNT),
85+
REG_NAME_ENTRY(WKUP_THOLD_HI),
86+
REG_NAME_ENTRY(WKUP_THOLD_LO),
87+
REG_NAME_ENTRY(WKUP_COUNT_HI),
88+
REG_NAME_ENTRY(WKUP_COUNT_LO),
8589
REG_NAME_ENTRY(WDOG_REGWEN),
8690
REG_NAME_ENTRY(WDOG_CTRL),
8791
REG_NAME_ENTRY(WDOG_BARK_THOLD),
@@ -119,36 +123,40 @@ struct OtAonTimerState {
119123
uint32_t pclk;
120124
};
121125

122-
static uint32_t
126+
static uint64_t
123127
ot_aon_timer_ns_to_ticks(OtAonTimerState *s, uint32_t prescaler, int64_t ns)
124128
{
125129
uint64_t ticks = muldiv64((uint64_t)ns, s->pclk, NANOSECONDS_PER_SECOND);
126-
return (uint32_t)(ticks / (prescaler + 1u));
130+
return ticks / (prescaler + 1u);
127131
}
128132

129133
static int64_t
130-
ot_aon_timer_ticks_to_ns(OtAonTimerState *s, uint32_t prescaler, uint32_t ticks)
134+
ot_aon_timer_ticks_to_ns(OtAonTimerState *s, uint32_t prescaler, uint64_t ticks)
131135
{
132-
uint64_t ns = muldiv64((uint64_t)ticks * (prescaler + 1u),
133-
NANOSECONDS_PER_SECOND, s->pclk);
136+
uint64_t ns =
137+
muldiv64(ticks * (prescaler + 1u), NANOSECONDS_PER_SECOND, s->pclk);
134138
if (ns > INT64_MAX) {
135139
return INT64_MAX;
136140
}
137141
return (int64_t)ns;
138142
}
139143

140-
static uint32_t ot_aon_timer_get_wkup_count(OtAonTimerState *s, uint64_t now)
144+
static uint64_t ot_aon_timer_get_wkup_count(OtAonTimerState *s, uint64_t now)
141145
{
142146
uint32_t prescaler = FIELD_EX32(s->regs[R_WKUP_CTRL], WKUP_CTRL, PRESCALER);
143-
return s->regs[R_WKUP_COUNT] +
147+
uint64_t wkup_count =
148+
((uint64_t)s->regs[R_WKUP_COUNT_HI] << 32u) | s->regs[R_WKUP_COUNT_LO];
149+
return wkup_count +
144150
ot_aon_timer_ns_to_ticks(s, prescaler,
145151
(int64_t)(now - s->wkup_origin_ns));
146152
}
147153

148154
static uint32_t ot_aon_timer_get_wdog_count(OtAonTimerState *s, uint64_t now)
149155
{
150156
return s->regs[R_WDOG_COUNT] +
151-
ot_aon_timer_ns_to_ticks(s, 0u, (int64_t)(now - s->wdog_origin_ns));
157+
(uint32_t)
158+
ot_aon_timer_ns_to_ticks(s, 0u,
159+
(int64_t)(now - s->wdog_origin_ns));
152160
}
153161

154162
static int64_t ot_aon_timer_compute_next_timeout(OtAonTimerState *s,
@@ -192,7 +200,6 @@ static void ot_aon_timer_update_irqs(OtAonTimerState *s)
192200
{
193201
bool wkup = (bool)(s->regs[R_INTR_STATE] & INTR_WKUP_TIMER_EXPIRED_MASK);
194202
bool bark = (bool)(s->regs[R_INTR_STATE] & INTR_WDOG_TIMER_BARK_MASK);
195-
196203
trace_ot_aon_timer_irqs(s->ot_id, wkup, bark, s->wdog_bite);
197204

198205
ibex_irq_set(&s->irq_wkup, wkup);
@@ -218,8 +225,9 @@ static void ot_aon_timer_rearm_wkup(OtAonTimerState *s, bool reset_origin)
218225
return;
219226
}
220227

221-
uint32_t count = ot_aon_timer_get_wkup_count(s, now);
222-
uint32_t threshold = s->regs[R_WKUP_THOLD];
228+
uint64_t count = ot_aon_timer_get_wkup_count(s, now);
229+
uint64_t threshold =
230+
((uint64_t)s->regs[R_WKUP_THOLD_HI] << 32u) | s->regs[R_WKUP_THOLD_LO];
223231

224232
if (count >= threshold) {
225233
s->regs[R_INTR_STATE] |= INTR_WKUP_TIMER_EXPIRED_MASK;
@@ -309,7 +317,8 @@ static uint64_t ot_aon_timer_read(void *opaque, hwaddr addr, unsigned size)
309317
hwaddr reg = R32_OFF(addr);
310318
switch (reg) {
311319
case R_WKUP_CTRL:
312-
case R_WKUP_THOLD:
320+
case R_WKUP_THOLD_HI:
321+
case R_WKUP_THOLD_LO:
313322
case R_WDOG_REGWEN:
314323
case R_WDOG_CTRL:
315324
case R_WDOG_BARK_THOLD:
@@ -318,11 +327,18 @@ static uint64_t ot_aon_timer_read(void *opaque, hwaddr addr, unsigned size)
318327
case R_WKUP_CAUSE:
319328
val32 = s->regs[reg];
320329
break;
321-
case R_WKUP_COUNT: {
330+
case R_WKUP_COUNT_HI: {
331+
uint64_t now = ot_aon_timer_is_wkup_enabled(s) ?
332+
qemu_clock_get_ns(OT_VIRTUAL_CLOCK) :
333+
s->wkup_origin_ns;
334+
val32 = (uint32_t)(ot_aon_timer_get_wkup_count(s, now) >> 32u);
335+
break;
336+
}
337+
case R_WKUP_COUNT_LO: {
322338
uint64_t now = ot_aon_timer_is_wkup_enabled(s) ?
323339
qemu_clock_get_ns(OT_VIRTUAL_CLOCK) :
324340
s->wkup_origin_ns;
325-
val32 = ot_aon_timer_get_wkup_count(s, now);
341+
val32 = (uint32_t)ot_aon_timer_get_wkup_count(s, now);
326342
break;
327343
}
328344
case R_WDOG_COUNT: {
@@ -384,19 +400,23 @@ static void ot_aon_timer_write(void *opaque, hwaddr addr, uint64_t value,
384400
/* stop timer */
385401
timer_del(s->wkup_timer);
386402
/* save current count */
387-
uint32_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK);
388-
s->regs[R_WKUP_COUNT] = ot_aon_timer_get_wkup_count(s, now);
403+
uint64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK);
404+
uint64_t count = ot_aon_timer_get_wkup_count(s, now);
405+
s->regs[R_WKUP_COUNT_HI] = (uint32_t)(count >> 32u);
406+
s->regs[R_WKUP_COUNT_LO] = (uint32_t)count;
389407
s->wkup_origin_ns = now;
390408
}
391409
}
392410
break;
393411
}
394-
case R_WKUP_THOLD:
395-
s->regs[R_WKUP_THOLD] = val32;
412+
case R_WKUP_THOLD_HI:
413+
case R_WKUP_THOLD_LO:
414+
s->regs[reg] = val32;
396415
ot_aon_timer_rearm_wkup(s, false);
397416
break;
398-
case R_WKUP_COUNT:
399-
s->regs[R_WKUP_COUNT] = val32;
417+
case R_WKUP_COUNT_HI:
418+
case R_WKUP_COUNT_LO:
419+
s->regs[reg] = val32;
400420
ot_aon_timer_rearm_wkup(s, true);
401421
break;
402422
case R_WDOG_REGWEN:

0 commit comments

Comments
 (0)