mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-29 13:03:36 +01:00
core: add a hardware detection interface
This commit is contained in:
parent
7798f276ae
commit
3324d58afa
18 changed files with 386 additions and 201 deletions
189
include/gint/hardware.h
Normal file
189
include/gint/hardware.h
Normal file
|
@ -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 <gint/defs/types.h>
|
||||
|
||||
/* 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 */
|
|
@ -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 <gint/defs/types.h>
|
||||
|
||||
/* 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 */
|
|
@ -6,7 +6,7 @@
|
|||
#define GINT_TIMER
|
||||
|
||||
#include <gint/defs/types.h>
|
||||
#include <gint/mpu.h>
|
||||
#include <gint/hardware.h>
|
||||
|
||||
/* Timer identifiers
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <gint/clock.h>
|
||||
#include <core/std.h>
|
||||
|
||||
#include <gint/mpu.h>
|
||||
#include <gint/hardware.h>
|
||||
#include <gint/mpu/cpg.h>
|
||||
|
||||
//---
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <core/std.h>
|
||||
#include <core/mmu.h>
|
||||
|
||||
#include <gint/mpu.h>
|
||||
#include <gint/hardware.h>
|
||||
#include <gint/mpu/intc.h>
|
||||
|
||||
#include <gint/gint.h>
|
||||
|
@ -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];
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include <gint/gint.h>
|
||||
#include <core/std.h>
|
||||
#include <gint/mpu.h>
|
||||
#include <gint/hardware.h>
|
||||
#include <gint/mpu/intc.h>
|
||||
|
||||
/* Interrupt controllers */
|
||||
|
|
115
src/core/hardware.c
Normal file
115
src/core/hardware.c
Normal file
|
@ -0,0 +1,115 @@
|
|||
//---
|
||||
// gint:core:hardware - Platform information and hardware detection
|
||||
//---
|
||||
|
||||
#include <gint/hardware.h>
|
||||
#include <gint/defs/attributes.h>
|
||||
#include <gint/defs/types.h>
|
||||
#include <gint/defs/util.h>
|
||||
#include <gint/mpu/pfc.h>
|
||||
|
||||
/* 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 */
|
|
@ -3,6 +3,7 @@
|
|||
//---
|
||||
|
||||
#include <core/mmu.h>
|
||||
#include <gint/hardware.h>
|
||||
|
||||
//---
|
||||
// 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;
|
||||
}
|
||||
|
|
|
@ -1,90 +0,0 @@
|
|||
//---
|
||||
// gint:core:mpu - Runtime MPU detection
|
||||
//---
|
||||
|
||||
#include <gint/mpu.h>
|
||||
#include <gint/defs/attributes.h>
|
||||
#include <gint/defs/types.h>
|
||||
#include <gint/defs/util.h>
|
||||
|
||||
/* 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 */
|
|
@ -6,7 +6,7 @@
|
|||
#include <gint/drivers.h>
|
||||
#include <core/std.h>
|
||||
#include <core/setup.h>
|
||||
#include <gint/mpu.h>
|
||||
#include <gint/hardware.h>
|
||||
#include <gint/mpu/intc.h>
|
||||
|
||||
/* VBR address, from the linker script */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//---
|
||||
// gint:core:start - Kernel initialisation and C runtime
|
||||
// gint:core:start - Kernel initialization and C runtime
|
||||
//--
|
||||
|
||||
#include <gint/defs/attributes.h>
|
||||
|
@ -8,7 +8,7 @@
|
|||
#include <core/mmu.h>
|
||||
#include <gint/drivers.h>
|
||||
#include <gint/gint.h>
|
||||
#include <gint/mpu.h>
|
||||
#include <gint/hardware.h>
|
||||
|
||||
/* 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 */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include <gint/mpu.h>
|
||||
#include <gint/hardware.h>
|
||||
#include <gint/mpu/dma.h>
|
||||
#include <gint/mpu/power.h>
|
||||
#include <gint/mpu/intc.h>
|
||||
|
@ -116,6 +116,8 @@ static void init(void)
|
|||
|
||||
/* Unmask the DMA0 interrupt */
|
||||
INTC.MSKCLR->IMR1 = 0x01;
|
||||
|
||||
gint[HWDMA] = HW_LOADED;
|
||||
}
|
||||
|
||||
//---
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#include <gint/drivers/iokbd.h>
|
||||
#include <gint/defs/attributes.h>
|
||||
#include <gint/mpu.h>
|
||||
#include <gint/hardware.h>
|
||||
|
||||
//---
|
||||
// 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 */
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
//---
|
||||
|
||||
#include <gint/defs/types.h>
|
||||
#include <gint/hardware.h>
|
||||
#include <gint/drivers.h>
|
||||
#include <gint/dma.h>
|
||||
#include <core/std.h>
|
||||
|
@ -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,
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include <gint/gint.h>
|
||||
|
||||
#include <gint/defs/types.h>
|
||||
#include <gint/mpu.h>
|
||||
#include <gint/hardware.h>
|
||||
#include <gint/mpu/rtc.h>
|
||||
|
||||
//---
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
//---
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include <gint/defs/attributes.h>
|
||||
#include <gint/mpu.h>
|
||||
#include <gint/hardware.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#include <gint/defs/attributes.h>
|
||||
#include <gint/defs/types.h>
|
||||
#include <gint/mpu.h>
|
||||
#include <gint/hardware.h>
|
||||
|
||||
#include <gint/syscalls.h>
|
||||
|
||||
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
//---
|
||||
|
|
Loading…
Reference in a new issue