mirror of
https://gitlab.com/qemu-project/opensbi.git
synced 2025-11-10 05:37:55 +08:00
lib: utils/timer: Expose timer update function
Exposing the ACLINT timer update APIs so the user can update the mtimer after waking up from the non-retentive suspend. Reviewed-by: Cyan Yang <cyan.yang@sifive.com> Reviewed-by: Anup Patel <anup@brainfault.org> Signed-off-by: Nick Hu <nick.hu@sifive.com> Link: https://lore.kernel.org/r/20251020-cache-upstream-v7-10-69a132447d8a@sifive.com Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
@ -42,6 +42,11 @@ struct aclint_mtimer_data {
|
||||
void (*time_wr)(bool timecmp, u64 value, volatile u64 *addr);
|
||||
};
|
||||
|
||||
struct aclint_mtimer_data *aclint_get_mtimer_data(void);
|
||||
|
||||
void aclint_mtimer_update(struct aclint_mtimer_data *mt,
|
||||
struct aclint_mtimer_data *ref);
|
||||
|
||||
void aclint_mtimer_sync(struct aclint_mtimer_data *mt);
|
||||
|
||||
void aclint_mtimer_set_reference(struct aclint_mtimer_data *mt,
|
||||
|
||||
@ -109,10 +109,34 @@ static struct sbi_timer_device mtimer = {
|
||||
.timer_event_stop = mtimer_event_stop
|
||||
};
|
||||
|
||||
void aclint_mtimer_sync(struct aclint_mtimer_data *mt)
|
||||
struct aclint_mtimer_data *aclint_get_mtimer_data(void)
|
||||
{
|
||||
return mtimer_get_hart_data_ptr(sbi_scratch_thishart_ptr());
|
||||
}
|
||||
|
||||
void aclint_mtimer_update(struct aclint_mtimer_data *mt,
|
||||
struct aclint_mtimer_data *ref)
|
||||
{
|
||||
u64 v1, v2, mv, delta;
|
||||
u64 *mt_time_val, *ref_time_val;
|
||||
|
||||
if (!mt || !ref || !mt->time_rd || !mt->time_wr || !ref->time_rd)
|
||||
return;
|
||||
|
||||
mt_time_val = (void *)mt->mtime_addr;
|
||||
ref_time_val = (void *)ref->mtime_addr;
|
||||
if (!atomic_raw_xchg_ulong(&mt->time_delta_computed, 1)) {
|
||||
v1 = mt->time_rd(mt_time_val);
|
||||
mv = ref->time_rd(ref_time_val);
|
||||
v2 = mt->time_rd(mt_time_val);
|
||||
delta = mv - ((v1 / 2) + (v2 / 2));
|
||||
mt->time_wr(false, mt->time_rd(mt_time_val) + delta,
|
||||
mt_time_val);
|
||||
}
|
||||
}
|
||||
|
||||
void aclint_mtimer_sync(struct aclint_mtimer_data *mt)
|
||||
{
|
||||
struct aclint_mtimer_data *reference;
|
||||
|
||||
/* Sync-up non-shared MTIME if reference is available */
|
||||
@ -120,17 +144,7 @@ void aclint_mtimer_sync(struct aclint_mtimer_data *mt)
|
||||
return;
|
||||
|
||||
reference = mt->time_delta_reference;
|
||||
mt_time_val = (void *)mt->mtime_addr;
|
||||
ref_time_val = (void *)reference->mtime_addr;
|
||||
if (!atomic_raw_xchg_ulong(&mt->time_delta_computed, 1)) {
|
||||
v1 = mt->time_rd(mt_time_val);
|
||||
mv = reference->time_rd(ref_time_val);
|
||||
v2 = mt->time_rd(mt_time_val);
|
||||
delta = mv - ((v1 / 2) + (v2 / 2));
|
||||
mt->time_wr(false, mt->time_rd(mt_time_val) + delta,
|
||||
mt_time_val);
|
||||
}
|
||||
|
||||
aclint_mtimer_update(mt, reference);
|
||||
}
|
||||
|
||||
void aclint_mtimer_set_reference(struct aclint_mtimer_data *mt,
|
||||
|
||||
Reference in New Issue
Block a user