The Clock-Pulse Generator on the Prizm, similar to the SH7724’s CPG, allows executing code to dynamically alter the operating frequencies of the various clocks in the SH7305.
Registers #
This section is incorrect as it doesn’t mention the FLL and the individual divisors. Also, there are more than one FRQCR registers.
Frequency Control Register (FRQCR1) #
The FRQCR1 is a longword memory-mapped to 0xA4150000 which can only be accessed as a longword for Read and Write operations. A description of it in technical bit-field breakdown is below:
/*
* FRQCR
* 31: Kick
* Writing 1 here updates CPG settings
* 29-24: PLL
* Multiplier = (PLL + 1) * 2
* 23-20: I_CLK
* CPU Clock Divisor
* 15-12: SH_CLK
* SuperHighway Clock Divisor
* 11-8: B_CLK
* Bus Clock Divisor
* 3-0: P_CLK
* Peripheral Clock Divisor
*
* Divisor values:
* 0000 x1/2
* 0001 x1/3
* 0010 x1/4
* 0011 x1/6
* 0100 x1/8
* 0101 x1/12
* 0110 x1/16
* 1000 x1/24
* 1001 x1/32
* 1010 x1/36
* 1011 x1/48
* 1101 x1/72
*
* Updates to the FRQCR do not go into effect until 1 is written to the kick bit.
*---------------------------------------------------------------------------------
*
* Before using the watchdog timer it migt be necessary to call enable_mtspcr(0, 13),
* this will enable the RCLK signal to the WDT.
*/
FRQCR2 #
Todo
FLL #
Todo
Divisors #
Todo
Usage #
Changing clock frequencies #
This is wrong. The clock speed is effected by the CPU divisor, the PLL, and the FLL multiplier and divisor.
The one circuit that needs to be changed to make a difference in clock speed is the PLL circuit. The Prizm runs at 16x frequency, which is 58MHz (the base frequency is ~3.6MHz). It can be overclocked to at most 87MHz. One can simply write a new longword with the new PLL multiplication value to the FRQCR, and then rewrite it again with the top bit [31] (the FRQCR Kick, which needs to be set to 1 to “kick” the new value into place) set to change the frequencies. Valid PLL multiplication ratios are:
#define PLL_24x 0b010111 // 87 MHz
#define PLL_18x 0b010001 // 65.25 MHz
#define PLL_16x 0b001111 // 58 MHz (NORMAL SPEED)
#define PLL_15x 0b001110 // 54.37 MHz
#define PLL_12x 0b001011 // 43.5 MHz
#define PLL_8x 0b000111 // 29 MHz
#define PLL_6x 0b000101 // 21.75 MHz
#define PLL_4x 0b000011 // 14.5 MHz
#define PLL_3x 0b000010 // 10.8 MHz
#define PLL_2x 0b000001 // 7.25 MHz
#define PLL_1x 0b000000 // 3.6 MHz
Note that there are higher values that you may go to safely if you properly adjust the FLL
Example code #
The below code can be used to change the PLL circuit multiplication:
void change_freq(int mult) {
__asm__(
"mov r4, r0\n\t"
"and #0x3F, r0\n\t"
"shll16 r0\n\t"
"shll8 r0\n\t"
"mov.l frqcr, r1\n\t"
"mov.l pll_mask, r3\n\t"
"mov.l @r1, r2\n\t"
"and r3, r2\n\t"
"or r0, r2\n\t"
"mov.l r2, @r1\n\t"
"mov.l frqcr_kick_bit, r0\n\t"
"mov.l @r1, r2\n\t"
"or r0, r2\n\t"
"rts\n\t"
"mov.l r2, @r1\n\t"
".align 4\n\t"
"frqcr_kick_bit: .long 0x80000000\n\t"
"pll_mask: .long 0xC0FFFFFF\n\t"
"frqcr: .long 0xA4150000\n\t"
);
}
For example, to change into 24x (87MHz) frequency, and back again:
change_freq(PLL_24x);
...
change_freq(PLL_16x);
Notes #
Precautions when changing clock frequencies #
Making the PLL circuit multiplier a non-valid value, will lead to the Prizm crashing.
Note that the Prizm actually uses non-valid values for the divisors, so the list of valid values may be questionable.