riscv: simplify timer interrupt handling
Just disable the timer interrupt and notify supervisor. To receive another timer interrupt just set timecmp and enable machine mode timer interrupt again. TEST=Run linux on sifive unleashed Change-Id: I5d693f872bd492c9d0017b514882a4cebd5ccadd Signed-off-by: Philipp Hug <philipp@hug.cx> Reviewed-on: https://review.coreboot.org/29340 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net> Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
This commit is contained in:
parent
d4ab5bbc82
commit
1ed082bc8b
|
@ -20,9 +20,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <vm.h>
|
#include <vm.h>
|
||||||
|
|
||||||
static uint64_t *time;
|
|
||||||
static uint64_t *timecmp;
|
|
||||||
|
|
||||||
static const char *const exception_names[] = {
|
static const char *const exception_names[] = {
|
||||||
"Instruction address misaligned",
|
"Instruction address misaligned",
|
||||||
"Instruction access fault",
|
"Instruction access fault",
|
||||||
|
@ -78,62 +75,22 @@ static void print_trap_information(const trapframe *tf)
|
||||||
printk(BIOS_DEBUG, "Stored sp: %p\n", (void*) tf->gpr[2]);
|
printk(BIOS_DEBUG, "Stored sp: %p\n", (void*) tf->gpr[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gettimer(void)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* FIXME: This hard-coded value (currently) works on spike, but we
|
|
||||||
* should really read it from the device tree.
|
|
||||||
*/
|
|
||||||
uintptr_t clint = 0x02000000;
|
|
||||||
|
|
||||||
time = (void *)(clint + 0xbff8);
|
|
||||||
timecmp = (void *)(clint + 0x4000);
|
|
||||||
|
|
||||||
if (!time)
|
|
||||||
die("Got timer interrupt but found no timer.");
|
|
||||||
if (!timecmp)
|
|
||||||
die("Got timer interrupt but found no timecmp.");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void interrupt_handler(trapframe *tf)
|
static void interrupt_handler(trapframe *tf)
|
||||||
{
|
{
|
||||||
uint64_t cause = tf->cause & ~0x8000000000000000ULL;
|
uint64_t cause = tf->cause & ~0x8000000000000000ULL;
|
||||||
uint32_t msip, ssie;
|
|
||||||
|
|
||||||
switch (cause) {
|
switch (cause) {
|
||||||
case IRQ_M_TIMER:
|
case IRQ_M_TIMER:
|
||||||
// The only way to reset the timer interrupt is to
|
/*
|
||||||
// write mtimecmp. But we also have to ensure the
|
* Set interrupt pending for supervisor mode and disable timer
|
||||||
// comparison fails, for a long time, to let
|
* interrupt in machine mode.
|
||||||
// supervisor interrupt handler compute a new value
|
* To receive another timer interrupt just set timecmp and
|
||||||
// and set it. Finally, it fires if mtimecmp is <=
|
* enable machine mode timer interrupt again.
|
||||||
// mtime, not =, so setting mtimecmp to 0 won't work
|
*/
|
||||||
// to clear the interrupt and disable a new one. We
|
|
||||||
// have to set the mtimecmp far into the future.
|
|
||||||
// Akward!
|
|
||||||
//
|
|
||||||
// Further, maybe the platform doesn't have the
|
|
||||||
// hardware or the payload never uses it. We hold off
|
|
||||||
// querying some things until we are sure we need
|
|
||||||
// them. What to do if we can not find them? There are
|
|
||||||
// no good options.
|
|
||||||
|
|
||||||
// This hart may have disabled timer interrupts. If
|
clear_csr(mie, MIP_MTIP);
|
||||||
// so, just return. Kernels should only enable timer
|
set_csr(mip, MIP_STIP);
|
||||||
// interrupts on one hart, and that should be hart 0
|
|
||||||
// at present, as we only search for
|
|
||||||
// "core{0{0{timecmp" above.
|
|
||||||
ssie = read_csr(sie);
|
|
||||||
if (!(ssie & SIP_STIP))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!timecmp)
|
|
||||||
gettimer();
|
|
||||||
//printk(BIOS_SPEW, "timer interrupt\n");
|
|
||||||
*timecmp = (uint64_t) -1;
|
|
||||||
msip = read_csr(mip);
|
|
||||||
msip |= SIP_STIP;
|
|
||||||
write_csr(mip, msip);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk(BIOS_EMERG, "======================================\n");
|
printk(BIOS_EMERG, "======================================\n");
|
||||||
|
|
Loading…
Reference in New Issue