172 lines
5.0 KiB

// gint:clock - Clock signals, overclock, and standby modes
#ifndef GINT_CLOCK
#define GINT_CLOCK
#ifdef __cplusplus
extern "C" {
#include <gint/defs/types.h>
/* This header used to expose the sleep() function; include <gint/cpu.h> to
ensure this is still the case */
#include <gint/cpu.h>
// Clock signals
/* clock_frequency_t
A dump of the Clock Pulse Generator's (CPG) configuration. Use the MPU
detection functions from <gint/mpu.h> to use the correct fields. */
typedef struct
union {
int PLL1;
int FLL;
union {
int PLL2;
int PLL;
int Bphi_div;
int Iphi_div;
int Pphi_div;
union {
int CKIO_f;
int RTCCLK_f;
int Bphi_f;
int Iphi_f;
int Pphi_f;
} clock_frequency_t;
/* clock_freq() - get the frequency of the main clocks
This function returns the address of a static object which is used by the
module; this address never changes. */
const clock_frequency_t *clock_freq(void);
/* cpg_compute_freq(): Compute the current clock frequency
This function updates the data structure returned by clock_freq() by
determining the current clock frequencies from the CPG. */
void cpg_compute_freq(void);
// Overclock
/* The following enumerations define the clock speed settings supported by
gint. These are always the settings from Ftune/Ptune, which are the most
widely tested and gint treats as the standard. */
enum {
/* Combinations of hardware settings that are none of Ftune's levels */
/* Ftune's 5 default overclock levels. The main settings are listed below,
thoug many more are involved.
On SH4 fx-9860G-likr:
(Not supported yet)
On the fx G-III series:
(Not supported yet)
On fx-CG 10/20:
F1: CPU @ 58 MHz, BFC @ 29 MHz [Default speed]
F2: CPU @ 58 MHz, BFC @ 29 MHz [Improved memory speed]
F3: CPU @ 118 MHz, BFC @ 58 MHz [Faster than F2]
F4: CPU @ 118 MHz, BFC @ 118 MHz [Fastest bus option]
F5: CPU @ 191 MHz, BFC @ 94 MHz [Fastest CPU option]
On fx-CG 50:
F1: CPU @ 116 MHz, BFC @ 58 MHz [Default speed]
F2: CPU @ 58 MHz, BFC @ 29 MHz [Clearly slower: F2 < F3 < F1]
F3: CPU @ 94 MHz, BFC @ 47 MHz [Clearly slower: F2 < F3 < F1]
F4: CPU @ 232 MHz, BFC @ 58 MHz [Fastest CPU option]
F5: CPU @ 189 MHz, BFC @ 94 MHz [Fastest bus option] */
/* The default clock speed is always Ftune's F1 */
#ifdef FXCG50
/* clock_get_speed(): Determine the current clock speed
This function compares the current hardware state with the settings for each
speed level and returns the current one. If the hardware state does not
correspond to any of Ftune's settings, CLOCK_SPEED_UNKNOWN is returned. */
int clock_get_speed(void);
/* clock_set_speed(): Set the current clock speed
This function sets the clock speed to the desired level. This is "the
overclock function", although depending on the model or settings it is also
the downclocking function.
The process of changing clock speeds is non-trivial, requires waiting for
the DMA to finish its work and slightly affects running timers. You should
avoid changing the clock speed constantly if not necessary. If this function
detects that the desired clock speed is already in use, it returns without
performing any change.
Currently the clock speed is not reset during a world switch nor when
leaving the add-in. */
void clock_set_speed(int speed);
// Sleep functions
/* sleep_us(): Sleep for a fixed duration in microseconds
Stops the processor until the specified delay in microseconds has elapsed.
(The processor will still wake up occasionally to handle interrupts.) This
function selects a timer with timer_setup() called with TIMER_ANY. */
void sleep_us(uint64_t delay_us);
/* sleep_us_spin(): Actively sleep for a fixed duration in microseconds
Like sleep_us(), but uses timer_spinwait() and does not rely on interrupts
being enabled. Useful in timer code running without interrupts. */
void sleep_us_spin(uint64_t delay_us);
/* sleep_ms(): Sleep for a fixed duration in milliseconds */
#define sleep_ms(delay_ms) sleep_us((delay_ms) * 1000ull)
// Low-level overclock functions
// These low-level functions directly read or write registers involved in
// setting the overclock level. Don't use them directly unless you understand
// how their interactions with the environment; instead, use clock_set_speed().
struct cpg_overclock_setting
uint32_t FLLFRQ, FRQCR;
uint32_t CS0BCR, CS2BCR, CS3BCR, CS5aBCR;
uint32_t CS0WCR, CS2WCR, CS3WCR, CS5aWCR;
/* Queries the clock setting from the hardware. */
void cpg_get_overclock_setting(struct cpg_overclock_setting *s);
/* Applies the specified overclock setting. */
void cpg_set_overclock_setting(struct cpg_overclock_setting const *s);
#ifdef __cplusplus
#endif /* GINT_CLOCK */