Search
lxdream.org :: lxdream/src/sh4/timer.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/timer.c
changeset 30:89b30313d757
prev23:1ec3acd0594d
next53:f2981805b929
author nkeynes
date Mon Dec 26 10:48:45 2005 +0000 (18 years ago)
permissions -rw-r--r--
last change Remove default MMIO trace
view annotate diff log raw
     1 /**
     2  * $Id: timer.c,v 1.2 2005-12-25 05:57:00 nkeynes Exp $
     3  * 
     4  * SH4 Timer/Clock peripheral modules (CPG, TMU, RTC), combined together to
     5  * keep things simple (they intertwine a bit).
     6  *
     7  * Copyright (c) 2005 Nathan Keynes.
     8  *
     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.
    13  *
    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.
    18  */
    20 #include "dream.h"
    21 #include "mem.h"
    22 #include "clock.h"
    23 #include "sh4core.h"
    24 #include "sh4mmio.h"
    26 /********************************* CPG *************************************/
    28 int32_t mmio_region_CPG_read( uint32_t reg )
    29 {
    30     return MMIO_READ( CPG, reg );
    31 }
    33 void mmio_region_CPG_write( uint32_t reg, uint32_t val )
    34 {
    35     MMIO_WRITE( CPG, reg, val );
    36 }
    38 /********************************** RTC *************************************/
    40 int32_t mmio_region_RTC_read( uint32_t reg )
    41 {
    42     return MMIO_READ( RTC, reg );
    43 }
    45 void mmio_region_RTC_write( uint32_t reg, uint32_t val )
    46 {
    47     MMIO_WRITE( RTC, reg, val );
    48 }
    50 /********************************** TMU *************************************/
    52 int timer_divider[3] = {16,16,16};
    54 int32_t mmio_region_TMU_read( uint32_t reg )
    55 {
    56     return MMIO_READ( TMU, reg );
    57 }
    60 int get_timer_div( int val )
    61 {
    62     switch( val & 0x07 ) {
    63         case 0: return 16; /* assume peripheral clock is IC/4 */
    64         case 1: return 64;
    65         case 2: return 256;
    66         case 3: return 1024;
    67         case 4: return 4096;
    68     }
    69     return 1;
    70 }
    72 void mmio_region_TMU_write( uint32_t reg, uint32_t val )
    73 {
    74     switch( reg ) {
    75         case TCR0:
    76             timer_divider[0] = get_timer_div(val);
    77             break;
    78         case TCR1:
    79             timer_divider[1] = get_timer_div(val);
    80             break;
    81         case TCR2:
    82             timer_divider[2] = get_timer_div(val);
    83             break;
    84     }
    85     MMIO_WRITE( TMU, reg, val );
    86 }
    88 void TMU_run_slice( uint32_t nanosecs )
    89 {
    90     int tcr = MMIO_READ( TMU, TSTR );
    91     int cycles = nanosecs / sh4_peripheral_period;
    92     if( tcr & 0x01 ) {
    93         int count = cycles / timer_divider[0];
    94         int *val = MMIO_REG( TMU, TCNT0 );
    95         if( *val < count ) {
    96             MMIO_READ( TMU, TCR0 ) |= 0x100;
    97             /* interrupt goes here */
    98             count -= *val;
    99             *val = MMIO_READ( TMU, TCOR0 ) - count;
   100         } else {
   101             *val -= count;
   102         }
   103     }
   104     if( tcr & 0x02 ) {
   105         int count = cycles / timer_divider[1];
   106         int *val = MMIO_REG( TMU, TCNT1 );
   107         if( *val < count ) {
   108             MMIO_READ( TMU, TCR1 ) |= 0x100;
   109             /* interrupt goes here */
   110             count -= *val;
   111             *val = MMIO_READ( TMU, TCOR1 ) - count;
   112         } else {
   113             *val -= count;
   114         }
   115     }
   116     if( tcr & 0x04 ) {
   117         int count = cycles / timer_divider[2];
   118         int *val = MMIO_REG( TMU, TCNT2 );
   119         if( *val < count ) {
   120             MMIO_READ( TMU, TCR2 ) |= 0x100;
   121             /* interrupt goes here */
   122             count -= *val;
   123             *val = MMIO_READ( TMU, TCOR2 ) - count;
   124         } else {
   125             *val -= count;
   126         }
   127     }
   128 }
.