[haiku-commits] haiku: hrev46081 - src/system/kernel/arch/arm

  • From: ithamar@xxxxxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 17 Sep 2013 03:08:47 +0200 (CEST)

hrev46081 adds 1 changeset to branch 'master'
old head: 7418443d1246959a5d89dad67d56b749a6708c6a
new head: af1c0b55ca4c6303ce2c2d8789442421ddda2bc8
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=af1c0b5+%5E7418443

----------------------------------------------------------------------------

af1c0b5: ARM: kernel: fix timer resolution and implement basic timekeeping.
  
  The previously used method for programming the timer did not take
  into account that our timespec is 64bit while the register we poke
  it into is 32 bit. Since the PXA (SoC in Verdex target) has a limited
  scale of resolution (us,ms,second) we dynamicly determine the one
  that we can most closely match, and set that.
  
  For f.ex. snooze to work however, we also need system_time to work.
  The current implementation uses a system timer at microsecond
  resolution to keep track of time.
  
  Although the code is far from perfect, committing it now before
  it gets lost, since I'm working on the infrastructure code
  to properly factor out the SoC specific code out of the core
  ARM architecture code (so the kernel can support more then
  our poor old Verdex QEMU target ;))

                          [ Ithamar R. Adema <ithamar@xxxxxxxxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev46081
Commit:      af1c0b55ca4c6303ce2c2d8789442421ddda2bc8
URL:         http://cgit.haiku-os.org/haiku/commit/?id=af1c0b5
Author:      Ithamar R. Adema <ithamar@xxxxxxxxxxxxxxxxxxx>
Date:        Tue Sep 17 01:03:17 2013 UTC

----------------------------------------------------------------------------

2 files changed, 55 insertions(+), 21 deletions(-)
src/system/kernel/arch/arm/arch_timer.cpp | 74 ++++++++++++++++++++-------
src/system/kernel/lib/arch/arm/Jamfile    |  2 -

----------------------------------------------------------------------------

diff --git a/src/system/kernel/arch/arm/arch_timer.cpp 
b/src/system/kernel/arch/arm/arch_timer.cpp
index 5cf8574..6c291ed 100644
--- a/src/system/kernel/arch/arm/arch_timer.cpp
+++ b/src/system/kernel/arch/arm/arch_timer.cpp
@@ -35,35 +35,63 @@
 #define PXA_OSSR               0x05
 #define PXA_OIER               0x07
 #define PXA_OSCR4              0x10
+#define PXA_OSCR5              0x11
 #define PXA_OSMR4              0x20
+#define PXA_OSMR5              0x21
 #define PXA_OMCR4              0x30
+#define PXA_OMCR5              0x31
 
+#define PXA_RES_S      (3 << 0)
+#define PXA_RES_MS     (1 << 1)
+#define PXA_RES_US     (1 << 2)
 
-static area_id sPxaTimersArea;
-static uint32 *sPxaTimersBase;
+#define US2S(bt)       ((bt) / 1000000ULL)
+#define US2MS(bt)      ((bt) / 1000ULL)
 
+static area_id sPxaTimersArea = B_ERROR;
+static uint32 *sPxaTimersBase = NULL;
+static bigtime_t sSystemTime = 0;
 
 static int32
 pxa_timer_interrupt(void *data)
 {
-       int32 ret = timer_interrupt();
-        sPxaTimersBase[PXA_OSSR] |= (1 << 4);
+       if (sPxaTimersBase[PXA_OSSR] & (1 << 4)) {
+               sPxaTimersBase[PXA_OSSR] |= (1 << 4);
+               return timer_interrupt();
+       }
 
-        return ret;
-}
+       if (sPxaTimersBase[PXA_OSSR]  & (1 << 5)) {
+               sPxaTimersBase[PXA_OSSR] |= (1 << 5);
+               sSystemTime += UINT_MAX + 1ULL;
+       }
 
+       return B_HANDLED_INTERRUPT;
+}
 
 void
 arch_timer_set_hardware_timer(bigtime_t timeout)
 {
-       TRACE(("arch_timer_set_hardware_timer(%lld)\n", timeout));
-
-       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
+       uint32 val = timeout & UINT_MAX;
+       uint32 res = PXA_RES_US;
+
+       if (timeout & ~UINT_MAX) {
+               // Does not fit, so scale resolution down to milliseconds
+               if (US2MS(timeout) & ~UINT_MAX) {
+                       // Still does not fit, scale down to seconds as last 
ditch attempt
+                       val = US2S(timeout) & UINT_MAX;
+                       res = PXA_RES_S;
+               } else {
+                       // Fits in millisecond resolution
+                       val = US2MS(timeout) & UINT_MAX;
+                       res = PXA_RES_MS;
+               }
        }
+
+       TRACE(("arch_timer_set_hardware_timer(val=%lu, res=%lu)\n", val, res));
+       sPxaTimersBase[PXA_OIER] |= (1 << 4);
+       sPxaTimersBase[PXA_OMCR4] = res;
+       sPxaTimersBase[PXA_OSMR4] = val;
+       sPxaTimersBase[PXA_OSCR4] = 0; // start counting from 0 again
 }
 
 
@@ -72,13 +100,10 @@ arch_timer_clear_hardware_timer()
 {
        TRACE(("arch_timer_clear_hardware_timer\n"));
 
-       if (sPxaTimersBase) {
-               sPxaTimersBase[PXA_OMCR4] = 0; // disable our timer
-               sPxaTimersBase[PXA_OIER] &= ~(4 << 1);
-       }
+       sPxaTimersBase[PXA_OMCR4] = 0; // disable our timer
+       sPxaTimersBase[PXA_OIER] &= ~(1 << 4);
 }
 
-
 int
 arch_init_timer(kernel_args *args)
 {
@@ -88,9 +113,20 @@ arch_init_timer(kernel_args *args)
        if (sPxaTimersArea < 0)
                return sPxaTimersArea;
 
-       sPxaTimersBase[PXA_OMCR4] = 0; // disable our timer
+       sPxaTimersBase[PXA_OIER] |= (1 << 5); // enable timekeeping timer
+       sPxaTimersBase[PXA_OMCR5] = PXA_RES_US | (1 << 7);
+       sPxaTimersBase[PXA_OSMR5] = UINT_MAX;
+       sPxaTimersBase[PXA_OSCR5] = 0;
 
        install_io_interrupt_handler(PXA_TIMERS_INTERRUPT, 
&pxa_timer_interrupt, NULL, 0);
 
        return B_OK;
 }
+
+bigtime_t
+system_time(void)
+{
+       return (sPxaTimersBase != NULL) ?
+               sSystemTime + sPxaTimersBase[PXA_OSCR5] :
+               0ULL;
+}
diff --git a/src/system/kernel/lib/arch/arm/Jamfile 
b/src/system/kernel/lib/arch/arm/Jamfile
index 084a552..1bdf0f1 100644
--- a/src/system/kernel/lib/arch/arm/Jamfile
+++ b/src/system/kernel/lib/arch/arm/Jamfile
@@ -11,8 +11,6 @@ SEARCH_SOURCE += [ FDirName $(librootSources) os arch generic 
] ;
 KernelMergeObject kernel_os_arch_$(TARGET_ARCH).o :
        atomic.S
        byteorder.S
-#      system_time_asm.S
-       system_time.c
 
        generic_system_time_nsecs.cpp
 


Other related posts:

  • » [haiku-commits] haiku: hrev46081 - src/system/kernel/arch/arm - ithamar