138 lines
4.6 KiB
Diff
138 lines
4.6 KiB
Diff
|
|
From 4044284b230182cbaeb401bdb1b65dcbd11c7550 Mon Sep 17 00:00:00 2001
|
||
|
|
From: Xianglai Li <lixianglai@loongson.cn>
|
||
|
|
Date: Mon, 7 Apr 2025 18:59:42 +0800
|
||
|
|
Subject: [PATCH] hw/rtc: Fixed loongson rtc emulation errors
|
||
|
|
|
||
|
|
The expire time is sent to the timer only
|
||
|
|
when the expire Time is greater than 0 or
|
||
|
|
greater than now. Otherwise, the timer
|
||
|
|
will trigger interruption continuously.
|
||
|
|
|
||
|
|
Timer interrupts are sent using pulse functions.
|
||
|
|
|
||
|
|
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||
|
|
---
|
||
|
|
hw/loongarch/virt.c | 9 +++++++--
|
||
|
|
hw/rtc/ls7a_rtc.c | 22 +++++++++++++---------
|
||
|
|
2 files changed, 20 insertions(+), 11 deletions(-)
|
||
|
|
|
||
|
|
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||
|
|
index 0c24e632bb..ce026a4c3c 100644
|
||
|
|
--- a/hw/loongarch/virt.c
|
||
|
|
+++ b/hw/loongarch/virt.c
|
||
|
|
@@ -51,6 +51,11 @@
|
||
|
|
#include "qemu/error-report.h"
|
||
|
|
#include "qemu/guest-random.h"
|
||
|
|
|
||
|
|
+#define FDT_IRQ_FLAGS_EDGE_LO_HI 1
|
||
|
|
+#define FDT_IRQ_FLAGS_EDGE_HI_LO 2
|
||
|
|
+#define FDT_IRQ_FLAGS_LEVEL_HI 4
|
||
|
|
+#define FDT_IRQ_FLAGS_LEVEL_LO 8
|
||
|
|
+
|
||
|
|
static bool virt_is_veiointc_enabled(LoongArchVirtMachineState *lvms)
|
||
|
|
{
|
||
|
|
if (lvms->veiointc == ON_OFF_AUTO_OFF) {
|
||
|
|
@@ -275,7 +280,7 @@ static void fdt_add_rtc_node(LoongArchVirtMachineState *lvms,
|
||
|
|
"loongson,ls7a-rtc");
|
||
|
|
qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg", 2, base, 2, size);
|
||
|
|
qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
|
||
|
|
- VIRT_RTC_IRQ - VIRT_GSI_BASE , 0x4);
|
||
|
|
+ VIRT_RTC_IRQ - VIRT_GSI_BASE , FDT_IRQ_FLAGS_EDGE_LO_HI);
|
||
|
|
qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupt-parent",
|
||
|
|
*pch_pic_phandle);
|
||
|
|
g_free(nodename);
|
||
|
|
@@ -334,7 +339,7 @@ static void fdt_add_uart_node(LoongArchVirtMachineState *lvms,
|
||
|
|
qemu_fdt_setprop_cell(ms->fdt, nodename, "clock-frequency", 100000000);
|
||
|
|
if (chosen)
|
||
|
|
qemu_fdt_setprop_string(ms->fdt, "/chosen", "stdout-path", nodename);
|
||
|
|
- qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts", irq, 0x4);
|
||
|
|
+ qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts", irq, FDT_IRQ_FLAGS_LEVEL_HI);
|
||
|
|
qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupt-parent",
|
||
|
|
*pch_pic_phandle);
|
||
|
|
g_free(nodename);
|
||
|
|
diff --git a/hw/rtc/ls7a_rtc.c b/hw/rtc/ls7a_rtc.c
|
||
|
|
index 1f9e38a735..be9546c850 100644
|
||
|
|
--- a/hw/rtc/ls7a_rtc.c
|
||
|
|
+++ b/hw/rtc/ls7a_rtc.c
|
||
|
|
@@ -145,20 +145,22 @@ static void toymatch_write(LS7ARtcState *s, uint64_t val, int num)
|
||
|
|
now = qemu_clock_get_ms(rtc_clock);
|
||
|
|
toymatch_val_to_time(s, val, &tm);
|
||
|
|
expire_time = now + (qemu_timedate_diff(&tm) - s->offset_toy) * 1000;
|
||
|
|
- timer_mod(s->toy_timer[num], expire_time);
|
||
|
|
+ if (expire_time > now)
|
||
|
|
+ timer_mod(s->toy_timer[num], expire_time);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
static void rtcmatch_write(LS7ARtcState *s, uint64_t val, int num)
|
||
|
|
{
|
||
|
|
- uint64_t expire_ns;
|
||
|
|
+ int64_t expire_ns;
|
||
|
|
|
||
|
|
/* it do not support write when toy disabled */
|
||
|
|
if (rtc_enabled(s)) {
|
||
|
|
s->rtcmatch[num] = val;
|
||
|
|
/* calculate expire time */
|
||
|
|
expire_ns = ticks_to_ns(val) - ticks_to_ns(s->offset_rtc);
|
||
|
|
- timer_mod_ns(s->rtc_timer[num], expire_ns);
|
||
|
|
+ if (expire_ns > 0)
|
||
|
|
+ timer_mod_ns(s->rtc_timer[num], expire_ns);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@@ -185,7 +187,7 @@ static void ls7a_rtc_stop(LS7ARtcState *s)
|
||
|
|
static void ls7a_toy_start(LS7ARtcState *s)
|
||
|
|
{
|
||
|
|
int i;
|
||
|
|
- uint64_t expire_time, now;
|
||
|
|
+ int64_t expire_time, now;
|
||
|
|
struct tm tm = {};
|
||
|
|
|
||
|
|
now = qemu_clock_get_ms(rtc_clock);
|
||
|
|
@@ -194,19 +196,21 @@ static void ls7a_toy_start(LS7ARtcState *s)
|
||
|
|
for (i = 0; i < TIMER_NUMS; i++) {
|
||
|
|
toymatch_val_to_time(s, s->toymatch[i], &tm);
|
||
|
|
expire_time = now + (qemu_timedate_diff(&tm) - s->offset_toy) * 1000;
|
||
|
|
- timer_mod(s->toy_timer[i], expire_time);
|
||
|
|
+ if (expire_time > now)
|
||
|
|
+ timer_mod(s->toy_timer[i], expire_time);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
static void ls7a_rtc_start(LS7ARtcState *s)
|
||
|
|
{
|
||
|
|
int i;
|
||
|
|
- uint64_t expire_time;
|
||
|
|
+ int64_t expire_time;
|
||
|
|
|
||
|
|
/* recalculate expire time and enable timer */
|
||
|
|
for (i = 0; i < TIMER_NUMS; i++) {
|
||
|
|
expire_time = ticks_to_ns(s->rtcmatch[i]) - ticks_to_ns(s->offset_rtc);
|
||
|
|
- timer_mod_ns(s->rtc_timer[i], expire_time);
|
||
|
|
+ if (expire_time > 0)
|
||
|
|
+ timer_mod_ns(s->rtc_timer[i], expire_time);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@@ -370,7 +374,7 @@ static void toy_timer_cb(void *opaque)
|
||
|
|
LS7ARtcState *s = opaque;
|
||
|
|
|
||
|
|
if (toy_enabled(s)) {
|
||
|
|
- qemu_irq_raise(s->irq);
|
||
|
|
+ qemu_irq_pulse(s->irq);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@@ -379,7 +383,7 @@ static void rtc_timer_cb(void *opaque)
|
||
|
|
LS7ARtcState *s = opaque;
|
||
|
|
|
||
|
|
if (rtc_enabled(s)) {
|
||
|
|
- qemu_irq_raise(s->irq);
|
||
|
|
+ qemu_irq_pulse(s->irq);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
--
|
||
|
|
2.41.0.windows.1
|
||
|
|
|