# HG changeset patch # User nkeynes # Date 1222424950 0 # Node ID b941c703ccd6c7d0a2cccbb87da1c8150449c8e5 # Parent 368fc0dcd57ce2e2eb019e10f89a8e008272427d Improve FRQCR register handling slightly (recognize the PLLEN1 flag) --- a/src/sh4/sh4mmio.h Fri Sep 12 11:59:49 2008 +0000 +++ b/src/sh4/sh4mmio.h Fri Sep 26 10:29:10 2008 +0000 @@ -117,9 +117,16 @@ LONG_PORT( 0x040, DMAOR, PORT_MRW, 0, "DMA operation register" ) MMIO_REGION_END +#define FRQCR_CKOEN 0x0800 +#define FRQCR_PLL1EN 0x0400 +#define FRQCR_PLL2EN 0x0200 +#define FRQCR_IFC_MASK 0x01C0 +#define FRQCR_BFC_MASK 0x0038 +#define FRQCR_PFC_MASK 0x0007 + /* Clock Pulse Generator (page 233 [273] of sh7750h manual) */ MMIO_REGION_BEGIN( 0xFFC00000, CPG, "Clock Pulse Generator" ) - WORD_PORT( 0x000, FRQCR, PORT_MRW, UNDEFINED, "Frequency control" ) + WORD_PORT( 0x000, FRQCR, PORT_MRW, 0x0E0A, "Frequency control" ) BYTE_PORT( 0x004, STBCR, PORT_MRW, 0, "Standby control" ) BYTE_PORT( 0x008, WTCNT, PORT_MRW, 0, "Watchdog timer counter" ) BYTE_PORT( 0x00C, WTCSR, PORT_MRW, 0, "Watchdog timer control/status" ) --- a/src/sh4/timer.c Fri Sep 12 11:59:49 2008 +0000 +++ b/src/sh4/timer.c Fri Sep 26 10:29:10 2008 +0000 @@ -27,18 +27,22 @@ #include "sh4/intc.h" /********************************* CPG *************************************/ -/* This is the base clock from which all other clocks are derived */ +/* This is the base clock from which all other clocks are derived. + * Note: The real clock runs at 33Mhz, which is multiplied by the PLL to + * run the instruction clock at 200Mhz. For sake of simplicity/precision, + * we instead use 200Mhz as the base rate and divide everything down instead. + **/ uint32_t sh4_input_freq = SH4_BASE_RATE; uint32_t sh4_cpu_multiplier = 2000; /* = 0.5 * frequency */ uint32_t sh4_cpu_freq = SH4_BASE_RATE; -uint32_t sh4_bus_freq = SH4_BASE_RATE; -uint32_t sh4_peripheral_freq = SH4_BASE_RATE / 2; +uint32_t sh4_bus_freq = SH4_BASE_RATE / 2; +uint32_t sh4_peripheral_freq = SH4_BASE_RATE / 4; uint32_t sh4_cpu_period = 1000 / SH4_BASE_RATE; /* in nanoseconds */ -uint32_t sh4_bus_period = 1000 / SH4_BASE_RATE; -uint32_t sh4_peripheral_period = 2000 / SH4_BASE_RATE; +uint32_t sh4_bus_period = 2* 1000 / SH4_BASE_RATE; +uint32_t sh4_peripheral_period = 4 * 2000 / SH4_BASE_RATE; int32_t mmio_region_CPG_read( uint32_t reg ) { @@ -53,16 +57,20 @@ void mmio_region_CPG_write( uint32_t reg, uint32_t val ) { uint32_t div; + uint32_t primary_clock = sh4_input_freq; + switch( reg ) { case FRQCR: /* Frequency control */ + if( (val & FRQCR_PLL1EN) == 0 ) + primary_clock /= 6; div = ifc_divider[(val >> 6) & 0x07]; - sh4_cpu_freq = sh4_input_freq / div; + sh4_cpu_freq = primary_clock / div; sh4_cpu_period = sh4_cpu_multiplier * div / sh4_input_freq; div = ifc_divider[(val >> 3) & 0x07]; - sh4_bus_freq = sh4_input_freq / div; + sh4_bus_freq = primary_clock / div; sh4_bus_period = 1000 * div / sh4_input_freq; div = pfc_divider[val & 0x07]; - sh4_peripheral_freq = sh4_input_freq / div; + sh4_peripheral_freq = primary_clock / div; sh4_peripheral_period = 1000 * div / sh4_input_freq; /* Update everything that depends on the peripheral frequency */