khypervisor
v1
|
00001 /* 00002 * timer.c 00003 * -------------------------------------- 00004 * Implementation of ARMv7 Generic Timer 00005 * Responsible: Inkyu Han 00006 */ 00007 #include "timer.h" 00008 #include "generic_timer.h" 00009 00010 #include <config/cfg_platform.h> 00011 #include <k-hypervisor-config.h> 00012 00013 static struct timer_channel _channels[TIMER_NUM_MAX_CHANNELS]; 00014 00015 static void _timer_each_callback_channel( timer_channel_t channel, void *param) 00016 { 00017 int i; 00018 for( i = 0; i < TIMER_MAX_CHANNEL_CALLBACKS; i++ ) { 00019 if( _channels[channel].callbacks[i] ) _channels[channel].callbacks[i](param); 00020 } 00021 } 00022 00023 static int _timer_channel_num_callbacks( timer_channel_t channel ) 00024 { 00025 int i, count = 0; 00026 for( i = 0; i < TIMER_MAX_CHANNEL_CALLBACKS; i++) { 00027 if( _channels[channel].callbacks[i] ) count++; 00028 } 00029 return count; 00030 } 00031 00032 static void _timer_hw_callback(void *pdata) 00033 { 00034 generic_timer_disable_int(GENERIC_TIMER_HYP); 00035 00036 _timer_each_callback_channel(timer_sched, pdata); 00037 00038 generic_timer_set_tval(GENERIC_TIMER_HYP, _channels[timer_sched].interval_us); 00039 00040 generic_timer_enable_int(GENERIC_TIMER_HYP); 00041 } 00042 00043 hvmm_status_t timer_init(timer_channel_t channel) 00044 { 00045 int i; 00046 for( i = 0; i < TIMER_MAX_CHANNEL_CALLBACKS; i++ ) { 00047 _channels[channel].callbacks[i] = 0; 00048 } 00049 00050 generic_timer_init(); 00051 return HVMM_STATUS_SUCCESS; 00052 } 00053 00054 hvmm_status_t timer_start(timer_channel_t channel) 00055 { 00056 if ( _timer_channel_num_callbacks( channel ) > 0 ) { 00057 00058 generic_timer_set_callback(GENERIC_TIMER_HYP, &_timer_hw_callback ); 00059 00060 generic_timer_set_tval(GENERIC_TIMER_HYP, _channels[channel].interval_us); 00061 00062 generic_timer_enable_irq(GENERIC_TIMER_HYP); 00063 00064 generic_timer_enable_int(GENERIC_TIMER_HYP); 00065 } 00066 00067 return HVMM_STATUS_SUCCESS; 00068 } 00069 00070 hvmm_status_t timer_stop(timer_channel_t channel) 00071 { 00072 generic_timer_disable_int(GENERIC_TIMER_HYP); 00073 return HVMM_STATUS_SUCCESS; 00074 } 00075 00076 hvmm_status_t timer_set_interval(timer_channel_t channel, uint32_t interval_us) 00077 { 00078 _channels[channel].interval_us = timer_t2c(interval_us); 00079 return HVMM_STATUS_SUCCESS; 00080 } 00081 00082 uint32_t timer_get_interval(timer_channel_t channel) 00083 { 00084 return _channels[channel].interval_us; 00085 } 00086 00087 hvmm_status_t timer_add_callback(timer_channel_t channel, timer_callback_t callback) 00088 { 00089 int i; 00090 hvmm_status_t result = HVMM_STATUS_BUSY; 00091 for( i = 0; i < TIMER_MAX_CHANNEL_CALLBACKS; i++ ) { 00092 if( _channels[channel].callbacks[i] == 0 ) { 00093 _channels[channel].callbacks[i] = callback; 00094 result = HVMM_STATUS_SUCCESS; 00095 break; 00096 } 00097 } 00098 return result; 00099 } 00100 00101 hvmm_status_t timer_remove_callback(timer_channel_t channel, timer_callback_t callback) 00102 { 00103 int i; 00104 hvmm_status_t result = HVMM_STATUS_NOT_FOUND; 00105 for( i = 0; i < TIMER_MAX_CHANNEL_CALLBACKS; i++ ) { 00106 if ( _channels[channel].callbacks[i] == callback ) { 00107 _channels[channel].callbacks[i] = 0; 00108 result = HVMM_STATUS_SUCCESS; 00109 break; 00110 } 00111 } 00112 return result; 00113 } 00114 00115 uint64_t timer_t2c(uint64_t time_us) 00116 { 00117 return time_us * COUNT_PER_USEC; 00118 }