spu: starter driver, supporting direct CPU access to SPU memory

This commit is contained in:
Lephe 2020-10-21 18:29:04 +02:00
parent 8ff7d89d33
commit 3694f20d56
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
6 changed files with 196 additions and 2 deletions

View File

@ -38,6 +38,9 @@ enum {
INTC_RTC_ATI,
INTC_RTC_PRI,
INTC_RTC_CUI,
/* SPU; interrupts from the DSPs and the SPU-bound DMA */
INTC_SPU_DSP0,
INTC_SPU_DSP1,
};
//---

View File

@ -293,7 +293,7 @@ typedef struct
// Forward definitions
//---
/* Provided by core/gint.c */
/* Provided by intc/intc.c */
extern sh7705_intc_t SH7705_INTC;
extern sh7305_intc_t SH7305_INTC;

View File

@ -82,7 +82,7 @@ typedef volatile struct
uint32_t :1;
uint32_t I2C :1;
uint32_t :1;
uint32_t SPU :1;
uint32_t FSI_SPU :1;
uint32_t _unknown2 :1;
uint32_t :1;
uint32_t LCDC :1;

97
include/gint/mpu/spu.h Normal file
View File

@ -0,0 +1,97 @@
//---
// gint:mpu:spu - Sound Processing Unit and its DSPs
//---
#ifndef GINT_MPU_SPU
#define GINT_MPU_SPU
#include <gint/defs/types.h>
typedef volatile struct
{
uint32_t PBANKC0; /* Program Bank Control 0 */
uint32_t PBANKC1; /* Program Bank Control 1 */
pad(0x8);
uint32_t XBANKC0; /* X Bank Control 0 */
uint32_t XBANKC1; /* X Bank Control 1 */
pad(0x10);
lword_union(SPUSRST, /* SPU Software Reset */
uint32_t :24;
uint32_t DB3 :1; /* DMABUF 3 */
uint32_t DB2 :1; /* DMABUF 2 */
uint32_t DB1 :1; /* DMABUF 1 */
uint32_t DB0 :1; /* DMABUF 0 */
uint32_t :3;
uint32_t RST :1; /* Reset */
);
uint32_t const SPUADR; /* SPU address */
uint32_t const ENDIAN; /* SuperHyway endian */
pad(0x10);
uint32_t GCOM[8]; /* Global Common */
pad(0x20);
uint32_t const DMABUF[4]; /* Inter-DSP Communication Buffer */
} GPACKED(4) spu_t;
typedef volatile struct
{
uint32_t SBAR; /* Source base address */
uint32_t SAR; /* Source address */
uint32_t DBAR; /* Destination base address */
uint32_t DAR; /* Destination address */
uint32_t TCR; /* Transfer count */
uint32_t SHPRI; /* SHway priority */
uint32_t CHCR; /* Channel control */
pad(0x4);
} GPACKED(4) spu_dsp_dma_t;
typedef volatile struct {
uint32_t LSA; /* Loop start address */
uint32_t LEA; /* Loop end address */
pad(0x8);
} GPACKED(4) spu_dsp_loop_t;
typedef volatile struct
{
uint32_t DSPRST; /* DSP full reset */
uint32_t DSPCORERST; /* DSP core reset */
uint32_t const DSPHOLD; /* DSP hold */
uint32_t DSPRESTART; /* DSP restart */
pad(0x8);
uint32_t IEMASKC; /* CPU interrupt source mask */
uint32_t IMASKC; /* CPU interrupt signal mask */
uint32_t IEVENTC; /* CPU interrupt source */
uint32_t IEMASKD; /* DSP interrupt source mask */
uint32_t IMASKD; /* DSP interrupt signal mask */
uint32_t IESETD; /* DSP interrupt set */
uint32_t IECLRD; /* DSP interrupt clear */
uint32_t OR; /* DMAC operation */
uint32_t COM[8]; /* CPU-DSP communication */
uint32_t BTADRU; /* Bus-through address high */
uint32_t BTADRL; /* Bus-through address low */
uint32_t WDATU; /* Bus-through write data high */
uint32_t WDATL; /* Bus-through write data low */
uint32_t RDATU; /* Bus-through read data high */
uint32_t RDATL; /* Bus-through read data low */
uint32_t BTCTRL; /* Bus-through mode control */
uint32_t SPUSTS; /* SPU status */
pad(0x88);
spu_dsp_dma_t DMA[3];
pad(0x20);
spu_dsp_loop_t LP[3];
} GPACKED(4) spu_dsp_t;
#define SH7305_SPU (*(spu_t *)0xfe2ffc00)
#define SH7305_DSP0 (*(spu_dsp_t *)0xfe2ffd00)
#define SH7305_DSP1 (*(spu_dsp_t *)0xfe3ffd00)
#endif /* GINT_MPU_SPU */

