aboutsummaryrefslogtreecommitdiff
path: root/hw/riscv/sifive_clint.c
diff options
context:
space:
mode:
authorBin Meng <bin.meng@windriver.com>2020-09-01 09:39:10 +0800
committerAlistair Francis <alistair.francis@wdc.com>2020-09-09 15:54:19 -0700
commita47ef6e93ab2ca1db8d5ecb61fda3c41f926a26b (patch)
tree00c66845ba4693643cd3bd41f190908b781543fd /hw/riscv/sifive_clint.c
parentce908a2f6f6d6e1d8ede485ee3f9f7d36ee3533c (diff)
downloadqemu-a47ef6e93ab2ca1db8d5ecb61fda3c41f926a26b.zip
qemu-a47ef6e93ab2ca1db8d5ecb61fda3c41f926a26b.tar.gz
qemu-a47ef6e93ab2ca1db8d5ecb61fda3c41f926a26b.tar.bz2
hw/riscv: clint: Avoid using hard-coded timebase frequency
At present the CLINT timestamp is using a hard-coded timebase frequency value SIFIVE_CLINT_TIMEBASE_FREQ. This might not be true for all boards. Add a new 'timebase-freq' property to the CLINT device, and update various functions to accept this as a parameter. Signed-off-by: Bin Meng <bin.meng@windriver.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-Id: <1598924352-89526-16-git-send-email-bmeng.cn@gmail.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Diffstat (limited to 'hw/riscv/sifive_clint.c')
-rw-r--r--hw/riscv/sifive_clint.c26
1 files changed, 15 insertions, 11 deletions
diff --git a/hw/riscv/sifive_clint.c b/hw/riscv/sifive_clint.c
index 15e13d5..fa1ddf2 100644
--- a/hw/riscv/sifive_clint.c
+++ b/hw/riscv/sifive_clint.c
@@ -29,22 +29,23 @@
#include "hw/riscv/sifive_clint.h"
#include "qemu/timer.h"
-static uint64_t cpu_riscv_read_rtc(void)
+static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
{
return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
- SIFIVE_CLINT_TIMEBASE_FREQ, NANOSECONDS_PER_SECOND);
+ timebase_freq, NANOSECONDS_PER_SECOND);
}
/*
* Called when timecmp is written to update the QEMU timer or immediately
* trigger timer interrupt if mtimecmp <= current timer value.
*/
-static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value)
+static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value,
+ uint32_t timebase_freq)
{
uint64_t next;
uint64_t diff;
- uint64_t rtc_r = cpu_riscv_read_rtc();
+ uint64_t rtc_r = cpu_riscv_read_rtc(timebase_freq);
cpu->env.timecmp = value;
if (cpu->env.timecmp <= rtc_r) {
@@ -59,7 +60,7 @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value)
diff = cpu->env.timecmp - rtc_r;
/* back to ns (note args switched in muldiv64) */
next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
- muldiv64(diff, NANOSECONDS_PER_SECOND, SIFIVE_CLINT_TIMEBASE_FREQ);
+ muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq);
timer_mod(cpu->env.timer, next);
}
@@ -112,10 +113,10 @@ static uint64_t sifive_clint_read(void *opaque, hwaddr addr, unsigned size)
}
} else if (addr == clint->time_base) {
/* time_lo */
- return cpu_riscv_read_rtc() & 0xFFFFFFFF;
+ return cpu_riscv_read_rtc(clint->timebase_freq) & 0xFFFFFFFF;
} else if (addr == clint->time_base + 4) {
/* time_hi */
- return (cpu_riscv_read_rtc() >> 32) & 0xFFFFFFFF;
+ return (cpu_riscv_read_rtc(clint->timebase_freq) >> 32) & 0xFFFFFFFF;
}
error_report("clint: invalid read: %08x", (uint32_t)addr);
@@ -153,13 +154,13 @@ static void sifive_clint_write(void *opaque, hwaddr addr, uint64_t value,
/* timecmp_lo */
uint64_t timecmp_hi = env->timecmp >> 32;
sifive_clint_write_timecmp(RISCV_CPU(cpu),
- timecmp_hi << 32 | (value & 0xFFFFFFFF));
+ timecmp_hi << 32 | (value & 0xFFFFFFFF), clint->timebase_freq);
return;
} else if ((addr & 0x7) == 4) {
/* timecmp_hi */
uint64_t timecmp_lo = env->timecmp;
sifive_clint_write_timecmp(RISCV_CPU(cpu),
- value << 32 | (timecmp_lo & 0xFFFFFFFF));
+ value << 32 | (timecmp_lo & 0xFFFFFFFF), clint->timebase_freq);
} else {
error_report("clint: invalid timecmp write: %08x", (uint32_t)addr);
}
@@ -194,6 +195,7 @@ static Property sifive_clint_properties[] = {
DEFINE_PROP_UINT32("timecmp-base", SiFiveCLINTState, timecmp_base, 0),
DEFINE_PROP_UINT32("time-base", SiFiveCLINTState, time_base, 0),
DEFINE_PROP_UINT32("aperture-size", SiFiveCLINTState, aperture_size, 0),
+ DEFINE_PROP_UINT32("timebase-freq", SiFiveCLINTState, timebase_freq, 0),
DEFINE_PROP_END_OF_LIST(),
};
@@ -232,7 +234,8 @@ type_init(sifive_clint_register_types)
*/
DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
uint32_t hartid_base, uint32_t num_harts, uint32_t sip_base,
- uint32_t timecmp_base, uint32_t time_base, bool provide_rdtime)
+ uint32_t timecmp_base, uint32_t time_base, uint32_t timebase_freq,
+ bool provide_rdtime)
{
int i;
for (i = 0; i < num_harts; i++) {
@@ -242,7 +245,7 @@ DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
continue;
}
if (provide_rdtime) {
- riscv_cpu_set_rdtime_fn(env, cpu_riscv_read_rtc);
+ riscv_cpu_set_rdtime_fn(env, cpu_riscv_read_rtc, timebase_freq);
}
env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
&sifive_clint_timer_cb, cpu);
@@ -256,6 +259,7 @@ DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
qdev_prop_set_uint32(dev, "timecmp-base", timecmp_base);
qdev_prop_set_uint32(dev, "time-base", time_base);
qdev_prop_set_uint32(dev, "aperture-size", size);
+ qdev_prop_set_uint32(dev, "timebase-freq", timebase_freq);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
return dev;