aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/riscv/microchip_pfsoc.c6
-rw-r--r--hw/riscv/sifive_clint.c26
-rw-r--r--hw/riscv/sifive_e.c3
-rw-r--r--hw/riscv/sifive_u.c3
-rw-r--r--hw/riscv/spike.c3
-rw-r--r--hw/riscv/virt.c3
6 files changed, 28 insertions, 16 deletions
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
index 11ebdd1aa8..da6bd295ce 100644
--- a/hw/riscv/microchip_pfsoc.c
+++ b/hw/riscv/microchip_pfsoc.c
@@ -60,6 +60,9 @@
#define BIOS_FILENAME "hss.bin"
#define RESET_VECTOR 0x20220000
+/* CLINT timebase frequency */
+#define CLINT_TIMEBASE_FREQ 1000000
+
/* GEM version */
#define GEM_REVISION 0x0107010c
@@ -187,7 +190,8 @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp)
/* CLINT */
sifive_clint_create(memmap[MICROCHIP_PFSOC_CLINT].base,
memmap[MICROCHIP_PFSOC_CLINT].size, 0, ms->smp.cpus,
- SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, false);
+ SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
+ CLINT_TIMEBASE_FREQ, false);
/* L2 cache controller */
create_unimplemented_device("microchip.pfsoc.l2cc",
diff --git a/hw/riscv/sifive_clint.c b/hw/riscv/sifive_clint.c
index 15e13d5f7a..fa1ddf2ccd 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;
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
index cd7560d8ec..36ccfb2071 100644
--- a/hw/riscv/sifive_e.c
+++ b/hw/riscv/sifive_e.c
@@ -213,7 +213,8 @@ static void sifive_e_soc_realize(DeviceState *dev, Error **errp)
memmap[SIFIVE_E_PLIC].size);
sifive_clint_create(memmap[SIFIVE_E_CLINT].base,
memmap[SIFIVE_E_CLINT].size, 0, ms->smp.cpus,
- SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, false);
+ SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
+ SIFIVE_CLINT_TIMEBASE_FREQ, false);
create_unimplemented_device("riscv.sifive.e.aon",
memmap[SIFIVE_E_AON].base, memmap[SIFIVE_E_AON].size);
sifive_e_prci_create(memmap[SIFIVE_E_PRCI].base);
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 404d5e6918..2bc3992989 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -706,7 +706,8 @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
serial_hd(1), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_U_UART1_IRQ));
sifive_clint_create(memmap[SIFIVE_U_CLINT].base,
memmap[SIFIVE_U_CLINT].size, 0, ms->smp.cpus,
- SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, false);
+ SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
+ SIFIVE_CLINT_TIMEBASE_FREQ, false);
if (!sysbus_realize(SYS_BUS_DEVICE(&s->prci), errp)) {
return;
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index 56f5fe73c7..b54a396107 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -242,7 +242,8 @@ static void spike_board_init(MachineState *machine)
sifive_clint_create(
memmap[SPIKE_CLINT].base + i * memmap[SPIKE_CLINT].size,
memmap[SPIKE_CLINT].size, base_hartid, hart_count,
- SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, false);
+ SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
+ SIFIVE_CLINT_TIMEBASE_FREQ, false);
}
/* register system main memory (actual RAM) */
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 6fca513ec9..c67a910e48 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -541,7 +541,8 @@ static void virt_machine_init(MachineState *machine)
sifive_clint_create(
memmap[VIRT_CLINT].base + i * memmap[VIRT_CLINT].size,
memmap[VIRT_CLINT].size, base_hartid, hart_count,
- SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, true);
+ SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
+ SIFIVE_CLINT_TIMEBASE_FREQ, true);
/* Per-socket PLIC hart topology configuration string */
plic_hart_config_len =