mirror of
https://gitee.com/anod/open_agb_firm.git
synced 2025-05-07 22:34:12 +08:00
149 lines
6.3 KiB
C
149 lines
6.3 KiB
C
#pragma once
|
|
|
|
/*
|
|
* This file is part of open_agb_firm
|
|
* Copyright (C) 2021 derrek, profi200
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <assert.h>
|
|
#include "types.h"
|
|
#include "mem_map.h"
|
|
#include "util.h"
|
|
|
|
|
|
#define NDMA_REGS_BASE (IO_MEM_ARM9_ONLY + 0x2000)
|
|
#define REG_NDMA_GCNT *((vu32*)NDMA_REGS_BASE) // Global control.
|
|
|
|
// Note: The channel regs are offset by 4 (REG_NDMA_GLOBAL_CNT).
|
|
typedef struct
|
|
{
|
|
vu32 sad; // 0x00 Source address.
|
|
vu32 dad; // 0x04 Destination address.
|
|
vu32 tcnt; // 0x08 Total repeat length in words.
|
|
vu32 wcnt; // 0x0C Logical block size in words.
|
|
vu32 bcnt; // 0x10 Block transfer timing/interval.
|
|
vu32 fdata; // 0x14 Fill data.
|
|
vu32 cnt; // 0x18 Control.
|
|
} NdmaCh;
|
|
static_assert(offsetof(NdmaCh, cnt) == 0x18, "Error: Member cnt of NdmaCh is not at offset 0x18!");
|
|
|
|
ALWAYS_INLINE NdmaCh* getNdmaChRegs(u8 c)
|
|
{
|
|
return &((NdmaCh*)(NDMA_REGS_BASE + 4))[c];
|
|
}
|
|
|
|
|
|
// REG_NDMA_GCNT
|
|
#define NDMA_REG_READBACK (1u) // Show internal state on REG_NDMAx_SAD/DAD/TCNT/WCNT. 3DS mode only.
|
|
#define NDMA_ROUND_ROBIN(n) (1u<<31 | (intLog2(n) + 1)<<16) // DSP DMA/CPU cycles (power of 2). Maximum 16384.
|
|
#define NDMA_HIGHEST_PRIO (0u)
|
|
|
|
// REG_NDMA_BCNT
|
|
// TODO: When is the delay happening during transfers?
|
|
// TODO: Does NDMA run at 67 MHz in 3DS mode? We will assume so for now.
|
|
#define NDMA_CYCLES(n) (n) // Maximum 65535. 0 means no delay/interval.
|
|
#define NDMA_PRESCALER_1 (0u) // 67027964 Hz.
|
|
#define NDMA_PRESCALER_4 (1u<<16) // 16756991 Hz.
|
|
#define NDMA_PRESCALER_16 (2u<<16) // 4189247.75 Hz.
|
|
#define NDMA_PRESCALER_64 (3u<<16) // 1047311.9375 Hz.
|
|
#define NDMA_FASTEST (NDMA_PRESCALER_1 | NDMA_CYCLES(0)) // Convenience macro.
|
|
|
|
// REG_NDMA_CNT
|
|
#define NDMA_DAD_INC (0u) // Destination address increment.
|
|
#define NDMA_DAD_DEC (1u<<10) // Destination address decrement.
|
|
#define NDMA_DAD_FIX (2u<<10) // Destination address fixed.
|
|
#define NDMA_DAD_RELOAD (1u<<12) // Reload destination address on logical block end (REG_NDMAx_WCNT).
|
|
#define NDMA_SAD_INC (0u) // Source address increment.
|
|
#define NDMA_SAD_DEC (1u<<13) // Source address decrement.
|
|
#define NDMA_SAD_FIX (2u<<13) // Source address fixed.
|
|
#define NDMA_SAD_FILL (3u<<13) // Source is REG_NDMAx_FDATA.
|
|
#define NDMA_SAD_RELOAD (1u<<15) // Reload source address on logical block end (REG_NDMAx_WCNT).
|
|
#define NDMA_BURST_SHIFT (16u)
|
|
#define NDMA_BURST(n) (intLog2(n)<<NDMA_BURST_SHIFT) // Burst length is 2ⁿ words. Maximum 32768. Must be power of 2.
|
|
#define NDMA_TCNT_MODE (0u) // REG_NDMAx_TCNT mode.
|
|
#define NDMA_REPEAT_MODE (1u<<29) // Repeat transfer infinitely.
|
|
#define NDMA_IRQ_EN (1u<<30) // IRQ enable.
|
|
#define NDMA_EN (1u<<31) // Channel enable/active.
|
|
|
|
|
|
enum
|
|
{
|
|
NDMA_START_TIMER0 = 0u<<24,
|
|
NDMA_START_TIMER1 = 1u<<24,
|
|
NDMA_START_TIMER2 = 2u<<24,
|
|
NDMA_START_TIMER3 = 3u<<24,
|
|
NDMA_START_CTRCARD1 = 4u<<24, // Fires with SPICARD aswell but seems to be broken.
|
|
NDMA_START_CTRCARD2 = 5u<<24, // Fires with SPICARD aswell but seems to be broken.
|
|
NDMA_START_TOSHSD1 = 6u<<24,
|
|
NDMA_START_TOSHSD3 = 7u<<24,
|
|
NDMA_START_AES_IN = 8u<<24, // AES write fifo.
|
|
NDMA_START_AES_OUT = 9u<<24, // AES read fifo.
|
|
NDMA_START_SHA_IN = 10u<<24,
|
|
NDMA_START_SHA_OUT = 11u<<24, // For chaining.
|
|
NDMA_START_NTRCARD = 12u<<24,
|
|
// 13 and 14 unused?
|
|
NDMA_START_DEV2DEV = 15u<<24, // Needed for below startup modes.
|
|
|
|
// Direct device to device modes.
|
|
NDMA_START_CTRCARD1_AES = NDMA_START_DEV2DEV | 0u, // CTRCARD1 to AES.
|
|
NDMA_START_CTRCARD2_AES = NDMA_START_DEV2DEV | 1u, // CTRCARD2 to AES.
|
|
NDMA_START_AES_CTRCARD1 = NDMA_START_DEV2DEV | 2u, // AES to CTRCARD1.
|
|
NDMA_START_AES_CTRCARD2 = NDMA_START_DEV2DEV | 3u, // AES to CTRCARD2.
|
|
NDMA_START_CTRCARD1_SHA = NDMA_START_DEV2DEV | 4u, // CTRCARD1 to SHA.
|
|
NDMA_START_CTRCARD2_SHA = NDMA_START_DEV2DEV | 5u, // CTRCARD2 to SHA.
|
|
NDMA_START_SHA_CTRCARD1 = NDMA_START_DEV2DEV | 6u, // SHA to CTRCARD1.
|
|
NDMA_START_SHA_CTRCARD2 = NDMA_START_DEV2DEV | 7u, // SHA to CTRCARD2.
|
|
NDMA_START_TOSHSD1_AES = NDMA_START_DEV2DEV | 8u, // TOSHSD1 to AES.
|
|
NDMA_START_TOSHSD3_AES = NDMA_START_DEV2DEV | 9u, // TOSHSD3 to AES.
|
|
NDMA_START_AES_TOSHSD1 = NDMA_START_DEV2DEV | 10u, // AES to TOSHSD1.
|
|
NDMA_START_AES_TOSHSD3 = NDMA_START_DEV2DEV | 11u, // AES to TOSHSD3.
|
|
NDMA_START_TOSHSD1_SHA = NDMA_START_DEV2DEV | 12u, // TOSHSD1 to SHA.
|
|
NDMA_START_TOSHSD3_SHA = NDMA_START_DEV2DEV | 13u, // TOSHSD3 to SHA.
|
|
NDMA_START_SHA_TOSHSD1 = NDMA_START_DEV2DEV | 14u, // SHA to TOSHSD1.
|
|
NDMA_START_SHA_TOSHSD3 = NDMA_START_DEV2DEV | 15u, // SHA to TOSHSD3.
|
|
NDMA_START_AES_SHA = NDMA_START_DEV2DEV | 16u, // AES to SHA.
|
|
NDMA_START_SHA_AES = NDMA_START_DEV2DEV | 17u, // SHA to AES.
|
|
// 18-31 unused?
|
|
|
|
// This bit is technically not part of the startup modes.
|
|
NDMA_START_IMMEDIATE = 16u<<24
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
* @brief Initializes all NDMA channels.
|
|
*/
|
|
void NDMA_init(void);
|
|
|
|
/**
|
|
* @brief Copies data using the NDMA engine.
|
|
*
|
|
* @param dest Pointer to destination memory. Must be 4 bytes aligned.
|
|
* @param source Pointer to source data. Must be 4 bytes aligned.
|
|
* @param[in] size The size of the data. Must be multiple of 4.
|
|
*/
|
|
void NDMA_copy(u32 *dest, const u32 *source, u32 size);
|
|
|
|
/**
|
|
* @brief Fills memory with the given value using the NDMA engine.
|
|
*
|
|
* @param dest Pointer to destination memory. Must be 4 bytes aligned.
|
|
* @param[in] value The value each 32-bit word will be set to.
|
|
* @param[in] size The size of the memory to fill. Must be multiple of 4.
|
|
*/
|
|
void NDMA_fill(u32 *dest, u32 value, u32 size);
|