View File

@ -56,6 +56,9 @@ static struct info {
{ IPRK, 0xf000, IMR10, 0x04, IPRA, 0x000f },
{ IPRK, 0xf000, IMR10, 0x02, IPRA, 0x000f },
{ IPRK, 0xf000, IMR10, 0x01, IPRA, 0x000f },
/* SPU */
{ IPRC, 0x000f, IMR3, 0x04, _ /* Not supported on SH3! */ },
{ IPRC, 0x000f, IMR4, 0x08, _ },
};

91
src/spu/spu.c Normal file
View File

@ -0,0 +1,91 @@
#include <gint/mpu/spu.h>
#include <gint/mpu/cpg.h>
#include <gint/mpu/power.h>
#include <gint/drivers.h>
#include <gint/clock.h>
#include <gint/intc.h>
#define SPU SH7305_SPU
#define DSP0 SH7305_DSP0
#define DSP1 SH7305_DSP1
#define CPG SH7305_CPG
#define POWER SH7305_POWER
static void init(void)
{
/* Block SPU interrupts from DSP0, DSP1, and their DMA */
intc_priority(INTC_SPU_DSP0, 0);
intc_priority(INTC_SPU_DSP1, 0);
/* Stop both the SPU and FSI clocks */
CPG.FSICLKCR.lword = 0x00000103;
CPG.SPUCLKCR.lword = 0x00000100;
/* Enable the FSI clock, then the SPU/SPURAM clock */
CPG.FSICLKCR.CLKSTP = 0;
CPG.SPUCLKCR.CLKSTP = 0;
/* Power the clocks through MSTPCR2 */
POWER.MSTPCR2.FSI_SPU = 0;
/* Reset the SPU */
SPU.SPUSRST.RST = 0;
SPU.SPUSRST.RST = 1;
sleep_us_spin(1000);
/* Perform full DSP resets */
DSP0.DSPCORERST = 1;
DSP1.DSPCORERST = 1;
DSP0.DSPRST = 0;
DSP1.DSPRST = 0;
sleep_us_spin(1000);
}
int spu_zero(void)
{
return 0;
}
//---
// Hardware context
//---
typedef struct
{
uint32_t PBANKC0, PBANKC1;
uint32_t XBANKC0, XBANKC1;
} ctx_t;
GBSS static ctx_t sys_ctx, gint_ctx;
static void ctx_save(void *buf)
{
ctx_t *ctx = buf;
ctx->PBANKC0 = SPU.PBANKC0;
ctx->PBANKC1 = SPU.PBANKC1;
ctx->XBANKC0 = SPU.XBANKC0;
ctx->XBANKC1 = SPU.XBANKC1;
}
static void ctx_restore(void *buf)
{
ctx_t *ctx = buf;
SPU.PBANKC0 = ctx->PBANKC0;
SPU.PBANKC1 = ctx->PBANKC1;
SPU.XBANKC0 = ctx->XBANKC0;
SPU.XBANKC1 = ctx->XBANKC1;
}
//---
// Driver structure definition
//---
gint_driver_t drv_spu = {
.name = "SPU",
.init = init,
.sys_ctx = &sys_ctx,
.gint_ctx = &gint_ctx,
.ctx_save = ctx_save,
.ctx_restore = ctx_restore,
};
GINT_DECLARE_DRIVER(3, drv_spu);