diff --git a/minix/kernel/arch/earm/arch_clock.c b/minix/kernel/arch/earm/arch_clock.c index f26370c37..431556fbe 100644 --- a/minix/kernel/arch/earm/arch_clock.c +++ b/minix/kernel/arch/earm/arch_clock.c @@ -40,7 +40,7 @@ int init_local_timer(unsigned freq) tsc_per_ms[0] = 15000; } else if (BOARD_IS_RPI_2_B(machine.board_id) || BOARD_IS_RPI_3_B(machine.board_id)) { - tsc_per_ms[0] = read_cntfrq() / 1000; + tsc_per_ms[0] = 1000; } else { panic("Can not do the clock setup. machine (0x%08x) is unknown\n",machine.board_id); diff --git a/minix/kernel/arch/earm/bsp/rpi/rpi_intr.c b/minix/kernel/arch/earm/bsp/rpi/rpi_intr.c index 53e85c09a..483d3d46d 100644 --- a/minix/kernel/arch/earm/bsp/rpi/rpi_intr.c +++ b/minix/kernel/arch/earm/bsp/rpi/rpi_intr.c @@ -25,6 +25,7 @@ static kern_phys_map intr_phys_map; static kern_phys_map timer_phys_map; static irq_hook_t dummy8_irq_hook; +static irq_hook_t dummy40_irq_hook; static irq_hook_t dummy41_irq_hook; static irq_hook_t dummy51_irq_hook; @@ -71,9 +72,10 @@ intr_init(const int auto_eoi) mmio_write(rpi2_intr.core_base + QA7_CORE0TIMER, 0x8); /* Register dummy irq handlers */ - put_irq_handler(&dummy8_irq_hook, 8, (irq_handler_t)dummy_irq_handler); - put_irq_handler(&dummy41_irq_hook, 41, (irq_handler_t)dummy_irq_handler); - put_irq_handler(&dummy51_irq_hook, 51, (irq_handler_t)dummy_irq_handler); + put_irq_handler(&dummy8_irq_hook, 8, dummy_irq_handler); + put_irq_handler(&dummy40_irq_hook, 40, dummy_irq_handler); + put_irq_handler(&dummy41_irq_hook, 41, dummy_irq_handler); + put_irq_handler(&dummy51_irq_hook, 51, dummy_irq_handler); return 0; } diff --git a/minix/kernel/arch/earm/bsp/rpi/rpi_timer.c b/minix/kernel/arch/earm/bsp/rpi/rpi_timer.c index 1b400450a..4f83252fb 100644 --- a/minix/kernel/arch/earm/bsp/rpi/rpi_timer.c +++ b/minix/kernel/arch/earm/bsp/rpi/rpi_timer.c @@ -20,16 +20,18 @@ static irq_hook_t arm_timer_hook; struct arm_timer { + vir_bytes st_base; + int size; int irq_nr; u32_t freq; + + int st_workaround; }; -static struct arm_timer arm_timer = { - .irq_nr = RPI2_IRQ_ARMTIMER, - .freq = 0, -}; +static struct arm_timer arm_timer; -static kern_phys_map stc_timer_phys_map; +static kern_phys_map st_timer_phys_map; +static kern_phys_map st_timer_user_phys_map; int bsp_register_timer_handler(const irq_handler_t handler) @@ -51,8 +53,11 @@ bsp_register_timer_handler(const irq_handler_t handler) /* callback for when the free running clock gets mapped */ int -kern_phys_fr_user_mapped(vir_bytes id, phys_bytes address) +kern_phys_st_user_mapped(vir_bytes id, phys_bytes address) { + arm_frclock.tcrr = address + RPI_ST_CLO; + arm_frclock.hz = RPI_ST_FREQ; + return 0; } @@ -60,6 +65,41 @@ void bsp_timer_init(unsigned freq) { arm_timer.freq = freq; + + if (BOARD_IS_RPI_2_B(machine.board_id) || + BOARD_IS_RPI_3_B(machine.board_id)) { + arm_timer.st_base = RPI_ST_BASE; + arm_timer.size = 0x1000; /* 4K */ + } else { + panic + ("Can not do the timer setup. machine (0x%08x) is unknown\n", + machine.board_id); + } + + kern_phys_map_ptr(arm_timer.st_base, arm_timer.size, + VMMF_UNCACHED | VMMF_WRITE, + &st_timer_phys_map, (vir_bytes) & arm_timer.st_base); + + /* Check if we need to workaround QEMU's lack of ST support */ + if (mmio_read(arm_timer.st_base + RPI_ST_CLO) == 0) { + /* + * Uh oh. We'll have to rely on the ARM processor's internal + * timers. Not good. + */ + printf("Working around lack of system timer support - please fix\n"); + arm_timer.st_workaround = 1; + arm_timer.irq_nr = RPI2_IRQ_ARMTIMER; + } + else { + arm_timer.st_workaround = 0; + arm_timer.irq_nr = RPI_IRQ_ST_C3; + + /* the timer is also mapped in user space hence the this */ + /* second mapping and callback to set kerninfo frclock_tcrr */ + kern_req_phys_map(arm_timer.st_base, ARM_PAGE_SIZE, + VMMF_UNCACHED | VMMF_USER, + &st_timer_user_phys_map, kern_phys_st_user_mapped, 0); + } } void @@ -71,15 +111,30 @@ bsp_timer_stop() void bsp_timer_int_handler() { - /* Arm next timer countdown and enable timer */ - write_cntv_cval(-1); - write_cntv_tval(read_cntfrq() / arm_timer.freq); - write_cntv_ctl(ARMTIMER_ENABLE); + if (arm_timer.st_workaround) { + /* Arm next timer countdown and enable timer */ + write_cntv_cval(-1); + write_cntv_tval(read_cntfrq() / arm_timer.freq); + write_cntv_ctl(ARMTIMER_ENABLE); + } + else { + /* Set next timer alarm and enable timer */ + u32_t next_alarm = mmio_read(arm_timer.st_base + RPI_ST_CLO); + next_alarm += RPI_ST_FREQ / arm_timer.freq; + + mmio_write(arm_timer.st_base + RPI_ST_C3, next_alarm); + mmio_write(arm_timer.st_base + RPI_ST_CS, RPI_ST_M3); + } } /* Use the free running clock as TSC */ void read_tsc_64(u64_t * t) { - *t = read_cntv_cval(); + if (arm_timer.st_workaround) + *t = read_cntv_cval(); + else { + *t = mmio_read(arm_timer.st_base + RPI_ST_CHI); + *t = (*t << 32) | mmio_read(arm_timer.st_base + RPI_ST_CLO); + } } diff --git a/minix/kernel/arch/earm/bsp/rpi/rpi_timer_registers.h b/minix/kernel/arch/earm/bsp/rpi/rpi_timer_registers.h index 351f99901..4dd3a686f 100644 --- a/minix/kernel/arch/earm/bsp/rpi/rpi_timer_registers.h +++ b/minix/kernel/arch/earm/bsp/rpi/rpi_timer_registers.h @@ -8,4 +8,23 @@ #define RPI2_IRQ_ARMTIMER 3 +#define RPI_ST_BASE 0x3f003000 + +#define RPI_ST_CS 0x0 +#define RPI_ST_CLO 0x4 +#define RPI_ST_CHI 0x8 +#define RPI_ST_C0 0xc +#define RPI_ST_C1 0x10 +#define RPI_ST_C2 0x14 +#define RPI_ST_C3 0x18 + +#define RPI_ST_M0 0x1 +#define RPI_ST_M1 0x2 +#define RPI_ST_M2 0x4 +#define RPI_ST_M3 0x8 + +#define RPI_IRQ_ST_C3 67 + +#define RPI_ST_FREQ 1000000 + #endif /* _RPI_TIMER_REGISTERS_H */