121 lines
2.5 KiB
C
121 lines
2.5 KiB
C
#include "kernel/kernel.h"
|
|
#include "kernel/clock.h"
|
|
#include <sys/types.h>
|
|
#include <machine/cpu.h>
|
|
#include <minix/board.h>
|
|
#include <minix/mmio.h>
|
|
#include <assert.h>
|
|
#include <io.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include "arch_proto.h"
|
|
#include "bsp_timer.h"
|
|
#include "rpi_timer_registers.h"
|
|
#include "rpi_intr_registers.h"
|
|
#include "bsp_intr.h"
|
|
|
|
/* interrupt handler hook */
|
|
static irq_hook_t rpi_timer_hook;
|
|
|
|
static u32_t counts_per_hz = ~0;
|
|
static u64_t high_frc;
|
|
|
|
static int rpi_timer_init_ok = 0;
|
|
struct rpi_timer_registers;
|
|
|
|
struct bcm2835_timer
|
|
{
|
|
vir_bytes base;
|
|
int irq_nr;
|
|
struct rpi_timer_registers *regs;
|
|
};
|
|
|
|
struct rpi_timer_registers
|
|
{
|
|
vir_bytes STCS;
|
|
vir_bytes STCLO;
|
|
vir_bytes STCHI;
|
|
vir_bytes STC3;
|
|
};
|
|
|
|
static struct rpi_timer_registers regs_v1 =
|
|
{
|
|
.STCS = BCM2835_STIMER_CS,
|
|
.STCLO = BCM2835_STIMER_CLO,
|
|
.STCHI = BCM2835_STIMER_CHI,
|
|
.STC3 = BCM2835_STIMER_C3
|
|
};
|
|
static struct bcm2835_timer rpi_timer = {
|
|
.base = BCM2835_STIMER_BASE,
|
|
.irq_nr = BCM2835_INT_TIMER3,
|
|
.regs = ®s_v1
|
|
};
|
|
|
|
static struct bcm2835_timer *timer;
|
|
|
|
int
|
|
bsp_register_timer_handler(const irq_handler_t handler)
|
|
{
|
|
/* Initialize the CLOCK's interrupt hook. */
|
|
rpi_timer_hook.proc_nr_e = NONE;
|
|
rpi_timer_hook.irq = timer->irq_nr;
|
|
|
|
put_irq_handler(&rpi_timer_hook, timer->irq_nr, handler);
|
|
/* only unmask interrupts after registering */
|
|
bsp_irq_unmask(timer->irq_nr);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* meta data for remapping */
|
|
static kern_phys_map timer_phys_map;
|
|
void
|
|
bsp_timer_init(unsigned freq)
|
|
{
|
|
if ( BOARD_IS_RPI(machine.board_id))
|
|
{
|
|
u32_t stclo;
|
|
timer = &rpi_timer;
|
|
counts_per_hz = BCM2835_STIMER_HZ / freq;
|
|
kern_phys_map_ptr(timer->base, ARM_PAGE_SIZE,
|
|
VMMF_UNCACHED | VMMF_WRITE,
|
|
&timer_phys_map, (vir_bytes) & timer->base);
|
|
mmio_write( timer->base + timer->regs->STCS, BCM2835_STIMER_M3 );
|
|
stclo = mmio_read( timer->base + timer->regs->STCLO );
|
|
stclo += counts_per_hz;
|
|
mmio_write( timer->base + timer->regs->STC3, stclo );
|
|
frclock_init();
|
|
rpi_timer_init_ok = 1;
|
|
}
|
|
}
|
|
|
|
void
|
|
bsp_timer_stop()
|
|
{
|
|
|
|
}
|
|
|
|
void
|
|
bsp_timer_int_handler()
|
|
{
|
|
u32_t stclo;
|
|
mmio_write( timer->base + timer->regs->STCS , BCM2835_STIMER_M3 );
|
|
stclo = mmio_read( timer->base + timer->regs->STCLO );
|
|
stclo += counts_per_hz;
|
|
mmio_write( timer->base + timer->regs->STC3, stclo );
|
|
}
|
|
|
|
void
|
|
read_tsc_64(u64_t* t)
|
|
{
|
|
u32_t stclo, stchi;
|
|
if (rpi_timer_init_ok) {
|
|
stclo = mmio_read( timer->base + timer->regs->STCLO );
|
|
stchi = mmio_read( timer->base + timer->regs->STCHI );
|
|
*t = ((u64_t)stchi << 32) | (u64_t)stclo;
|
|
} else {
|
|
*t = (u64_t) 0;
|
|
}
|
|
}
|
|
|