1 /* 2 * Copyright 2007-2012, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * François Revol <revol@free.fr> 7 * Ithamar R. Adema <ithamar@upgrade-android.com> 8 * 9 * Copyright 2001, Travis Geiselbrecht. All rights reserved. 10 * Distributed under the terms of the NewOS License. 11 */ 12 13 14 #include <boot/stage2.h> 15 #include <kernel.h> 16 #include <debug.h> 17 18 #include <timer.h> 19 #include <arch/timer.h> 20 #include <arch/cpu.h> 21 22 23 //#define TRACE_ARCH_TIMER 24 #ifdef TRACE_ARCH_TIMER 25 # define TRACE(x) dprintf x 26 #else 27 # define TRACE(x) ; 28 #endif 29 30 31 #define PXA_TIMERS_PHYS_BASE 0x40A00000 32 #define PXA_TIMERS_SIZE B_PAGE_SIZE 33 #define PXA_TIMERS_INTERRUPT 7 /* OST_4_11 */ 34 35 #define PXA_OSSR 0x05 36 #define PXA_OIER 0x07 37 #define PXA_OSCR4 0x10 38 #define PXA_OSCR5 0x11 39 #define PXA_OSMR4 0x20 40 #define PXA_OSMR5 0x21 41 #define PXA_OMCR4 0x30 42 #define PXA_OMCR5 0x31 43 44 #define PXA_RES_S (3 << 0) 45 #define PXA_RES_MS (1 << 1) 46 #define PXA_RES_US (1 << 2) 47 48 #define US2S(bt) ((bt) / 1000000ULL) 49 #define US2MS(bt) ((bt) / 1000ULL) 50 51 static area_id sPxaTimersArea = -1; 52 static uint32 *sPxaTimersBase = NULL; 53 static bigtime_t sSystemTime = 0; 54 55 static int32 56 pxa_timer_interrupt(void *data) 57 { 58 if (sPxaTimersBase[PXA_OSSR] & (1 << 4)) { 59 sPxaTimersBase[PXA_OSSR] |= (1 << 4); 60 return timer_interrupt(); 61 } 62 63 if (sPxaTimersBase[PXA_OSSR] & (1 << 5)) { 64 sPxaTimersBase[PXA_OSSR] |= (1 << 5); 65 sSystemTime += UINT_MAX + 1ULL; 66 } 67 68 return B_HANDLED_INTERRUPT; 69 } 70 71 void 72 arch_timer_set_hardware_timer(bigtime_t timeout) 73 { 74 uint32 val = timeout & UINT_MAX; 75 uint32 res = PXA_RES_US; 76 77 if (timeout & ~UINT_MAX) { 78 // Does not fit, so scale resolution down to milliseconds 79 if (US2MS(timeout) & ~UINT_MAX) { 80 // Still does not fit, scale down to seconds as last ditch attempt 81 val = US2S(timeout) & UINT_MAX; 82 res = PXA_RES_S; 83 } else { 84 // Fits in millisecond resolution 85 val = US2MS(timeout) & UINT_MAX; 86 res = PXA_RES_MS; 87 } 88 } 89 90 TRACE(("arch_timer_set_hardware_timer(val=%lu, res=%lu)\n", val, res)); 91 sPxaTimersBase[PXA_OIER] |= (1 << 4); 92 sPxaTimersBase[PXA_OMCR4] = res; 93 sPxaTimersBase[PXA_OSMR4] = val; 94 sPxaTimersBase[PXA_OSCR4] = 0; // start counting from 0 again 95 } 96 97 98 void 99 arch_timer_clear_hardware_timer() 100 { 101 TRACE(("arch_timer_clear_hardware_timer\n")); 102 103 sPxaTimersBase[PXA_OMCR4] = 0; // disable our timer 104 sPxaTimersBase[PXA_OIER] &= ~(1 << 4); 105 } 106 107 int 108 arch_init_timer(kernel_args *args) 109 { 110 TRACE(("%s\n", __func__)); 111 sPxaTimersArea = map_physical_memory("pxa_timers", PXA_TIMERS_PHYS_BASE, 112 PXA_TIMERS_SIZE, 0, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&sPxaTimersBase); 113 114 if (sPxaTimersArea < 0) 115 return sPxaTimersArea; 116 117 sPxaTimersBase[PXA_OIER] |= (1 << 5); // enable timekeeping timer 118 sPxaTimersBase[PXA_OMCR5] = PXA_RES_US | (1 << 7); 119 sPxaTimersBase[PXA_OSMR5] = UINT_MAX; 120 sPxaTimersBase[PXA_OSCR5] = 0; 121 122 install_io_interrupt_handler(PXA_TIMERS_INTERRUPT, &pxa_timer_interrupt, NULL, 0); 123 124 return B_OK; 125 } 126 127 bigtime_t 128 system_time(void) 129 { 130 if (sPxaTimersArea < 0) 131 return 0; 132 133 return (sPxaTimersBase != NULL) ? 134 sSystemTime + sPxaTimersBase[PXA_OSCR5] : 135 0ULL; 136 } 137