diff --git a/include/gint/hardware.h b/include/gint/hardware.h new file mode 100644 index 0000000..84b99ff --- /dev/null +++ b/include/gint/hardware.h @@ -0,0 +1,189 @@ +//--- +// gint:hardware - Platform information and hardware detection +// +// This components centralizes detected information about the runtime +// hardware, including MPU version, peripheral modules, and how drivers +// configured them. +// +// The most common use of this header is for the isSH3() and isSH4() +// macros that let you run MPU-dependent jobs and are used like this: +// if(isSH3()) do_sh3(); +// else do_sh4(); +//--- + +#ifndef GINT_PLATFORM +#define GINT_PLATFORM + +#include + +/* Most of the information here is going to be stored in (key, value) pairs for + predetermined keys and 32-bits values that are often integers or a set of + flags. The data will be filled by gint or its drivers. */ + +#define HW_KEYS 16 +extern uint32_t gint[HW_KEYS]; + +/* MPU detection macros, with a faster version on fx-CG 50 */ + +#ifdef FX9860G +#define isSH3() (gint[HWMPU] & 1) +#define isSH4() (!isSH3()) +#endif + +#ifdef FXCG50 +#define isSH3() 0 +#define isSH4() 1 +#endif + +/* hw_detect(): Basic hardware detection + This function probes the hardware and fills in the HWMPU, HWCPUVR and + HWCPUPR fields. */ +void hw_detect(void); + +/* This bit should be set in all data longwords except HWMPU, HWCPUVR, HWCPUPR + and HWCALC which are guaranteed to always be loaded. If not set then the + information must be treated as invalid. */ +#define HW_LOADED 0x80000000 + +/* +** Key list +*/ + +#define HWMPU 0 /* MPU type */ +#define HWCPUVR 1 /* CPU Version Register */ +#define HWCPUPR 2 /* CPU Product Register */ +#define HWCALC 3 /* Calculator model */ +#define HWRAM 4 /* Amount of RAM */ +#define HWROM 5 /* Amount of ROM */ +#define HWMMU 6 /* Memory Management Unit */ +#define HWURAM 7 /* Userspace RAM (set iff HWMMU is loaded) */ +#define HWCPG 8 /* Clock Pulse Generator */ +#define HWDMA 9 /* Direct Memory Access Controller */ +#define HWTMU 10 /* Timer Unit */ +#define HWETMU 11 /* Extra Timer Units */ +#define HWRTC 12 /* Real-Time Clock */ +#define HWKBD 13 /* Keyboard */ +#define HWKBDSF 14 /* Keyboard Scan Frequency (set iff HWKBD is loaded) */ +#define HWDD 15 /* Display Driver */ + +/* +** MPU type +*/ + +/* Unknown MPUs are all assumed to be SH-4A-based */ +#define HWMPU_UNKNOWN 0 +/* Used on original fx-9860G, SH-3-based */ +#define HWMPU_SH7337 1 +/* Used on recent fx-9860G derivates such as the fx-9750G II, and also on the + fx-CG 10/20/50. SH-4A-based */ +#define HWMPU_SH7305 2 +/* Used on the fx-9860G II, SH-3-based */ +#define HWMPU_SH7355 3 +/* Closest documented match to the SH7305, not used in any known calculator. + Detected and included for reference only */ +#define HWMPU_SH7724 4 + +/* +** Calculator type +*/ + +/* SH-3-based fx-9860G-family */ +#define HWCALC_FX9860G_SH3 1 +/* Other SH-4A-based fx-9860G-family */ +#define HWCALC_FX9860G_SH4 2 +/* Graph 35+E II, an SH-4A French extension of the fx-9860G family */ +#define HWCALC_G35PE2 3 +/* fx-CG 10/20, also known as the "Prizm" family */ +#define HWCALC_PRIZM 4 +/* fx-CG 50, a late extension to the Prizm family */ +#define HWCALC_FXCG50 5 + +/* +** Memory Management Unit +*/ + +/* MMU has a unified TLB. Essentially correlated with SH4. */ +#define HWMMU_UTLB 0x01 +/* Add-in is fully mapped in the TLB. This means that gint needs not handle TLB + misses as exceptions. This should generally be set on fx9860g, but not on + fxcg50. */ +#define HWMMU_FITTLB 0x02 + +/* +** Clock Pulse Generator +*/ + +/* Input clock frequency is known for this model and all frequencies are + computed (they used to be measured from the RTC). Should be 1 */ +#define HWCPG_COMP 0x01 +/* Used an extended CPG interface, correlated with SH4 */ +#define HWCPG_EXT 0x02 + +/* +** Direct Memory Access Controller +*/ + +/* Nothing other than the HW_LOADED bit yet */ + +/* +** Timer Unit +*/ + +/* Nothing other than the HW_LOADED bit yet */ + +/* +** Extra Timer Units +*/ + +/* A single-timer ETMU unit was found. Correlated with SH3 */ +#define HWETMU_1 0x01 +/* A 6-timer ETMU unit was found. Correlated with SH4 */ +#define HWETMU_6 0x02 +/* Individual timer status. Not all timers might be operational after setting + up the driver due to seemingly limitless behavioral differences with the + TMU. Operational here means TCNT=TCOR=-1, interrupt disabled and cleared. */ +#define HWETMU_OK0 0x04 +#define HWETMU_OK1 0x08 +#define HWETMU_OK2 0x10 +#define HWETMU_OK3 0x20 +#define HWETMU_OK4 0x40 +#define HWETMU_OK5 0x80 + +/* +** Real-Time Clock +*/ + +/* The RTC timer is enabled */ +#define HWRTC_TIMER 0x01 + +/* +** Keyboard +*/ + +/* The keyboard uses an I/O-port-based scan method. This is possible on both + SH3 and SH4, but gint will normally do it only on SH3. */ +#define HWKBD_IO 0x01 +/* When using the I/O-port scanning method on SH3, whether the watchdog is used + to delay I/O operations. */ +#define HWKBD_WDD 0x02 +/* The keyboard uses a KEYSC-based scan method. This is only possible on SH4 */ +#define HWKBD_KSI 0x04 + +/* +** Display Driver +*/ + +/* Display driver is known. This cannot be determined on fx9860g as the Toshiba + T6K11 and its Graph 35+E II variant don't seem to have an identification + command. It is set to 0 on fx9860g and used on fxcg50. */ +#define HWDD_KNOWN 0x01 +/* The display driver was configured to use the full screen, instead of leaving + bands on the side. [fxcg50] */ +#define HWDD_FULL 0x02 +/* The contrast address for this OS version is known. [fx9860g] */ +#define HWDD_CONTRAST 0x04 +/* Backlight management is supported. This is used both on fx9860g models with + backlit screen (although that very fact cannot be detected) and fxcg50. */ +#define HWDD_LIGHT 0x08 + +#endif /* GINT_PLATFORM */ diff --git a/include/gint/mpu.h b/include/gint/mpu.h deleted file mode 100644 index ef4ee95..0000000 --- a/include/gint/mpu.h +++ /dev/null @@ -1,87 +0,0 @@ -//--- -// gint:core:mpu - Runtime MPU detection -// -// This component detects the architecture and MPU type of the underlying -// hardware by relying on version registers and/or side-information. It -// provides macros isSH3() and isSH4() for MPU-dependent jobs -// -// if(isSH3()) print("SH3 code"); -// else print("SH4 code"); -//--- - -#ifndef GINT_CORE_MPU -#define GINT_CORE_MPU - -#include - -/* mpu_t - supported MPUs */ -typedef enum -{ - mpu_unknown = 0, - mpu_sh7337 = 1, /* fx9860g, SH-3 based */ - mpu_sh7305 = 2, /* fx9860g II, fxcg50, SH-4A based */ - mpu_sh7355 = 3, /* fx9860g II, SH-3 based */ - mpu_sh7724 = 4, /* For reference */ -} mpu_t; - - - -/* On fx9860g, the 256k byte RAM might be extended to 512k if the machine is - recent enough. This includes all SH4 and many SH3 fx-9750 GII; the only - model known to not have it is the old fx-9860G. */ -#ifdef FX9860G - -typedef struct -{ - /* MPU type, one of the above values */ - mpu_t mpu; - /* Extended RAM area (8804'0000:256k) is available */ - int extended_ram; - -} platform_t; - -/* mpu_id() - get the name of the underlying MPU */ -#define gint_mpu() (gint_platform.mpu) - -/* Quick SH-3/SH-4 tests. Unknown models are assumed to be SH-4A */ -#define isSH3() (gint_mpu() & 1) -#define isSH4() (!isSH3()) - -#endif /* FX9860G */ - - - -/* On fxcg50, the processor is always SH4. We can still differentiate between - modern fx-CG 50 and older fx-CG 10/20 which are called here "Prizm". (This - is done by observing the initial stack pointer.) */ -#ifdef FXCG50 - -typedef struct -{ - /* MPU type (always sh7305) */ - mpu_t mpu; - /* Whether this is an fx-CG 10/20 Prizm instead of an fx-CG 50 */ - int prizm; - -} platform_t; - -/* All fxcg50 machines have an SH7305, which makes things simpler. */ -#define gint_mpu() mpu_sh7305 -#define isSH3() 0 -#define isSH4() 1 - -#endif /* FX9860G */ - - - -/* Platform details collected by mpu_init() */ -extern const platform_t gint_platform; - -/* mpu_init() - detect hardware information - This function must be executed before other functions of this header can be - used successfully. - - @stack Starting stack address (roughly is enough) */ -void mpu_init(uint32_t stack); - -#endif /* GINT_CORE_MPU */ diff --git a/include/gint/timer.h b/include/gint/timer.h index 064823b..01af28d 100644 --- a/include/gint/timer.h +++ b/include/gint/timer.h @@ -6,7 +6,7 @@ #define GINT_TIMER #include -#include +#include /* Timer identifiers diff --git a/src/clock/freq.c b/src/clock/freq.c index 5c020c9..3ece5e8 100644 --- a/src/clock/freq.c +++ b/src/clock/freq.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include //--- @@ -65,6 +65,8 @@ static void sh7705_probe(void) freq.Bphi_f = ckio; freq.Iphi_f = (idiv == 3) ? ckio_3 : ckio >> idiv; freq.Pphi_f = (pdiv == 3) ? ckio_3 : ckio >> pdiv; + + gint[HWCPG] |= HWCPG_COMP; } #undef CPG @@ -109,6 +111,8 @@ static void sh7305_probe(void) freq.Bphi_f = base >> (divb + 1); freq.Iphi_f = base >> (divi + 1); freq.Pphi_f = base >> (divp + 1); + + gint[HWCPG] |= HWCPG_COMP | HWCPG_EXT; } #undef CPG @@ -135,11 +139,13 @@ static const char *cpg_status(void) static void init(void) { - /* This avoids warnings about sh7705() not being defined on fxcg50 */ + gint[HWCPG] = HW_LOADED; + + /* This avoids warnings about sh7705_probe() being undefined when + building for fxcg50 */ #ifdef FX9860G isSH3() ? sh7705_probe() : #endif - sh7305_probe(); } diff --git a/src/core/bootlog.c b/src/core/bootlog.c index b8b3236..ef57ef3 100644 --- a/src/core/bootlog.c +++ b/src/core/bootlog.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include @@ -65,22 +65,22 @@ void bootlog_loaded(void) uint32_t gint_size = (uint32_t)&sgdata + (uint32_t)&sgbss; /* MPU type */ - mpu_t mpu = gint_mpu(); + int mpu = gint[HWMPU]; const char *names = "SH7337\0 SH7305\0 SH7355\0 SH7724"; /* TODO: Use a solid API for boot-time printing */ dclear(color_white); print(1, 1, "gint @%7x SLmkd", GINT_VERSION); - if((uint)mpu < 4) print(1, 2, names + 8 * (mpu - 1)); + if(mpu >= 1 && mpu <= 4) print(1, 2, names + 8 * (mpu - 1)); else print(1, 2, "%6d", mpu); #ifdef FX9860G - print(8, 2, "%c?-", gint_platform.extended_ram ? 'R' : 'r'); + print(8, 2, "%c?-", gint[HWRAM] >= (512 << 10) ? 'R' : 'r'); #endif #ifdef FXCG50 - print(8, 2, "--%c", gint_platform.prizm ? 'P' : 'p'); + print(8, 2, "---"); #endif char os[11]; diff --git a/src/core/gint.c b/src/core/gint.c index 987210c..fff389d 100644 --- a/src/core/gint.c +++ b/src/core/gint.c @@ -4,7 +4,7 @@ #include #include -#include +#include #include /* Interrupt controllers */ diff --git a/src/core/hardware.c b/src/core/hardware.c new file mode 100644 index 0000000..c756610 --- /dev/null +++ b/src/core/hardware.c @@ -0,0 +1,115 @@ +//--- +// gint:core:hardware - Platform information and hardware detection +//--- + +#include +#include +#include +#include +#include + +/* Holds information about the current platform */ +GBSS uint32_t gint[HW_KEYS]; + +/* Processor Version Register */ +#define PVR (*((volatile uint32_t *)0xff000030)) +/* Product Register */ +#define PRR (*((volatile uint32_t *)0xff000044)) + +#ifdef FX9860G + +/* mpu_detect() - detect the underlying MPU + Many thanks to Simon Lothar for relevant documentation. + + Processor Version Register (PVR) and Product Version Register (PRR) provide + info for SH-4-based MPUS; SH-3 based boards are detected and distinguished + by testing writable bits in the Port L Control Register (PLCR). + + Returns the detected MPU type, falling back on mpu_unknown */ +GSECTION(".pretext") +static int mpu_detect(void) +{ + #define PLCR SH7705_PFC.PLCR + + /* Detect SH-3-based MPUs by testing writable bits in PLCR */ + uint16_t old = PLCR; + PLCR = 0xffff; + uint16_t tested = PLCR; + PLCR = old; + + if(tested == 0x00ff) return HWMPU_SH7337; + if(tested == 0x0fff) return HWMPU_SH7355; + + /* Check that we're dealing with an SH-4-based MPU */ + if((PVR & 0xffffff00) != 0x10300b00) return HWMPU_UNKNOWN; + + /* Tell SH-4 MPUs by testing the product version register */ + + uint32_t ver = PRR & 0xfffffff0; + if(ver == 0x00002c00) return HWMPU_SH7305; + if(ver == 0x00002200) return HWMPU_SH7724; + + return HWMPU_UNKNOWN; + #undef PLCR +} + +/* hw_detect(): Basic hardware detection */ +GSECTION(".pretext") +void hw_detect(void) +{ + gint[HWMPU] = mpu_detect(); + + if(isSH4()) + { + gint[HWCPUVR] = PVR; + gint[HWCPUPR] = PRR; + } + + /* Detect RAM by checking if 8804'0000 is the same as 8800'0000. */ + + volatile uint8_t *R4 = (void *)0x88040000; + volatile uint8_t *R0 = (void *)0x88000000; + + /* Make backups */ + uint8_t b0 = *R0; + uint8_t b4 = *R4; + + /* Check if setting a different value in *R4 affects *R0. If not, then + we have extended RAM. */ + *R4 = ~b0; + int ext = (*R0 == b0); + + /* Restore backups */ + *R0 = b0; + *R4 = b4; + + gint[HWRAM] = ext ? (512 << 10) : (256 << 10); + /* Will be detected later on */ + gint[HWURAM] = -1; + /* Traditionally 4 MiB, Graph 35+E II has 8 MiB */ + gint[HWROM] = (gint[HWCALC] == HWCALC_G35PE2) ? (4 << 20) : (8 << 20); +} + +#endif /* FX9860G */ + +#ifdef FXCG50 + +/* hw_detect(): Basic hardware detection */ +GSECTION(".pretext") +void hw_detect(void) +{ + gint[HWMPU] = HWMPU_SH7305; + gint[HWCPUVR] = PVR; + gint[HWCPUPR] = PRR; + + /* Tell Prizms apart from fx-CG 50 by checking the stack address*/ + uint32_t stack; + __asm__("mov r15, %0" : "=r"(stack)); + gint[HWCALC] = (stack < 0x8c160000) ? HWCALC_PRIZM : HWCALC_FXCG50; + + /* Basic memory information */ + gint[HWRAM] = (2 << 20); + gint[HWROM] = (32 << 20); +} + +#endif /* FXCG50 */ diff --git a/src/core/mmu.c b/src/core/mmu.c index cd0c889..b8ab0a4 100644 --- a/src/core/mmu.c +++ b/src/core/mmu.c @@ -3,6 +3,7 @@ //--- #include +#include //--- // SH7705 TLB @@ -48,6 +49,9 @@ void tlb_mapped_memory(uint32_t *p_rom, uint32_t *p_ram) if(p_rom) *p_rom = rom; if(p_ram) *p_ram = ram; + + gint[HWMMU] = HW_LOADED; + gint[HWURAM] = ram; } #endif @@ -92,4 +96,7 @@ void utlb_mapped_memory(uint32_t *p_rom, uint32_t *p_ram) if(p_rom) *p_rom = rom; if(p_ram) *p_ram = ram; + + gint[HWMMU] = HW_LOADED | HWMMU_UTLB; + gint[HWURAM] = ram; } diff --git a/src/core/mpu.c b/src/core/mpu.c deleted file mode 100644 index ded69a4..0000000 --- a/src/core/mpu.c +++ /dev/null @@ -1,90 +0,0 @@ -//--- -// gint:core:mpu - Runtime MPU detection -//--- - -#include -#include -#include -#include - -/* Holds information about the current MPU */ -GBSS const platform_t gint_platform; - -/* This function is only used on fx9860g because all fxcg50 are SH4 */ -#ifdef FX9860G - -/* mpu_detect() - detect the underlying MPU - Many thanks to Simon Lothar for relevant documentation. - - Processor Version Register (PVR) and Product Version Register (PRR) provide - info for SH-4-based MPUS; SH-3 based boards are detected and distinguished - by testing writable bits in the Port L Control Register (PLCR). - - Returns the detected MPU type, falling back on mpu_unknown */ -GSECTION(".pretext") -static mpu_t mpu_detect(void) -{ - /* Processor Version Register */ - volatile uint32_t *pvr = (void *)0xff000030; - /* Product Version Register */ - volatile uint32_t *prr = (void *)0xff000044; - /* Port L Control Register */ - volatile uint16_t *plcr = (void *)0xa4000114; - - /* Detecting SH-3-based MPUs by testing writable bits in PLCR */ - - uint16_t old = *plcr; - *plcr = 0xffff; - uint16_t tested = *plcr; - *plcr = old; - - if(tested == 0x00ff) return mpu_sh7337; - if(tested == 0x0fff) return mpu_sh7355; - - /* Check that we're dealing with an SH-4-based MPU */ - if((*pvr & 0xffffff00) != 0x10300b00) return mpu_unknown; - - /* Tell SH-4 MPUs by testing the product version register */ - - uint32_t ver = *prr & 0xfffffff0; - if(ver == 0x00002c00) return mpu_sh7305; - if(ver == 0x00002200) return mpu_sh7724; - - return mpu_unknown; -} - -/* mpu_init() - detect and save information about the underlying MPU */ -GSECTION(".pretext") -void mpu_init(GUNUSED uint32_t stack) -{ - const_cast(gint_platform.mpu, mpu_t) = mpu_detect(); - - /* Detect additional RAM */ - - volatile uint8_t *after_ram = (void *)0x88040000; - volatile uint8_t *start_ram = (void *)0x88000000; - - uint8_t backup = *after_ram; - *after_ram = ~backup; - int ext = (*start_ram == backup); - *after_ram = backup; - - const_cint(gint_platform.extended_ram) = ext; -} - -#endif /* FX9860G */ - -#ifdef FXCG50 - -/* mpu_init() - detect and save information about the underlying MPU */ -GSECTION(".pretext") -void mpu_init(uint32_t stack) -{ - const_cast(gint_platform.mpu, mpu_t) = mpu_sh7305; - - /* Detect Prizm models */ - int prizm = (stack < 0x8c160000); - const_cint(gint_platform.prizm) = prizm; -} - -#endif /* FXCG50 */ diff --git a/src/core/setup.c b/src/core/setup.c index 4752799..ff88e54 100644 --- a/src/core/setup.c +++ b/src/core/setup.c @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include /* VBR address, from the linker script */ diff --git a/src/core/start.c b/src/core/start.c index 55e38eb..d7117da 100644 --- a/src/core/start.c +++ b/src/core/start.c @@ -1,5 +1,5 @@ //--- -// gint:core:start - Kernel initialisation and C runtime +// gint:core:start - Kernel initialization and C runtime //-- #include @@ -8,7 +8,7 @@ #include #include #include -#include +#include /* Symbols provided by the linker script. For sections: - l* represents the load address (source address in ROM) @@ -114,9 +114,7 @@ int start(int isappli, int optnum) processor with some incompatible features */ /* Detect architecture - this will tell SH3 from SH4 on fx9860g */ - uint32_t stack; - __asm__("mov r15, %0" : "=r"(stack)); - mpu_init(stack); + hw_detect(); /* Load data sections and wipe the bss section. This has to be done first for static and global variables to be initialized */ diff --git a/src/dma/dma.c b/src/dma/dma.c index f768e0e..09b36fb 100644 --- a/src/dma/dma.c +++ b/src/dma/dma.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -116,6 +116,8 @@ static void init(void) /* Unmask the DMA0 interrupt */ INTC.MSKCLR->IMR1 = 0x01; + + gint[HWDMA] = HW_LOADED; } //--- diff --git a/src/keysc/keysc.c b/src/keysc/keysc.c index fca2edf..63bd3f2 100644 --- a/src/keysc/keysc.c +++ b/src/keysc/keysc.c @@ -10,7 +10,7 @@ #include #include -#include +#include //--- // Keyboard buffer @@ -183,6 +183,9 @@ static void init(void) timer_setup(tid, delay, 0, callback, NULL); timer_start(tid); + + gint[HWKBD] = HW_LOADED | (isSH3() ? HWKBD_IO : HWKBD_KSI); + gint[HWKBDSF] = KEYBOARD_SCAN_FREQUENCY; } /* unload() - stop the support timer */ diff --git a/src/r61524/r61524.c b/src/r61524/r61524.c index 969af31..5e82eca 100644 --- a/src/r61524/r61524.c +++ b/src/r61524/r61524.c @@ -3,6 +3,7 @@ //--- #include +#include #include #include #include @@ -260,6 +261,19 @@ static void ctx_restore(void *buf) r61524_win_set(ctx->HSA, ctx->HEA, ctx->VSA, ctx->VEA); } +//--- +// Driver initialization +//--- + +static void init(void) +{ + select(device_code_read); + uint16_t devname = read(); + + gint[HWDD] = HW_LOADED | HWDD_FULL; + if(devname == 0x1524) gint[HWDD] |= HWDD_KNOWN; +} + //--- // Driver status string //--- @@ -285,7 +299,7 @@ static const char *r61524_status(void) gint_driver_t drv_r61524 = { .name = "R61524", - .init = NULL, + .init = init, .status = GINT_DRIVER_STATUS(r61524_status), .ctx_size = sizeof(ctx_t), .sys_ctx = &sys_ctx, diff --git a/src/rtc/rtc.c b/src/rtc/rtc.c index 9405e1b..7ac99f9 100644 --- a/src/rtc/rtc.c +++ b/src/rtc/rtc.c @@ -7,7 +7,7 @@ #include #include -#include +#include #include //--- @@ -150,6 +150,8 @@ static void init(void) /* Disable the periodic interrupt for now, but give it priority 5 */ RTC->RCR2.PES = RTC_NONE; gint_intlevel(isSH3() ? 3 : 40, 5); + + gint[HWRTC] = HW_LOADED | HWRTC_TIMER; } //--- diff --git a/src/std/memory.c b/src/std/memory.c index 41861cf..d3b9384 100644 --- a/src/std/memory.c +++ b/src/std/memory.c @@ -1,5 +1,5 @@ #include -#include +#include #include #include diff --git a/src/t6k11/t6k11.c b/src/t6k11/t6k11.c index e0b37ce..1af6eb6 100644 --- a/src/t6k11/t6k11.c +++ b/src/t6k11/t6k11.c @@ -7,7 +7,7 @@ #include #include -#include +#include #include @@ -222,6 +222,15 @@ static void ctx_restore(void *buf) command(reg_counter, cnt); } +//--- +// Driver initialization +//--- + +static void init(void) +{ + gint[HWDD] = HW_LOADED | HWDD_LIGHT; +} + //--- // Driver status string //--- @@ -243,7 +252,7 @@ static const char *t6k11_status(void) gint_driver_t drv_t6k11 = { .name = "T6K11", - .init = NULL, + .init = init, .status = GINT_DRIVER_STATUS(t6k11_status), .ctx_size = sizeof(ctx_t), .sys_ctx = &sys_ctx, diff --git a/src/tmu/tmu.c b/src/tmu/tmu.c index 4068acd..1088d3d 100644 --- a/src/tmu/tmu.c +++ b/src/tmu/tmu.c @@ -155,6 +155,7 @@ uint32_t timer_delay(int tid, uint64_t delay_us) uint64_t freq = clock->Pphi_f >> 2; /* fxcg50: Calculated = 29491200 but it's too low */ + /* TODO: Account for down spread spectrum in the CPG */ // uint64_t freq = 29020000 >> 2; /* Extra timers all run at 32768 Hz */ @@ -262,7 +263,7 @@ static void driver_sh3(void) TSTR = (void *)0xfffffe92; } -#endif +#endif /* FX9860G */ static void init(void) { @@ -365,6 +366,22 @@ static void init(void) SH7305_INTC.MSKCLR->IMR6 = 0x18; SH7305_INTC.MSKCLR->IMR8 = 0x02; } + + /* Record details in gint's hardware information interface */ + + gint[HWTMU] = HW_LOADED; + gint[HWETMU] = HW_LOADED | (isSH3() ? HWETMU_1 : HWETMU_6); + + for(int i = 3; i < timer_count(); i++) + { + tmu_extra_t *t = timers[i].tmu; + int v = !(t->TCOR + 1) + && !(t->TCNT + 1) + && !(t->TSTR) + && !(t->TCR.UNF) + && !(t->TCR.UNIE); + gint[HWETMU] |= v << (i - 1); + } } //---