kernel/arm: implement generic timer
Change-Id: I5edb7e36013d5e5d9d45ec3cf31014f99601a4c6 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5519 Tested-by: Commit checker robot <[email protected]> Reviewed-by: Fredrik Holmqvist <[email protected]>
This commit is contained in:
@@ -36,6 +36,7 @@ KernelMergeObject kernel_arch_arm.o :
|
||||
arch_atomic32.cpp
|
||||
|
||||
arch_int_gicv2.cpp
|
||||
arch_timer_generic.cpp
|
||||
|
||||
# SoC minimal kernel-required support
|
||||
# (timers, interrupts, rtc?)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2007-2021, Haiku Inc. All rights reserved.
|
||||
* Copyright 2007-2022, Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <arch/cpu.h>
|
||||
|
||||
#include <drivers/bus/FDT.h>
|
||||
#include "arch_timer_generic.h"
|
||||
#include "soc.h"
|
||||
|
||||
#include "soc_pxa.h"
|
||||
@@ -27,12 +28,11 @@
|
||||
|
||||
//#define TRACE_ARCH_TIMER
|
||||
#ifdef TRACE_ARCH_TIMER
|
||||
# define TRACE(x) dprintf x
|
||||
# define TRACE(x...) dprintf(x)
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
# define TRACE(x...) ;
|
||||
#endif
|
||||
|
||||
//static fdt_module_info *sFdtModule;
|
||||
|
||||
#if 0
|
||||
static struct fdt_device_info intc_table[] = {
|
||||
@@ -68,7 +68,15 @@ arch_timer_clear_hardware_timer()
|
||||
int
|
||||
arch_init_timer(kernel_args *args)
|
||||
{
|
||||
TRACE(("%s\n", __func__));
|
||||
TRACE("%s\n", __func__);
|
||||
|
||||
if (ARMGenericTimer::IsAvailable()) {
|
||||
TRACE("init ARMv7 generic timer\n");
|
||||
ARMGenericTimer::Init();
|
||||
}
|
||||
|
||||
//TODO: use SoC-specific timer as a fallback
|
||||
//if the generic timer is not available
|
||||
|
||||
#if 0
|
||||
status_t rc = get_module(B_FDT_MODULE_NAME, (module_info**)&sFdtModule);
|
||||
@@ -77,12 +85,13 @@ arch_init_timer(kernel_args *args)
|
||||
|
||||
rc = sFdtModule->setup_devices(intc_table, intc_count, NULL);
|
||||
if (rc != B_OK)
|
||||
panic("No interrupt controllers found!\n");
|
||||
panic("No hardware timer found!\n");
|
||||
#endif
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
bigtime_t
|
||||
system_time(void)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2022 Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "arch_timer_generic.h"
|
||||
|
||||
|
||||
#define TIMER_IRQ 30
|
||||
|
||||
|
||||
static uint32_t
|
||||
get_counter_freq(void)
|
||||
{
|
||||
uint32_t freq;
|
||||
asm volatile ("MRC p15, 0, %0, c14, c0, 0": "=r" (freq));
|
||||
return freq;
|
||||
}
|
||||
|
||||
|
||||
static uint64_t
|
||||
get_counter(void)
|
||||
{
|
||||
uint32_t counter_low;
|
||||
uint32_t counter_high;
|
||||
|
||||
asm volatile ("ISB\n"
|
||||
"MRRC p15, 0, %0, %1, c14"
|
||||
: "=r" (counter_low), "=r" (counter_high));
|
||||
return ((uint64_t)counter_high << 32) | counter_low;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ARMGenericTimer::SetTimeout(bigtime_t timeout)
|
||||
{
|
||||
uint32_t timeout_ticks = timeout * fTimerFrequency / 1000000;
|
||||
asm volatile ("ISB\n"
|
||||
"MCR p15, 0, %0, c14, c2, 0"
|
||||
: : "r"(timeout_ticks));
|
||||
|
||||
uint32_t timer_ctl = 1;
|
||||
asm volatile ("MCR p15, 0, %0, c14, c2, 1"
|
||||
: : "r"(timer_ctl));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ARMGenericTimer::Clear()
|
||||
{
|
||||
uint32_t timer_ctl = 2;
|
||||
asm volatile ("MCR p15, 0, %0, c14, c2, 1"
|
||||
: : "r"(timer_ctl));
|
||||
}
|
||||
|
||||
|
||||
bigtime_t
|
||||
ARMGenericTimer::Time()
|
||||
{
|
||||
return get_counter() / fTimerFrequency;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
ARMGenericTimer::_InterruptWrapper(void *data)
|
||||
{
|
||||
return ((ARMGenericTimer*)data)->HandleInterrupt();
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
ARMGenericTimer::HandleInterrupt()
|
||||
{
|
||||
return timer_interrupt();
|
||||
}
|
||||
|
||||
|
||||
ARMGenericTimer::ARMGenericTimer()
|
||||
: HardwareTimer()
|
||||
{
|
||||
Clear();
|
||||
|
||||
reserve_io_interrupt_vectors(1, TIMER_IRQ, INTERRUPT_TYPE_IRQ);
|
||||
install_io_interrupt_handler(TIMER_IRQ,
|
||||
&ARMGenericTimer::_InterruptWrapper, this, 0);
|
||||
|
||||
fTimerFrequency = get_counter_freq();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ARMGenericTimer::IsAvailable()
|
||||
{
|
||||
uint32_t pfr1;
|
||||
asm volatile("MRC p15, 0, %0, c0, c1, 1": "=r" (pfr1));
|
||||
return (pfr1 & 0x000F0000) == 0x00010000;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2022 Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef ARCH_ARM_TIMER_GENERIC_H
|
||||
#define ARCH_ARM_TIMER_GENERIC_H
|
||||
|
||||
#include <new>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include "soc.h"
|
||||
|
||||
class ARMGenericTimer : public HardwareTimer {
|
||||
public:
|
||||
void SetTimeout(bigtime_t timeout);
|
||||
void Clear();
|
||||
bigtime_t Time();
|
||||
|
||||
static status_t Init() {
|
||||
ARMGenericTimer *timer = new(std::nothrow) ARMGenericTimer();
|
||||
return timer != NULL ? B_OK : B_NO_MEMORY;
|
||||
}
|
||||
|
||||
static bool IsAvailable();
|
||||
protected:
|
||||
ARMGenericTimer();
|
||||
|
||||
private:
|
||||
static int32 _InterruptWrapper(void *data);
|
||||
int32 HandleInterrupt();
|
||||
|
||||
uint32_t fTimerFrequency;
|
||||
};
|
||||
|
||||
#endif /* ARCH_ARM_TIMER_GENERIC_H */
|
||||
@@ -46,20 +46,14 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
#if 0
|
||||
HardwareTimer(fdt_module_info *fdtModule, fdt_device_node node)
|
||||
: fFDT(fdtModule), fNode(node) {
|
||||
HardwareTimer()
|
||||
{
|
||||
if (sInstance) {
|
||||
panic("Multiple HardwareTimer objects created; that is currently unsupported!");
|
||||
}
|
||||
sInstance = this;
|
||||
}
|
||||
|
||||
// Keep our node around as we might want to grab attributes from it
|
||||
fdt_module_info *fFDT;
|
||||
fdt_device_node fNode;
|
||||
#endif
|
||||
|
||||
static HardwareTimer *sInstance;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user