Search
lxdream.org :: lxdream/src/sh4/timer.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/timer.c
changeset 619:0800a0137472
prev561:533f6b478071
next736: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 +0000
1.2 +++ b/src/sh4/timer.c Mon May 26 11:01:42 2008 +0000
1.3 @@ -17,12 +17,14 @@
1.4 * GNU General Public License for more details.
1.5 */
1.6
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.19
1.20 /********************************* CPG *************************************/
1.21 /* This is the base clock from which all other clocks are derived */
1.22 @@ -100,8 +102,21 @@
1.23
1.24 /********************************** TMU *************************************/
1.25
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.29
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.41
1.42 #define TCR_ICPF 0x0200
1.43 #define TCR_UNF 0x0100
1.44 @@ -115,22 +130,19 @@
1.45 uint32_t timer_run; /* cycles already run from this slice */
1.46 };
1.47
1.48 -struct TMU_timer TMU_timers[3];
1.49 +static struct TMU_timer TMU_timers[3];
1.50
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.71
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.86
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.95
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.130
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) ) { // reschedule
1.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) ) { // reschedule
1.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) ) { // reschedule
1.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.159
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.177
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 ) );
.