filename | src/sh4/timer.c |
changeset | 619:0800a0137472 |
prev | 561:533f6b478071 |
next | 736:a02d1475ccfd |
author | nkeynes |
date | Mon May 26 11:01:42 2008 +0000 (15 years ago) |
permissions | -rw-r--r-- |
last change | hange 64-bit configuration to use sizeof(void *) rather than the system id returned by config.guess - config.guess gets it wrong in some situations. |
file | annotate | diff | log | raw |
1.1 --- a/src/sh4/timer.c Tue Jan 01 05:08:38 2008 +00001.2 +++ b/src/sh4/timer.c Mon May 26 11:01:42 2008 +00001.3 @@ -17,12 +17,14 @@1.4 * GNU General Public License for more details.1.5 */1.7 -#include "dream.h"1.8 +#include <assert.h>1.9 +#include "lxdream.h"1.10 #include "mem.h"1.11 #include "clock.h"1.12 -#include "sh4core.h"1.13 -#include "sh4mmio.h"1.14 -#include "intc.h"1.15 +#include "eventq.h"1.16 +#include "sh4/sh4core.h"1.17 +#include "sh4/sh4mmio.h"1.18 +#include "sh4/intc.h"1.20 /********************************* CPG *************************************/1.21 /* This is the base clock from which all other clocks are derived */1.22 @@ -100,8 +102,21 @@1.24 /********************************** TMU *************************************/1.26 +#define TMU_IS_RUNNING(timer) (MMIO_READ(TMU,TSTR) & (1<<timer))1.27 +1.28 uint32_t TMU_count( int timer, uint32_t nanosecs );1.30 +void TMU_event_callback( int eventid )1.31 +{1.32 + TMU_count( eventid - EVENT_TMU0, sh4r.slice_cycle );1.33 +}1.34 +1.35 +void TMU_init(void)1.36 +{1.37 + register_event_callback( EVENT_TMU0, TMU_event_callback );1.38 + register_event_callback( EVENT_TMU1, TMU_event_callback );1.39 + register_event_callback( EVENT_TMU2, TMU_event_callback );1.40 +}1.42 #define TCR_ICPF 0x02001.43 #define TCR_UNF 0x01001.44 @@ -115,22 +130,19 @@1.45 uint32_t timer_run; /* cycles already run from this slice */1.46 };1.48 -struct TMU_timer TMU_timers[3];1.49 +static struct TMU_timer TMU_timers[3];1.51 int32_t mmio_region_TMU_read( uint32_t reg )1.52 {1.53 switch( reg ) {1.54 case TCNT0:1.55 TMU_count( 0, sh4r.slice_cycle );1.56 - TMU_timers[0].timer_run = sh4r.slice_cycle;1.57 break;1.58 case TCNT1:1.59 TMU_count( 1, sh4r.slice_cycle );1.60 - TMU_timers[1].timer_run = sh4r.slice_cycle;1.61 break;1.62 case TCNT2:1.63 TMU_count( 2, sh4r.slice_cycle );1.64 - TMU_timers[2].timer_run = sh4r.slice_cycle;1.65 break;1.66 }1.67 return MMIO_READ( TMU, reg );1.68 @@ -187,10 +199,19 @@1.69 MMIO_WRITE( TMU, TCR0 + (12*timer), tcr );1.70 }1.72 +void TMU_schedule_timer( int timer )1.73 +{1.74 + uint64_t duration = (uint64_t)((uint32_t)(MMIO_READ( TMU, TCNT0 + 12*timer )+1)) *1.75 + (uint64_t)TMU_timers[timer].timer_period - TMU_timers[timer].timer_remainder;1.76 + event_schedule_long( EVENT_TMU0+timer, (uint32_t)(duration / 1000000000),1.77 + (uint32_t)(duration % 1000000000) );1.78 +}1.79 +1.80 void TMU_start( int timer )1.81 {1.82 TMU_timers[timer].timer_run = sh4r.slice_cycle;1.83 TMU_timers[timer].timer_remainder = 0;1.84 + TMU_schedule_timer( timer );1.85 }1.87 /**1.88 @@ -199,7 +220,7 @@1.89 void TMU_stop( int timer )1.90 {1.91 TMU_count( timer, sh4r.slice_cycle );1.92 - TMU_timers[timer].timer_run = sh4r.slice_cycle;1.93 + event_cancel( EVENT_TMU0+timer );1.94 }1.96 /**1.97 @@ -207,25 +228,28 @@1.98 */1.99 uint32_t TMU_count( int timer, uint32_t nanosecs )1.100 {1.101 - nanosecs = nanosecs + TMU_timers[timer].timer_remainder -1.102 + uint32_t run_ns = nanosecs + TMU_timers[timer].timer_remainder -1.103 TMU_timers[timer].timer_run;1.104 TMU_timers[timer].timer_remainder =1.105 - nanosecs % TMU_timers[timer].timer_period;1.106 - uint32_t count = nanosecs / TMU_timers[timer].timer_period;1.107 + run_ns % TMU_timers[timer].timer_period;1.108 + TMU_timers[timer].timer_run = nanosecs;1.109 + uint32_t count = run_ns / TMU_timers[timer].timer_period;1.110 uint32_t value = MMIO_READ( TMU, TCNT0 + 12*timer );1.111 uint32_t reset = MMIO_READ( TMU, TCOR0 + 12*timer );1.112 if( count > value ) {1.113 uint32_t tcr = MMIO_READ( TMU, TCR0 + 12*timer );1.114 tcr |= TCR_UNF;1.115 count -= value;1.116 - value = reset - (count % reset);1.117 + value = reset - (count % reset) + 1;1.118 MMIO_WRITE( TMU, TCR0 + 12*timer, tcr );1.119 if( tcr & TCR_UNIE )1.120 intc_raise_interrupt( INT_TMU_TUNI0 + timer );1.121 + MMIO_WRITE( TMU, TCNT0 + 12*timer, value );1.122 + TMU_schedule_timer(timer);1.123 } else {1.124 value -= count;1.125 + MMIO_WRITE( TMU, TCNT0 + 12*timer, value );1.126 }1.127 - MMIO_WRITE( TMU, TCNT0 + 12*timer, value );1.128 return value;1.129 }1.131 @@ -253,27 +277,53 @@1.132 case TCR2:1.133 TMU_set_timer_control( 2, val );1.134 return;1.135 + case TCNT0:1.136 + MMIO_WRITE( TMU, reg, val );1.137 + if( TMU_IS_RUNNING(0) ) { // reschedule1.138 + TMU_timers[0].timer_run = sh4r.slice_cycle;1.139 + TMU_schedule_timer( 0 );1.140 + }1.141 + return;1.142 + case TCNT1:1.143 + MMIO_WRITE( TMU, reg, val );1.144 + if( TMU_IS_RUNNING(1) ) { // reschedule1.145 + TMU_timers[1].timer_run = sh4r.slice_cycle;1.146 + TMU_schedule_timer( 1 );1.147 + }1.148 + return;1.149 + case TCNT2:1.150 + MMIO_WRITE( TMU, reg, val );1.151 + if( TMU_IS_RUNNING(2) ) { // reschedule1.152 + TMU_timers[2].timer_run = sh4r.slice_cycle;1.153 + TMU_schedule_timer( 2 );1.154 + }1.155 + return;1.156 }1.157 MMIO_WRITE( TMU, reg, val );1.158 }1.160 -void TMU_run_slice( uint32_t nanosecs )1.161 +void TMU_count_all( uint32_t nanosecs )1.162 {1.163 int tcr = MMIO_READ( TMU, TSTR );1.164 if( tcr & 0x01 ) {1.165 TMU_count( 0, nanosecs );1.166 - TMU_timers[0].timer_run = 0;1.167 }1.168 if( tcr & 0x02 ) {1.169 TMU_count( 1, nanosecs );1.170 - TMU_timers[1].timer_run = 0;1.171 }1.172 if( tcr & 0x04 ) {1.173 TMU_count( 2, nanosecs );1.174 - TMU_timers[2].timer_run = 0;1.175 }1.176 }1.178 +void TMU_run_slice( uint32_t nanosecs )1.179 +{1.180 + TMU_count_all( nanosecs );1.181 + TMU_timers[0].timer_run = 0;1.182 + TMU_timers[1].timer_run = 0;1.183 + TMU_timers[2].timer_run = 0;1.184 +}1.185 +1.186 void TMU_update_clocks()1.187 {1.188 TMU_set_timer_control( 0, MMIO_READ( TMU, TCR0 ) );
.