4 * SH4 Timer/Clock peripheral modules (CPG, TMU, RTC), combined together to
5 * keep things simple (they intertwine a bit).
7 * Copyright (c) 2005 Nathan Keynes.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
25 #include "sh4/sh4core.h"
26 #include "sh4/sh4mmio.h"
29 /********************************* CPG *************************************/
30 /* This is the base clock from which all other clocks are derived.
31 * Note: The real clock runs at 33Mhz, which is multiplied by the PLL to
32 * run the instruction clock at 200Mhz. For sake of simplicity/precision,
33 * we instead use 200Mhz as the base rate and divide everything down instead.
35 uint32_t sh4_input_freq = SH4_BASE_RATE;
37 uint32_t sh4_cpu_multiplier = 2000; /* = 0.5 * frequency */
39 uint32_t sh4_cpu_freq = SH4_BASE_RATE;
40 uint32_t sh4_bus_freq = SH4_BASE_RATE / 2;
41 uint32_t sh4_peripheral_freq = SH4_BASE_RATE / 4;
43 uint32_t sh4_cpu_period = 1000 / SH4_BASE_RATE; /* in nanoseconds */
44 uint32_t sh4_bus_period = 2* 1000 / SH4_BASE_RATE;
45 uint32_t sh4_peripheral_period = 4 * 2000 / SH4_BASE_RATE;
47 MMIO_REGION_READ_FN( CPG, reg )
49 return MMIO_READ( CPG, reg&0xFFF );
51 MMIO_REGION_READ_DEFSUBFNS(CPG)
53 /* CPU + bus dividers (note officially only the first 6 values are valid) */
54 int ifc_divider[8] = { 1, 2, 3, 4, 5, 8, 8, 8 };
55 /* Peripheral clock dividers (only first 5 are officially valid) */
56 int pfc_divider[8] = { 2, 3, 4, 6, 8, 8, 8, 8 };
58 MMIO_REGION_WRITE_FN( CPG, reg, val )
61 uint32_t primary_clock = sh4_input_freq;
64 case FRQCR: /* Frequency control */
65 if( (val & FRQCR_PLL1EN) == 0 )
67 div = ifc_divider[(val >> 6) & 0x07];
68 sh4_cpu_freq = primary_clock / div;
69 sh4_cpu_period = sh4_cpu_multiplier * div / sh4_input_freq;
70 div = ifc_divider[(val >> 3) & 0x07];
71 sh4_bus_freq = primary_clock / div;
72 sh4_bus_period = 1000 * div / sh4_input_freq;
73 div = pfc_divider[val & 0x07];
74 sh4_peripheral_freq = primary_clock / div;
75 sh4_peripheral_period = 1000 * div / sh4_input_freq;
77 /* Update everything that depends on the peripheral frequency */
78 SCIF_update_line_speed();
80 case WTCSR: /* Watchdog timer */
84 MMIO_WRITE( CPG, reg, val );
88 * We don't really know what the default reset value is as it's determined
89 * by the mode select pins. This is the standard value that the BIOS sets,
90 * however, so it works for now.
94 mmio_region_CPG_write( FRQCR, 0x0E0A );
98 /********************************** RTC *************************************/
100 uint32_t rtc_output_period;
102 MMIO_REGION_READ_FN( RTC, reg )
104 return MMIO_READ( RTC, reg &0xFFF );
106 MMIO_REGION_READ_DEFSUBFNS(RTC)
108 MMIO_REGION_WRITE_FN( RTC, reg, val )
110 MMIO_WRITE( RTC, reg &0xFFF, val );
113 /********************************** TMU *************************************/
115 #define TMU_IS_RUNNING(timer) (MMIO_READ(TMU,TSTR) & (1<<timer))
117 uint32_t TMU_count( int timer, uint32_t nanosecs );
119 void TMU_event_callback( int eventid )
121 TMU_count( eventid - EVENT_TMU0, sh4r.slice_cycle );
126 register_event_callback( EVENT_TMU0, TMU_event_callback );
127 register_event_callback( EVENT_TMU1, TMU_event_callback );
128 register_event_callback( EVENT_TMU2, TMU_event_callback );
131 #define TCR_ICPF 0x0200
132 #define TCR_UNF 0x0100
133 #define TCR_UNIE 0x0020
135 #define TCR_IRQ_ACTIVE (TCR_UNF|TCR_UNIE)
138 uint32_t timer_period;
139 uint32_t timer_remainder; /* left-over cycles from last count */
140 uint32_t timer_run; /* cycles already run from this slice */
143 static struct TMU_timer TMU_timers[3];
145 void TMU_set_timer_control( int timer, int tcr )
148 uint32_t oldtcr = MMIO_READ( TMU, TCR0 + (12*timer) );
150 if( (oldtcr & TCR_UNF) == 0 ) {
151 tcr = tcr & (~TCR_UNF);
153 if( ((oldtcr & TCR_UNIE) == 0) &&
154 (tcr & TCR_IRQ_ACTIVE) == TCR_IRQ_ACTIVE ) {
155 intc_raise_interrupt( INT_TMU_TUNI0 + timer );
156 } else if( (oldtcr & TCR_UNIE) != 0 &&
157 (tcr & TCR_IRQ_ACTIVE) != TCR_IRQ_ACTIVE ) {
158 intc_clear_interrupt( INT_TMU_TUNI0 + timer );
162 switch( tcr & 0x07 ) {
164 period = sh4_peripheral_period << 2 ;
167 period = sh4_peripheral_period << 4;
170 period = sh4_peripheral_period << 6;
173 period = sh4_peripheral_period << 8;
176 period = sh4_peripheral_period << 10;
180 ERROR( "TMU %d period set to illegal value (5)", timer );
181 period = sh4_peripheral_period << 12; /* for something to do */
184 period = rtc_output_period;
187 /* External clock... Hrm? */
188 period = sh4_peripheral_period; /* I dunno... */
191 TMU_timers[timer].timer_period = period;
193 MMIO_WRITE( TMU, TCR0 + (12*timer), tcr );
196 void TMU_schedule_timer( int timer )
198 uint64_t duration = (uint64_t)((uint32_t)(MMIO_READ( TMU, TCNT0 + 12*timer )+1)) *
199 (uint64_t)TMU_timers[timer].timer_period - TMU_timers[timer].timer_remainder;
200 event_schedule_long( EVENT_TMU0+timer, (uint32_t)(duration / 1000000000),
201 (uint32_t)(duration % 1000000000) );
204 void TMU_start( int timer )
206 TMU_timers[timer].timer_run = sh4r.slice_cycle;
207 TMU_timers[timer].timer_remainder = 0;
208 TMU_schedule_timer( timer );
212 * Stop the given timer. Run it up to the current time and leave it there.
214 void TMU_stop( int timer )
216 TMU_count( timer, sh4r.slice_cycle );
217 event_cancel( EVENT_TMU0+timer );
221 * Count the specified timer for a given number of nanoseconds.
223 uint32_t TMU_count( int timer, uint32_t nanosecs )
225 uint32_t run_ns = nanosecs + TMU_timers[timer].timer_remainder -
226 TMU_timers[timer].timer_run;
227 TMU_timers[timer].timer_remainder =
228 run_ns % TMU_timers[timer].timer_period;
229 TMU_timers[timer].timer_run = nanosecs;
230 uint32_t count = run_ns / TMU_timers[timer].timer_period;
231 uint32_t value = MMIO_READ( TMU, TCNT0 + 12*timer );
232 uint32_t reset = MMIO_READ( TMU, TCOR0 + 12*timer );
233 if( count > value ) {
234 uint32_t tcr = MMIO_READ( TMU, TCR0 + 12*timer );
237 value = reset - (count % reset) + 1;
238 MMIO_WRITE( TMU, TCR0 + 12*timer, tcr );
240 intc_raise_interrupt( INT_TMU_TUNI0 + timer );
241 MMIO_WRITE( TMU, TCNT0 + 12*timer, value );
242 TMU_schedule_timer(timer);
245 MMIO_WRITE( TMU, TCNT0 + 12*timer, value );
250 MMIO_REGION_READ_FN( TMU, reg )
255 TMU_count( 0, sh4r.slice_cycle );
258 TMU_count( 1, sh4r.slice_cycle );
261 TMU_count( 2, sh4r.slice_cycle );
264 return MMIO_READ( TMU, reg );
266 MMIO_REGION_READ_DEFSUBFNS(TMU)
269 MMIO_REGION_WRITE_FN( TMU, reg, val )
276 oldval = MMIO_READ( TMU, TSTR );
277 for( i=0; i<3; i++ ) {
279 if( (oldval & tmp) != 0 && (val&tmp) == 0 )
281 else if( (oldval&tmp) == 0 && (val&tmp) != 0 )
286 TMU_set_timer_control( 0, val );
289 TMU_set_timer_control( 1, val );
292 TMU_set_timer_control( 2, val );
295 MMIO_WRITE( TMU, reg, val );
296 if( TMU_IS_RUNNING(0) ) { // reschedule
297 TMU_timers[0].timer_run = sh4r.slice_cycle;
298 TMU_schedule_timer( 0 );
302 MMIO_WRITE( TMU, reg, val );
303 if( TMU_IS_RUNNING(1) ) { // reschedule
304 TMU_timers[1].timer_run = sh4r.slice_cycle;
305 TMU_schedule_timer( 1 );
309 MMIO_WRITE( TMU, reg, val );
310 if( TMU_IS_RUNNING(2) ) { // reschedule
311 TMU_timers[2].timer_run = sh4r.slice_cycle;
312 TMU_schedule_timer( 2 );
316 MMIO_WRITE( TMU, reg, val );
319 void TMU_count_all( uint32_t nanosecs )
321 int tcr = MMIO_READ( TMU, TSTR );
323 TMU_count( 0, nanosecs );
326 TMU_count( 1, nanosecs );
329 TMU_count( 2, nanosecs );
333 void TMU_run_slice( uint32_t nanosecs )
335 TMU_count_all( nanosecs );
336 TMU_timers[0].timer_run = 0;
337 TMU_timers[1].timer_run = 0;
338 TMU_timers[2].timer_run = 0;
341 void TMU_update_clocks()
343 TMU_set_timer_control( 0, MMIO_READ( TMU, TCR0 ) );
344 TMU_set_timer_control( 1, MMIO_READ( TMU, TCR1 ) );
345 TMU_set_timer_control( 2, MMIO_READ( TMU, TCR2 ) );
350 TMU_timers[0].timer_remainder = 0;
351 TMU_timers[0].timer_run = 0;
352 TMU_timers[1].timer_remainder = 0;
353 TMU_timers[1].timer_run = 0;
354 TMU_timers[2].timer_remainder = 0;
355 TMU_timers[2].timer_run = 0;
359 void TMU_save_state( FILE *f ) {
360 fwrite( &TMU_timers, sizeof(TMU_timers), 1, f );
363 int TMU_load_state( FILE *f )
365 fread( &TMU_timers, sizeof(TMU_timers), 1, f );
.