1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/sh4/timer.c Fri Dec 23 11:44:55 2005 +0000
1.5 + * $Id: timer.c,v 1.1 2005-12-23 11:44:55 nkeynes Exp $
1.7 + * SH4 Timer/Clock peripheral modules (CPG, TMU, RTC), combined together to
1.8 + * keep things simple (they intertwine a bit).
1.10 + * Copyright (c) 2005 Nathan Keynes.
1.12 + * This program is free software; you can redistribute it and/or modify
1.13 + * it under the terms of the GNU General Public License as published by
1.14 + * the Free Software Foundation; either version 2 of the License, or
1.15 + * (at your option) any later version.
1.17 + * This program is distributed in the hope that it will be useful,
1.18 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.19 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.20 + * GNU General Public License for more details.
1.26 +#include "sh4core.h"
1.27 +#include "sh4mmio.h"
1.29 +/********************************* CPG *************************************/
1.31 +int32_t mmio_region_CPG_read( uint32_t reg )
1.33 + return MMIO_READ( CPG, reg );
1.36 +void mmio_region_CPG_write( uint32_t reg, uint32_t val )
1.38 + MMIO_WRITE( CPG, reg, val );
1.41 +/********************************** RTC *************************************/
1.43 +int32_t mmio_region_RTC_read( uint32_t reg )
1.45 + return MMIO_READ( RTC, reg );
1.48 +void mmio_region_RTC_write( uint32_t reg, uint32_t val )
1.50 + MMIO_WRITE( RTC, reg, val );
1.53 +/********************************** TMU *************************************/
1.55 +int timer_divider[3] = {16,16,16};
1.57 +int32_t mmio_region_TMU_read( uint32_t reg )
1.59 + return MMIO_READ( TMU, reg );
1.63 +int get_timer_div( int val )
1.65 + switch( val & 0x07 ) {
1.66 + case 0: return 16; /* assume peripheral clock is IC/4 */
1.67 + case 1: return 64;
1.68 + case 2: return 256;
1.69 + case 3: return 1024;
1.70 + case 4: return 4096;
1.75 +void mmio_region_TMU_write( uint32_t reg, uint32_t val )
1.79 + timer_divider[0] = get_timer_div(val);
1.82 + timer_divider[1] = get_timer_div(val);
1.85 + timer_divider[2] = get_timer_div(val);
1.88 + MMIO_WRITE( TMU, reg, val );
1.91 +void TMU_run_slice( int microsecs )
1.93 + int tcr = MMIO_READ( TMU, TSTR );
1.94 + int cycles = microsecs * 16 * 200;
1.95 + if( tcr & 0x01 ) {
1.96 + int count = cycles / timer_divider[0];
1.97 + int *val = MMIO_REG( TMU, TCNT0 );
1.98 + if( *val < count ) {
1.99 + MMIO_READ( TMU, TCR0 ) |= 0x100;
1.100 + /* interrupt goes here */
1.102 + *val = MMIO_READ( TMU, TCOR0 ) - count;
1.107 + if( tcr & 0x02 ) {
1.108 + int count = cycles / timer_divider[1];
1.109 + int *val = MMIO_REG( TMU, TCNT1 );
1.110 + if( *val < count ) {
1.111 + MMIO_READ( TMU, TCR1 ) |= 0x100;
1.112 + /* interrupt goes here */
1.114 + *val = MMIO_READ( TMU, TCOR1 ) - count;
1.119 + if( tcr & 0x04 ) {
1.120 + int count = cycles / timer_divider[2];
1.121 + int *val = MMIO_REG( TMU, TCNT2 );
1.122 + if( *val < count ) {
1.123 + MMIO_READ( TMU, TCR2 ) |= 0x100;
1.124 + /* interrupt goes here */
1.126 + *val = MMIO_READ( TMU, TCOR2 ) - count;