#include #include #include #include #include #include #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; sleep_us_spin(1000); SPU.SPUSRST.RST = 1; sleep_us_spin(1000); /* Initially give all P memory and X memory to DSP0 */ SPU.PBANKC0 = 0x1f; SPU.PBANKC1 = 0x00; SPU.XBANKC0 = 0x7f; SPU.XBANKC1 = 0x00; /* 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; 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; } static size_t ctx_size(void) { return (sizeof(ctx_t)); } //--- // Driver structure definition //--- gint_driver_t drv_spu = { .name = "SPU", .init = init, .ctx_size = &ctx_size, .ctx_save = (void*)&ctx_save, .ctx_restore = (void*)&ctx_restore, }; GINT_DECLARE_DRIVER(3, drv_spu);