blob: c4eaecdd7371288b8d47ca871c9e5b709beeb8a0 [file] [log] [blame]
#include <stdint.h>
#include "cpu.h"
#include "irq.h"
#include "msr.h"
static bool timer_irq_handler(void *context, struct irq_handle *h)
{
struct cpu *c = cpu();
/* Mask timer interrupt and dismiss current interrupt. */
write_msr(cnthp_ctl_el2, read_msr(cnthp_ctl_el2) | 0x2);
irq_dismiss(h);
/* Execute user-supplied callback. */
if (c->timer_cb)
return c->timer_cb(c->timer_context);
return false;
}
void timer_set(uint64_t time, bool (*cb)(void *), void *context)
{
uint64_t v;
struct cpu *c = cpu();
/* Save callback. */
c->timer_cb = cb;
c->timer_context = context;
/* TODO: There's a better way to advance this. */
v = read_msr(cntpct_el0);
write_msr(CNTHP_CVAL_EL2, v + time);
write_msr(cnthp_ctl_el2, 1); /* enable. */
}
void timer_init(void)
{
irq_config(TIMER_IRQ, irq_trigger_level, irq_polarity_active_high,
timer_irq_handler, NULL);
}
void timer_init_percpu(void)
{
/* Mask timer interrupt for now. */
write_msr(cnthp_ctl_el2, read_msr(cnthp_ctl_el2) | 0x2);
irq_enable(TIMER_IRQ);
}