From be7195d0f79a82a419cc06e4fc5b40e5dccf36a2 Mon Sep 17 00:00:00 2001 From: "Ithamar R. Adema" Date: Mon, 5 Nov 2012 01:34:25 +0100 Subject: [PATCH] ARM: add initial timer support. Currently hardcoded to PXA (verdex) support, needs SoC abstraction for seperating implementations, best done using FDT code as committed by Francois. --- src/system/kernel/arch/arm/arch_timer.cpp | 63 +++++++++++++++++++---- 1 file changed, 53 insertions(+), 10 deletions(-) diff --git a/src/system/kernel/arch/arm/arch_timer.cpp b/src/system/kernel/arch/arm/arch_timer.cpp index 7224c90c20..2bda04042c 100644 --- a/src/system/kernel/arch/arm/arch_timer.cpp +++ b/src/system/kernel/arch/arm/arch_timer.cpp @@ -1,9 +1,10 @@ /* - * Copyright 2007, Haiku Inc. All rights reserved. + * Copyright 2007-2012, Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: * François Revol + * Ithamar R. Adema * * Copyright 2001, Travis Geiselbrecht. All rights reserved. * Distributed under the terms of the NewOS License. @@ -16,30 +17,72 @@ #include #include -//#include +#include + +#define PXA_TIMERS_PHYS_BASE 0x40A00000 +#define PXA_TIMERS_SIZE 0x000000C0 +#define PXA_TIMERS_INTERRUPT 7 /* OST_4_11 */ + +#define PXA_OSSR 0x05 +#define PXA_OIER 0x07 +#define PXA_OSCR4 0x10 +#define PXA_OSMR4 0x20 +#define PXA_OMCR4 0x30 + +#define TRACE(x) //dprintf x + +static area_id sPxaTimersArea; +static uint32 *sPxaTimersBase; + + +static int32 +pxa_timer_interrupt(void *data) +{ + int32 ret = timer_interrupt(); + sPxaTimersBase[PXA_OSSR] |= (1 << 4); + + return ret; +} void arch_timer_set_hardware_timer(bigtime_t timeout) { - #warning ARM:WRITEME - // M68KPlatform::Default()->SetHardwareTimer(timeout); + TRACE(("arch_timer_set_hardware_timer(%lld): %p\n", timeout, sPxaTimersBase)); + + if (sPxaTimersBase) { + sPxaTimersBase[PXA_OIER] |= (1 << 4); + sPxaTimersBase[PXA_OMCR4] = 4; // set to exactly single milisecond resolution + sPxaTimersBase[PXA_OSMR4] = timeout; + sPxaTimersBase[PXA_OSCR4] = 0; // start counting from 0 again + } } void arch_timer_clear_hardware_timer() { - #warning ARM:WRITEME - // M68KPlatform::Default()->ClearHardwareTimer(); + TRACE(("arch_timer_clear_hardware_timer: %p\n", sPxaTimersBase)); + + if (sPxaTimersBase) { + sPxaTimersBase[PXA_OMCR4] = 0; // disable our timer + sPxaTimersBase[PXA_OIER] &= ~(4 << 1); + } } int arch_init_timer(kernel_args *args) { - #warning ARM:WRITEME - // M68KPlatform::Default()->InitTimer(args); - return 0; -} + sPxaTimersArea = map_physical_memory("pxa_timers", PXA_TIMERS_PHYS_BASE, + PXA_TIMERS_SIZE, 0, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&sPxaTimersBase); + if (sPxaTimersArea < 0) + return sPxaTimersArea; + + sPxaTimersBase[PXA_OMCR4] = 0; // disable our timer + + install_io_interrupt_handler(PXA_TIMERS_INTERRUPT, &pxa_timer_interrupt, NULL, 0); + + return B_OK; +}