-
Notifications
You must be signed in to change notification settings - Fork 77
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
hb: Use NDMA to clear RAM and clear DSi registers
- Loading branch information
1 parent
f6e093e
commit ab5ea03
Showing
3 changed files
with
248 additions
and
62 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,223 @@ | ||
#pragma once | ||
|
||
typedef struct | ||
{ | ||
const void* src; // Source address; not used in fill mode | ||
void* dst; // Destination address | ||
u32 totalWordCount; // For auto-start mode without infinite repeat | ||
u32 wordCount; // Number of words to transfer per start trigger | ||
u32 blockInterval; // Sets prescaler and cycles of delay between physical blocks | ||
u32 fillData; // For fill mode | ||
u32 control; | ||
} dma_twl_config_t; | ||
|
||
#define REG_NDMAGCNT (*(vu32*)0x04004100) | ||
|
||
#define NDMAGCNT_YIELD_CYCLES_0 (0 << 16) | ||
#define NDMAGCNT_YIELD_CYCLES_1 (1 << 16) | ||
#define NDMAGCNT_YIELD_CYCLES_2 (2 << 16) | ||
#define NDMAGCNT_YIELD_CYCLES_4 (3 << 16) | ||
#define NDMAGCNT_YIELD_CYCLES_8 (4 << 16) | ||
#define NDMAGCNT_YIELD_CYCLES_16 (5 << 16) | ||
#define NDMAGCNT_YIELD_CYCLES_32 (6 << 16) | ||
#define NDMAGCNT_YIELD_CYCLES_64 (7 << 16) | ||
#define NDMAGCNT_YIELD_CYCLES_128 (8 << 16) | ||
#define NDMAGCNT_YIELD_CYCLES_256 (9 << 16) | ||
#define NDMAGCNT_YIELD_CYCLES_512 (10 << 16) | ||
#define NDMAGCNT_YIELD_CYCLES_1024 (11 << 16) | ||
#define NDMAGCNT_YIELD_CYCLES_2048 (12 << 16) | ||
#define NDMAGCNT_YIELD_CYCLES_4096 (13 << 16) | ||
#define NDMAGCNT_YIELD_CYCLES_8192 (14 << 16) | ||
#define NDMAGCNT_YIELD_CYCLES_16384 (15 << 16) | ||
|
||
#define NDMAGCNT_ARBITRATION_FIXED (0 << 31) | ||
#define NDMAGCNT_ARBITRATION_ROUND_ROBIN (1 << 31) | ||
|
||
#define REG_NDMA0SAD (*(vu32*)0x04004104) | ||
#define REG_NDMA0DAD (*(vu32*)0x04004108) | ||
#define REG_NDMA0TCNT (*(vu32*)0x0400410C) | ||
#define REG_NDMA0WCNT (*(vu32*)0x04004110) | ||
#define REG_NDMA0BCNT (*(vu32*)0x04004114) | ||
#define REG_NDMA0FDATA (*(vu32*)0x04004118) | ||
#define REG_NDMA0CNT (*(vu32*)0x0400411C) | ||
|
||
#define REG_NDMA1SAD (*(vu32*)0x04004120) | ||
#define REG_NDMA1DAD (*(vu32*)0x04004124) | ||
#define REG_NDMA1TCNT (*(vu32*)0x04004128) | ||
#define REG_NDMA1WCNT (*(vu32*)0x0400412C) | ||
#define REG_NDMA1BCNT (*(vu32*)0x04004130) | ||
#define REG_NDMA1FDATA (*(vu32*)0x04004134) | ||
#define REG_NDMA1CNT (*(vu32*)0x04004138) | ||
|
||
#define REG_NDMA2SAD (*(vu32*)0x0400413C) | ||
#define REG_NDMA2DAD (*(vu32*)0x04004140) | ||
#define REG_NDMA2TCNT (*(vu32*)0x04004144) | ||
#define REG_NDMA2WCNT (*(vu32*)0x04004148) | ||
#define REG_NDMA2BCNT (*(vu32*)0x0400414C) | ||
#define REG_NDMA2FDATA (*(vu32*)0x04004150) | ||
#define REG_NDMA2CNT (*(vu32*)0x04004154) | ||
|
||
#define REG_NDMA3SAD (*(vu32*)0x04004158) | ||
#define REG_NDMA3DAD (*(vu32*)0x0400415C) | ||
#define REG_NDMA3TCNT (*(vu32*)0x04004160) | ||
#define REG_NDMA3WCNT (*(vu32*)0x04004164) | ||
#define REG_NDMA3BCNT (*(vu32*)0x04004168) | ||
#define REG_NDMA3FDATA (*(vu32*)0x0400416C) | ||
#define REG_NDMA3CNT (*(vu32*)0x04004170) | ||
|
||
#define NDMABCNT_INTERVAL(x) (x) | ||
#define NDMABCNT_PRESCALER_1 (0 << 16) | ||
#define NDMABCNT_PRESCALER_4 (1 << 16) | ||
#define NDMABCNT_PRESCALER_16 (2 << 16) | ||
#define NDMABCNT_PRESCALER_64 (3 << 16) | ||
|
||
#define NDMACNT_DST_MODE_INCREMENT (0 << 10) | ||
#define NDMACNT_DST_MODE_DECREMENT (1 << 10) | ||
#define NDMACNT_DST_MODE_FIXED (2 << 10) | ||
|
||
#define NDMACNT_DST_RELOAD (1 << 12) | ||
|
||
#define NDMACNT_SRC_MODE_INCREMENT (0 << 13) | ||
#define NDMACNT_SRC_MODE_DECREMENT (1 << 13) | ||
#define NDMACNT_SRC_MODE_FIXED (2 << 13) | ||
#define NDMACNT_SRC_MODE_FILLDATA (3 << 13) | ||
|
||
#define NDMACNT_SRC_RELOAD (1 << 15) | ||
|
||
#define NDMACNT_PHYSICAL_COUNT_1 (0 << 16) | ||
#define NDMACNT_PHYSICAL_COUNT_2 (1 << 16) | ||
#define NDMACNT_PHYSICAL_COUNT_4 (2 << 16) | ||
#define NDMACNT_PHYSICAL_COUNT_8 (3 << 16) | ||
#define NDMACNT_PHYSICAL_COUNT_16 (4 << 16) | ||
#define NDMACNT_PHYSICAL_COUNT_32 (5 << 16) | ||
#define NDMACNT_PHYSICAL_COUNT_64 (6 << 16) | ||
#define NDMACNT_PHYSICAL_COUNT_128 (7 << 16) | ||
#define NDMACNT_PHYSICAL_COUNT_256 (8 << 16) | ||
#define NDMACNT_PHYSICAL_COUNT_512 (9 << 16) | ||
#define NDMACNT_PHYSICAL_COUNT_1024 (10 << 16) | ||
#define NDMACNT_PHYSICAL_COUNT_2048 (11 << 16) | ||
#define NDMACNT_PHYSICAL_COUNT_4096 (12 << 16) | ||
#define NDMACNT_PHYSICAL_COUNT_8192 (13 << 16) | ||
#define NDMACNT_PHYSICAL_COUNT_16384 (14 << 16) | ||
#define NDMACNT_PHYSICAL_COUNT_32768 (15 << 16) | ||
|
||
#define NDMACNT_MODE_TIMER_0 (0 << 24) | ||
#define NDMACNT_MODE_TIMER_1 (1 << 24) | ||
#define NDMACNT_MODE_TIMER_2 (2 << 24) | ||
#define NDMACNT_MODE_TIMER_3 (3 << 24) | ||
#define NDMACNT_MODE_DS_SLOTA_ROM_XFER (4 << 24) | ||
#define NDMACNT_MODE_DS_SLOTB_ROM_XFER (5 << 24) | ||
#define NDMACNT_MODE_VBLANK (6 << 24) | ||
|
||
#ifdef LIBTWL_ARM9 | ||
|
||
#define NDMACNT_MODE_HBLANK (7 << 24) | ||
#define NDMACNT_MODE_DISPLAY (8 << 24) | ||
#define NDMACNT_MODE_MMEM_DISP_FIFO (9 << 24) | ||
#define NDMACNT_MODE_GX_FIFO (10 << 24) | ||
#define NDMACNT_MODE_CAMERA (11 << 24) | ||
|
||
#endif | ||
|
||
#ifdef LIBTWL_ARM7 | ||
|
||
#define NDMACNT_MODE_WIFI (7 << 24) | ||
#define NDMACNT_MODE_SDMMC (8 << 24) | ||
#define NDMACNT_MODE_SDIO (9 << 24) | ||
#define NDMACNT_MODE_AES_IN (10 << 24) | ||
#define NDMACNT_MODE_AES_OUT (11 << 24) | ||
#define NDMACNT_MODE_MIC (12 << 24) | ||
|
||
#endif | ||
|
||
#define NDMACNT_MODE_IMMEDIATE (1 << 28) | ||
#define NDMACNT_REPEAT_INFINITELY (1 << 29) | ||
#define NDMACNT_IRQ (1 << 30) | ||
#define NDMACNT_ENABLE (1 << 31) | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
/// @brief Configures twl ndma to use fixed arbitration. | ||
/// In this mode ndma0 has the highest and ndma3 the lowest priority, | ||
/// similar to the nitro dma channels. Note that ndma0 has a lower | ||
/// priority than nitro dma channel 3. When ndma channels are active | ||
/// the dsp and cpu can not access the bus. | ||
static inline void dma_twlSetFixedArbitration(void) | ||
{ | ||
REG_NDMAGCNT = NDMAGCNT_ARBITRATION_FIXED; | ||
} | ||
|
||
/// @brief Configures twl ndma to use round robin arbitration. | ||
/// In this mode nitro dma channels still have a higher priority, | ||
/// but bus access is distributed between all ndma channels and | ||
/// the dsp and cpu. | ||
/// This is done in the order ndma0, ndma1, ndma2, ndma3, dsp/cpu. | ||
/// Candidates that do not have any outstanding request are skipped, | ||
/// and the dsp takes priority over the cpu (as usual). The amount | ||
/// of cycles reserved for the dsp/cpu is configurable. | ||
/// @param yieldCycles The number of cycles that will be yielded to the | ||
/// dsp/cpu in the round robin schedule. When there is no request | ||
/// outstanding the cycles will not be wasted. Should be one of | ||
/// NDMAGCNT_YIELD_CYCLES_*. | ||
static inline void dma_twlSetRoundRobinArbitration(u32 yieldCycles) | ||
{ | ||
REG_NDMAGCNT = NDMAGCNT_ARBITRATION_ROUND_ROBIN | yieldCycles; | ||
} | ||
|
||
static inline void dma_twlSetParams(int dma, const dma_twl_config_t* config) | ||
{ | ||
vu32* channel = &(®_NDMA0SAD)[7 * dma]; | ||
channel[0] = (u32)config->src; | ||
channel[1] = (u32)config->dst; | ||
channel[2] = config->totalWordCount; | ||
channel[3] = config->wordCount; | ||
channel[4] = config->blockInterval; | ||
channel[5] = config->fillData; | ||
channel[6] = config->control; | ||
} | ||
|
||
static inline void dma_twlWait(int dma) | ||
{ | ||
vu32* cnt = &(®_NDMA0CNT)[7 * dma]; | ||
while (*cnt & NDMACNT_ENABLE); | ||
} | ||
|
||
static inline void dma_twlCopy32Async(int dma, const void* src, void* dst, u32 length) | ||
{ | ||
vu32* channel = &(®_NDMA0SAD)[7 * dma]; | ||
channel[0] = (u32)src; //SAD | ||
channel[1] = (u32)dst; //DAD | ||
channel[3] = length >> 2; //WCNT | ||
channel[4] = NDMABCNT_PRESCALER_1 | NDMABCNT_INTERVAL(0); //BCNT | ||
channel[6] = NDMACNT_DST_MODE_INCREMENT | NDMACNT_SRC_MODE_INCREMENT | | ||
NDMACNT_PHYSICAL_COUNT_1 | NDMACNT_MODE_IMMEDIATE | NDMACNT_ENABLE; | ||
} | ||
|
||
static inline void dma_twlCopy32(int dma, const void* src, void* dst, u32 length) | ||
{ | ||
dma_twlCopy32Async(dma, src, dst, length); | ||
dma_twlWait(dma); | ||
} | ||
|
||
static inline void dma_twlFill32Async(int dma, u32 value, void* dst, u32 length) | ||
{ | ||
vu32* channel = &(®_NDMA0SAD)[7 * dma]; | ||
channel[1] = (u32)dst; //DAD | ||
channel[3] = length >> 2; //WCNT | ||
channel[4] = NDMABCNT_PRESCALER_1 | NDMABCNT_INTERVAL(0); //BCNT | ||
channel[5] = value; //FDATA | ||
channel[6] = NDMACNT_DST_MODE_INCREMENT | NDMACNT_SRC_MODE_FILLDATA | | ||
NDMACNT_PHYSICAL_COUNT_1 | NDMACNT_MODE_IMMEDIATE | NDMACNT_ENABLE; | ||
} | ||
|
||
static inline void dma_twlFill32(int dma, u32 value, void* dst, u32 length) | ||
{ | ||
dma_twlFill32Async(dma, value, dst, length); | ||
dma_twlWait(dma); | ||
} | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif |