Lots of small changes related to recent findings.
Some cleanup.
This commit is contained in:
parent
391bc4d05d
commit
cdeec87351
|
@ -28,40 +28,45 @@
|
|||
#define GPIO_IRQ_ENABLE (1u<<2)
|
||||
|
||||
|
||||
// bits 3-7 pin number, bits 0-3 reg index.
|
||||
#define MAKE_GPIO(pin, reg) ((pin)<<3 | (reg))
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GPIO_1_0 = 0u<<3 | 0u,
|
||||
GPIO_1_1 = 1u<<3 | 0u,
|
||||
GPIO_1_2 = 2u<<3 | 0u,
|
||||
GPIO_1_0 = MAKE_GPIO(0u, 0u),
|
||||
GPIO_1_1 = MAKE_GPIO(1u, 0u),
|
||||
GPIO_1_2 = MAKE_GPIO(2u, 0u),
|
||||
|
||||
GPIO_2_0 = 0u<<3 | 1u,
|
||||
GPIO_2_1 = 1u<<3 | 1u,
|
||||
GPIO_2_0 = MAKE_GPIO(0u, 1u),
|
||||
GPIO_2_1 = MAKE_GPIO(1u, 1u),
|
||||
GPIO_2_2 = MAKE_GPIO(0u, 2u), // REG_GPIO2_DAT2
|
||||
|
||||
GPIO_3_0 = 0u<<3 | 2u,
|
||||
|
||||
GPIO_4_0 = 0u<<3 | 3u,
|
||||
GPIO_4_1 = 1u<<3 | 3u,
|
||||
GPIO_4_2 = 2u<<3 | 3u,
|
||||
GPIO_4_3 = 3u<<3 | 3u,
|
||||
GPIO_4_4 = 4u<<3 | 3u,
|
||||
GPIO_4_5 = 5u<<3 | 3u,
|
||||
GPIO_4_6 = 6u<<3 | 3u,
|
||||
GPIO_4_7 = 7u<<3 | 3u,
|
||||
GPIO_4_8 = 8u<<3 | 3u,
|
||||
GPIO_4_9 = 9u<<3 | 3u,
|
||||
GPIO_4_10 = 10u<<3 | 3u,
|
||||
GPIO_4_11 = 11u<<3 | 3u,
|
||||
|
||||
GPIO_5_0 = 0u<<3 | 4u,
|
||||
GPIO_3_0 = MAKE_GPIO(0u, 3u),
|
||||
GPIO_3_1 = MAKE_GPIO(1u, 3u),
|
||||
GPIO_3_2 = MAKE_GPIO(2u, 3u),
|
||||
GPIO_3_3 = MAKE_GPIO(3u, 3u),
|
||||
GPIO_3_4 = MAKE_GPIO(4u, 3u),
|
||||
GPIO_3_5 = MAKE_GPIO(5u, 3u),
|
||||
GPIO_3_6 = MAKE_GPIO(6u, 3u),
|
||||
GPIO_3_7 = MAKE_GPIO(7u, 3u),
|
||||
GPIO_3_8 = MAKE_GPIO(8u, 3u),
|
||||
GPIO_3_9 = MAKE_GPIO(9u, 3u),
|
||||
GPIO_3_10 = MAKE_GPIO(10u, 3u),
|
||||
GPIO_3_11 = MAKE_GPIO(11u, 3u),
|
||||
GPIO_3_12 = MAKE_GPIO(0u, 4u), // REG_GPIO3_DAT2
|
||||
|
||||
// Aliases
|
||||
GPIO_1_TOUCHSCREEN = GPIO_1_1, // Unset while touchscreen pen down
|
||||
GPIO_1_SHELL = GPIO_1_2, // 1 when closed
|
||||
GPIO_1_TOUCHSCREEN = GPIO_1_1, // Unset while touchscreen pen down. Unused after CODEC init.
|
||||
GPIO_1_SHELL = GPIO_1_2, // 1 when closed.
|
||||
|
||||
GPIO_4_HEADPH_JACK = GPIO_4_8, // Unset while headphones are plugged in
|
||||
GPIO_4_MCU = GPIO_4_9
|
||||
GPIO_2_HEADPH_JACK = GPIO_2_0, // Used after CODEC init.
|
||||
|
||||
GPIO_3_HEADPH_JACK = GPIO_3_8, // Unused/other function after CODEC init.
|
||||
GPIO_3_MCU = GPIO_3_9
|
||||
} Gpio;
|
||||
|
||||
#undef MAKE_GPIO
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
@ -79,12 +84,12 @@ void GPIO_config(Gpio gpio, u8 cfg);
|
|||
*
|
||||
* @return The state. Either 0 or 1.
|
||||
*/
|
||||
u8 GPIO_read(Gpio gpio);
|
||||
bool GPIO_read(Gpio gpio);
|
||||
|
||||
/**
|
||||
* @brief Writes a GPIO pin.
|
||||
*
|
||||
* @param[in] gpio The gpio.
|
||||
* @param[in] val The value.
|
||||
* @param[in] val The value. Must be 0 or 1.
|
||||
*/
|
||||
void GPIO_write(Gpio gpio, u8 val);
|
||||
void GPIO_write(Gpio gpio, bool val);
|
||||
|
|
|
@ -23,100 +23,113 @@
|
|||
#include "arm.h"
|
||||
|
||||
|
||||
#define CPU_II_REGS_BASE (MPCORE_PRIV_REG_BASE + 0x100)
|
||||
#define REG_CPU_II_CNT *((vu32*)(CPU_II_REGS_BASE + 0x00))
|
||||
#define REG_CPU_II_MASK *((vu32*)(CPU_II_REGS_BASE + 0x04))
|
||||
#define REG_CPU_II_BIN_POI *((vu32*)(CPU_II_REGS_BASE + 0x08))
|
||||
#define REG_CPU_II_AKN *((vu32*)(CPU_II_REGS_BASE + 0x0C))
|
||||
#define REG_CPU_II_EOI *((vu32*)(CPU_II_REGS_BASE + 0x10))
|
||||
#define REG_CPU_II_RUN_PRIO *((vu32*)(CPU_II_REGS_BASE + 0x14))
|
||||
#define REG_CPU_II_HIGH_PEN *((vu32*)(CPU_II_REGS_BASE + 0x18))
|
||||
// Most register names from: https://github.com/torvalds/linux/blob/master/include/linux/irqchip/arm-gic.h
|
||||
#define GIC_CPU_REGS_BASE (MPCORE_PRIV_REG_BASE + 0x100)
|
||||
#define REG_GIC_CPU_CTRL *(( vu32*)(GIC_CPU_REGS_BASE + 0x00)) // Control Register.
|
||||
#define REG_GIC_CPU_PRIMASK *(( vu32*)(GIC_CPU_REGS_BASE + 0x04)) // Priority Mask Register.
|
||||
#define REG_GIC_CPU_BINPOINT *(( vu32*)(GIC_CPU_REGS_BASE + 0x08)) // Binary Point Register.
|
||||
#define REG_GIC_CPU_INTACK *((const vu32*)(GIC_CPU_REGS_BASE + 0x0C)) // Interrupt Acknowledge Register.
|
||||
#define REG_GIC_CPU_EOI *(( vu32*)(GIC_CPU_REGS_BASE + 0x10)) // End of Interrupt Register.
|
||||
#define REG_GIC_CPU_RUNNINGPRI *((const vu32*)(GIC_CPU_REGS_BASE + 0x14)) // Running Priority Register.
|
||||
#define REG_GIC_CPU_HIGHPRI *((const vu32*)(GIC_CPU_REGS_BASE + 0x18)) // Highest Pending Interrupt Register.
|
||||
|
||||
#define GID_REGS_BASE (MPCORE_PRIV_REG_BASE + 0x1000)
|
||||
#define REG_GID_CNT *((vu32*)(GID_REGS_BASE + 0x000))
|
||||
#define REG_GID_CONTR_TYPE *((vu32*)(GID_REGS_BASE + 0x004))
|
||||
#define REGs_GID_ENA_SET ((vu32*)(GID_REGS_BASE + 0x100))
|
||||
#define REGs_GID_ENA_CLR ((vu32*)(GID_REGS_BASE + 0x180))
|
||||
#define REGs_GID_PEN_SET ((vu32*)(GID_REGS_BASE + 0x200))
|
||||
#define REGs_GID_PEN_CLR ((vu32*)(GID_REGS_BASE + 0x280))
|
||||
#define REGs_GID_ACTIVE_BIT ((vu32*)(GID_REGS_BASE + 0x300))
|
||||
#define REGs_GID_IPRIO ((vu32*)(GID_REGS_BASE + 0x400))
|
||||
#define REGs_GID_ITARG ((vu32*)(GID_REGS_BASE + 0x800))
|
||||
#define REGs_GID_ICONF ((vu32*)(GID_REGS_BASE + 0xC00))
|
||||
#define REGs_GID_LINE_LEV ((vu32*)(GID_REGS_BASE + 0xD00))
|
||||
#define REG_GID_SW_INT *((vu32*)(GID_REGS_BASE + 0xF00))
|
||||
#define REG_GID_PERI_INFO0 *((vu32*)(GID_REGS_BASE + 0xFE0))
|
||||
#define REG_GID_PERI_INFO1 *((vu32*)(GID_REGS_BASE + 0xFE4))
|
||||
#define REG_GID_PERI_INFO2 *((vu32*)(GID_REGS_BASE + 0xFE8))
|
||||
#define REG_GID_PERI_INFO3 *((vu32*)(GID_REGS_BASE + 0xFEC))
|
||||
#define REG_GID_PRIME_CELL0 *((vu32*)(GID_REGS_BASE + 0xFF0))
|
||||
#define REG_GID_PRIME_CELL1 *((vu32*)(GID_REGS_BASE + 0xFF4))
|
||||
#define REG_GID_PRIME_CELL2 *((vu32*)(GID_REGS_BASE + 0xFF8))
|
||||
#define REG_GID_PRIME_CELL3 *((vu32*)(GID_REGS_BASE + 0xFFC))
|
||||
#define GIC_DIST_REGS_BASE (MPCORE_PRIV_REG_BASE + 0x1000)
|
||||
#define REG_GIC_DIST_CTRL *(( vu32*)(GIC_DIST_REGS_BASE + 0x000)) // Interrupt Distributor Control Register.
|
||||
#define REG_GIC_DIST_CTR *((const vu32*)(GIC_DIST_REGS_BASE + 0x004)) // Interrupt Controller Type Register.
|
||||
#define REGs_GIC_DIST_ENABLE_SET (( vu32*)(GIC_DIST_REGS_BASE + 0x100)) // Interrupt Enable set Registers.
|
||||
#define REGs_GIC_DIST_ENABLE_CLEAR (( vu32*)(GIC_DIST_REGS_BASE + 0x180)) // Interrupt Enable clear Registers.
|
||||
#define REGs_GIC_DIST_PENDING_SET (( vu32*)(GIC_DIST_REGS_BASE + 0x200)) // Interrupt Pending set Registers.
|
||||
#define REGs_GIC_DIST_PENDING_CLEAR (( vu32*)(GIC_DIST_REGS_BASE + 0x280)) // Interrupt Pending clear Registers.
|
||||
#define REGs_GIC_DIST_ACTIVE_SET ((const vu32*)(GIC_DIST_REGS_BASE + 0x300)) // Interrupt Active Bit Registers.
|
||||
#define REGs_GIC_DIST_PRI (( vu32*)(GIC_DIST_REGS_BASE + 0x400)) // Interrupt Priority Registers.
|
||||
#define REGs_GIC_DIST_TARGET (( vu32*)(GIC_DIST_REGS_BASE + 0x800)) // Interrupt CPU targets Registers.
|
||||
#define REGs_GIC_DIST_CONFIG (( vu32*)(GIC_DIST_REGS_BASE + 0xC00)) // Interrupt Configuration Registers.
|
||||
#define REGs_GIC_DIST_LINE_LEVEL ((const vu32*)(GIC_DIST_REGS_BASE + 0xD00)) // Interrupt Line Level Registers.
|
||||
#define REG_GIC_DIST_SOFTINT *(( vu32*)(GIC_DIST_REGS_BASE + 0xF00)) // Software Interrupt Register.
|
||||
#define REG_GIC_DIST_PERIPH_IDENT0 *((const vu32*)(GIC_DIST_REGS_BASE + 0xFE0)) // Periphal Identification Register 0.
|
||||
#define REG_GIC_DIST_PERIPH_IDENT1 *((const vu32*)(GIC_DIST_REGS_BASE + 0xFE4)) // Periphal Identification Register 1.
|
||||
#define REG_GIC_DIST_PERIPH_IDENT2 *((const vu32*)(GIC_DIST_REGS_BASE + 0xFE8)) // Periphal Identification Register 2.
|
||||
#define REG_GIC_DIST_PERIPH_IDENT3 *((const vu32*)(GIC_DIST_REGS_BASE + 0xFEC)) // Periphal Identification Register 3.
|
||||
#define REG_GIC_DIST_PRIMECELL0 *((const vu32*)(GIC_DIST_REGS_BASE + 0xFF0)) // PrimeCell Identification Register 0.
|
||||
#define REG_GIC_DIST_PRIMECELL1 *((const vu32*)(GIC_DIST_REGS_BASE + 0xFF4)) // PrimeCell Identification Register 0.
|
||||
#define REG_GIC_DIST_PRIMECELL2 *((const vu32*)(GIC_DIST_REGS_BASE + 0xFF8)) // PrimeCell Identification Register 0.
|
||||
#define REG_GIC_DIST_PRIMECELL3 *((const vu32*)(GIC_DIST_REGS_BASE + 0xFFC)) // PrimeCell Identification Register 0.
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
IRQ_MPCORE_SW0 = 0u,
|
||||
IRQ_MPCORE_SW1 = 1u,
|
||||
IRQ_MPCORE_SW2 = 2u,
|
||||
IRQ_MPCORE_SW3 = 3u,
|
||||
IRQ_MPCORE_SW4 = 4u,
|
||||
IRQ_MPCORE_SW5 = 5u,
|
||||
IRQ_MPCORE_SW6 = 6u,
|
||||
IRQ_MPCORE_SW7 = 7u,
|
||||
IRQ_MPCORE_SW8 = 8u,
|
||||
IRQ_MPCORE_SW9 = 9u,
|
||||
IRQ_MPCORE_SW10 = 10u,
|
||||
IRQ_MPCORE_SW11 = 11u,
|
||||
IRQ_MPCORE_SW12 = 12u,
|
||||
IRQ_MPCORE_SW13 = 13u,
|
||||
IRQ_MPCORE_SW14 = 14u,
|
||||
IRQ_MPCORE_SW15 = 15u,
|
||||
IRQ_TIMER = 29u, // MPCore timer
|
||||
IRQ_WATCHDOG = 30u, // MPCore watchdog
|
||||
IRQ_SPI2 = 36u, // SPI bus 2 interrupt status update
|
||||
IRQ_IPI0 = 0u,
|
||||
IRQ_IPI1 = 1u,
|
||||
IRQ_IPI2 = 2u,
|
||||
IRQ_IPI3 = 3u,
|
||||
IRQ_IPI4 = 4u,
|
||||
IRQ_IPI5 = 5u,
|
||||
IRQ_IPI6 = 6u,
|
||||
IRQ_IPI7 = 7u,
|
||||
IRQ_IPI8 = 8u,
|
||||
IRQ_IPI9 = 9u,
|
||||
IRQ_IPI10 = 10u,
|
||||
IRQ_IPI11 = 11u,
|
||||
IRQ_IPI12 = 12u,
|
||||
IRQ_IPI13 = 13u,
|
||||
IRQ_IPI14 = 14u,
|
||||
IRQ_IPI15 = 15u,
|
||||
IRQ_TIMER = 29u, // MPCore timer.
|
||||
IRQ_WATCHDOG = 30u, // MPCore watchdog.
|
||||
IRQ_SPI2 = 36u, // SPI bus 2 interrupt status update.
|
||||
IRQ_UART = 37u, // New3DS-only UART?
|
||||
IRQ_PSC0 = 40u,
|
||||
IRQ_PSC1 = 41u,
|
||||
IRQ_PDC0 = 42u, // aka VBlank0
|
||||
IRQ_PDC1 = 43u, // aka VBlank1
|
||||
IRQ_PDC0 = 42u, // PDC0 topscreen H-/VBlank and errors.
|
||||
IRQ_PDC1 = 43u, // PDC1 bottom screen H-/VBlank and errors.
|
||||
IRQ_PPF = 44u,
|
||||
IRQ_P3D = 45u,
|
||||
IRQ_CDMA_EVENT0 = 48u, // Old 3DS CDMA
|
||||
IRQ_CDMA_EVENT1 = 49u, // Old 3DS CDMA
|
||||
IRQ_CDMA_EVENT2 = 50u, // Old 3DS CDMA
|
||||
IRQ_CDMA_EVENT3 = 51u, // Old 3DS CDMA
|
||||
IRQ_CDMA_EVENT4 = 52u, // Old 3DS CDMA
|
||||
IRQ_CDMA_EVENT5 = 53u, // Old 3DS CDMA
|
||||
IRQ_CDMA_EVENT6 = 54u, // Old 3DS CDMA
|
||||
IRQ_CDMA_EVENT7 = 55u, // Old 3DS CDMA
|
||||
IRQ_CDMA_EVENT8 = 56u, // Old 3DS CDMA
|
||||
IRQ_CDMA_FAULT = 57u, // Old 3DS CDMA
|
||||
IRQ_CDMA2_EVENT = 58u, // New 3DS CDMA
|
||||
IRQ_CDMA2_FAULT = 59u, // New 3DS CDMA
|
||||
IRQ_SDIO = 64u, // SDIO controller (WiFi)
|
||||
IRQ_SDIO_IRQ = 65u, // SDIO IRQ pin (WiFi)
|
||||
IRQ_CAM0 = 72u, // Camera 0 (DSi)
|
||||
IRQ_CAM1 = 73u, // Camera 1 (left eye)
|
||||
IRQ_LGYFB_BOT = 76u, // Legacy framebuffer bottom screen
|
||||
IRQ_LGYFB_TOP = 77u, // Legacy framebuffer top screen
|
||||
IRQ_CDMA_EVENT0 = 48u, // Old3DS CDMA.
|
||||
IRQ_CDMA_EVENT1 = 49u, // Old3DS CDMA.
|
||||
IRQ_CDMA_EVENT2 = 50u, // Old3DS CDMA.
|
||||
IRQ_CDMA_EVENT3 = 51u, // Old3DS CDMA.
|
||||
IRQ_CDMA_EVENT4 = 52u, // Old3DS CDMA.
|
||||
IRQ_CDMA_EVENT5 = 53u, // Old3DS CDMA.
|
||||
IRQ_CDMA_EVENT6 = 54u, // Old3DS CDMA.
|
||||
IRQ_CDMA_EVENT7 = 55u, // Old3DS CDMA.
|
||||
IRQ_CDMA_EVENT8 = 56u, // Old3DS CDMA.
|
||||
IRQ_CDMA_FAULT = 57u, // Old3DS CDMA.
|
||||
IRQ_CDMA2_EVENT = 58u, // New3DS-only CDMA event 0-31.
|
||||
IRQ_CDMA2_FAULT = 59u, // New3DS-only CDMA.
|
||||
IRQ_SDIO2 = 64u, // SDIO2 controller (WiFi).
|
||||
IRQ_SDIO2_IRQ = 65u, // SDIO2 IRQ pin (WiFi).
|
||||
IRQ_SDIO3 = 66u, // SDIO3 controller.
|
||||
IRQ_SDIO3_IRQ = 67u, // SDIO3 IRQ pin.
|
||||
IRQ_NTRCARD = 68u, // NTRCARD controller.
|
||||
IRQ_L2B1 = 69u, // New3DS-only first L2B converter.
|
||||
IRQ_L2B2 = 70u, // New3DS-only second L2B converter.
|
||||
IRQ_CAM1 = 72u, // Camera 1 (DSi).
|
||||
IRQ_CAM2 = 73u, // Camera 2 (left eye).
|
||||
IRQ_DSP = 74u,
|
||||
IRQ_Y2R1 = 75u,
|
||||
IRQ_LGYFB_BOT = 76u, // Legacy framebuffer bottom screen.
|
||||
IRQ_LGYFB_TOP = 77u, // Legacy framebuffer top screen.
|
||||
IRQ_Y2R2 = 78u, // New3DS-only.
|
||||
IRQ_G1 = 79u, // New3DS-only Hantro G1 decoder.
|
||||
IRQ_PXI_SYNC = 80u,
|
||||
IRQ_PXI_SYNC2 = 81u,
|
||||
IRQ_PXI_NOT_FULL = 82u,
|
||||
IRQ_PXI_NOT_EMPTY = 83u,
|
||||
IRQ_I2C1 = 84u,
|
||||
IRQ_I2C2 = 85u,
|
||||
IRQ_SPI3 = 86u, // SPI bus 3 interrupt status update
|
||||
IRQ_SPI1 = 87u, // SPI bus 1 interrupt status update
|
||||
IRQ_SPI3 = 86u, // SPI bus 3 interrupt status update.
|
||||
IRQ_SPI1 = 87u, // SPI bus 1 interrupt status update.
|
||||
IRQ_PDN = 88u,
|
||||
IRQ_LGY_SLEEP = 89u, // Triggers if legacy mode enters sleep.
|
||||
IRQ_MIC = 90u,
|
||||
IRQ_HID_PADCNT = 91u,
|
||||
IRQ_I2C3 = 92u,
|
||||
IRQ_GPIO_1_2 = 96u,
|
||||
IRQ_SHELL_CLOSED = 98u, // GPIO_1_0?
|
||||
IRQ_DS_WIFI = 95u,
|
||||
IRQ_GPIO_1_2_HIGH = 96u,
|
||||
IRQ_GPIO_1_2_LOW = 98u,
|
||||
IRQ_GPIO_1_1 = 99u,
|
||||
IRQ_GPIO_2_0 = 100u,
|
||||
IRQ_GPIO_2_1 = 102u,
|
||||
IRQ_GPIO_2_2 = 102u,
|
||||
IRQ_GPIO_4_0 = 104u,
|
||||
IRQ_GPIO_4_1 = 105u,
|
||||
IRQ_GPIO_4_2 = 106u,
|
||||
|
@ -129,17 +142,21 @@ typedef enum
|
|||
IRQ_GPIO_4_9 = 113u,
|
||||
IRQ_GPIO_4_10 = 114u,
|
||||
IRQ_GPIO_4_11 = 115u,
|
||||
IRQ_GAMECARD = 117u, // Gamecard inserted
|
||||
IRQ_PERF_MONITOR0 = 120u, // Core 0 performance monitor. Triggers on any counter overflow
|
||||
IRQ_PERF_MONITOR1 = 121u, // Core 1 performance monitor. Triggers on any counter overflow
|
||||
IRQ_PERF_MONITOR2 = 122u, // Unconfirmed. Core 2 performance monitor. Triggers on any counter overflow
|
||||
IRQ_PERF_MONITOR3 = 123u, // Unconfirmed. Core 3 performance monitor. Triggers on any counter overflow
|
||||
IRQ_GAMECARD_OFF = 116u, // Gamecard poweroff.
|
||||
IRQ_GAMECARD_INS = 117u, // Gamecard inserted.
|
||||
IRQ_L2C = 118u, // New3DS-only L2C-310 Level 2 Cache Controller.
|
||||
IRQ_UNK119 = 119u,
|
||||
IRQ_PERF_MONITOR0 = 120u, // Core 0 performance monitor. Triggers on any counter overflow.
|
||||
IRQ_PERF_MONITOR1 = 121u, // Core 1 performance monitor. Triggers on any counter overflow.
|
||||
IRQ_PERF_MONITOR2 = 122u, // Unconfirmed. Core 2 performance monitor. Triggers on any counter overflow.
|
||||
IRQ_PERF_MONITOR3 = 123u, // Unconfirmed. Core 3 performance monitor. Triggers on any counter overflow.
|
||||
|
||||
// Aliases
|
||||
IRQ_SHELL_OPENED = IRQ_GPIO_1_2,
|
||||
IRQ_TOUCHSCREEN = IRQ_GPIO_1_1, // Triggers on touchscreen pen down.
|
||||
IRQ_HEADPH_JACK = IRQ_GPIO_2_0, // Headphone jack. Triggers on both plugging in and out?
|
||||
IRQ_CTR_MCU = IRQ_GPIO_4_9 // Various MCU events trigger this. See MCU interrupt mask.
|
||||
IRQ_SHELL_OPENED = IRQ_GPIO_1_2_HIGH,
|
||||
IRQ_SHELL_CLOSED = IRQ_GPIO_1_2_LOW, // Triggers on GPIO_1_2 low?
|
||||
IRQ_TOUCHSCREEN = IRQ_GPIO_1_1, // Triggers on touchscreen pen down.
|
||||
IRQ_HEADPH_JACK = IRQ_GPIO_2_0, // Headphone jack. Triggers on both plugging in and out?
|
||||
IRQ_CTR_MCU = IRQ_GPIO_4_9 // Various MCU events trigger this. See MCU interrupt mask.
|
||||
} Interrupt;
|
||||
|
||||
|
||||
|
@ -158,20 +175,13 @@ void IRQ_init(void);
|
|||
/**
|
||||
* @brief Registers a interrupt service routine and enables the specified interrupt.
|
||||
*
|
||||
* @param[in] id The interrupt ID. Must be <128.
|
||||
* @param[in] prio The priority. 0 = highest, 14 = lowest, 15 = disabled
|
||||
* @param[in] cpuMask The CPU mask. Each of the 4 bits stands for 1 core. 0 means current CPU.
|
||||
* @param[in] edgeTriggered Set to true to make the interrupt edge triggered. false is level triggered.
|
||||
* @param[in] isr The interrupt service routine to call.
|
||||
* @param[in] id The interrupt ID. Must be <128.
|
||||
* @param[in] prio The priority. 0 = highest, 14 = lowest, 15 = disabled.
|
||||
* @param[in] cpuMask The CPU mask. Each of the 4 bits stands for 1 core.
|
||||
* 0 means current CPU.
|
||||
* @param[in] isr The interrupt service routine to call.
|
||||
*/
|
||||
void IRQ_registerIsr(Interrupt id, u8 prio, u8 cpuMask, bool edgeTriggered, IrqIsr isr);
|
||||
|
||||
/**
|
||||
* @brief Unregisters the interrupt service routine and disables the specified interrupt.
|
||||
*
|
||||
* @param[in] id The interrupt ID. Must be <128.
|
||||
*/
|
||||
void IRQ_unregisterIsr(Interrupt id);
|
||||
void IRQ_registerIsr(Interrupt id, u8 prio, u8 cpuMask, IrqIsr isr);
|
||||
|
||||
/**
|
||||
* @brief Reenables a previously disabled but registered interrupt.
|
||||
|
@ -187,6 +197,14 @@ void IRQ_enable(Interrupt id);
|
|||
*/
|
||||
void IRQ_disable(Interrupt id);
|
||||
|
||||
/**
|
||||
* @brief Triggers a software interrupt for the specified CPUs.
|
||||
*
|
||||
* @param[in] id The interrupt ID. Must be <16.
|
||||
* @param[in] cpuMask The CPU mask. Each of the 4 bits stands for 1 core.
|
||||
*/
|
||||
void IRQ_softwareInterrupt(Interrupt id, u8 cpuMask);
|
||||
|
||||
/**
|
||||
* @brief Sets the priority of an interrupt.
|
||||
*
|
||||
|
@ -196,12 +214,11 @@ void IRQ_disable(Interrupt id);
|
|||
void IRQ_setPriority(Interrupt id, u8 prio);
|
||||
|
||||
/**
|
||||
* @brief Triggers a software interrupt for the specified CPUs.
|
||||
* @brief Unregisters the interrupt service routine and disables the specified interrupt.
|
||||
*
|
||||
* @param[in] id The interrupt ID. Must be <16.
|
||||
* @param[in] cpuMask The CPU mask. Each of the 4 bits stands for 1 core.
|
||||
* @param[in] id The interrupt ID. Must be <128.
|
||||
*/
|
||||
void IRQ_softwareInterrupt(Interrupt id, u8 cpuMask);
|
||||
void IRQ_unregisterIsr(Interrupt id);
|
||||
|
||||
|
||||
#if !__thumb__
|
||||
|
|
|
@ -22,84 +22,84 @@
|
|||
|
||||
|
||||
// REG_DMA330_DSR
|
||||
#define DSR_WAKEUP_EVNT_SHIFT (4u)
|
||||
#define DSR_WAKEUP_EVNT_MASK (0x1Fu<<DSR_WAKEUP_EVNT_SHIFT)
|
||||
#define DSR_DNS (1u<<9) // DMA Manager is non-secure
|
||||
#define DSR_WAKE_EVNT_SHIFT (4u)
|
||||
#define DSR_WAKE_EVNT_MASK (0x1Fu<<DSR_WAKEUP_EVNT_SHIFT)
|
||||
#define DSR_DNS (1u<<9) // DMA Manager is non-secure.
|
||||
|
||||
enum
|
||||
{
|
||||
DSR_STATUS_STOPPED = 0u,
|
||||
DSR_STATUS_EXECUTING = 1u,
|
||||
DSR_STATUS_CACHE_MISS = 2u,
|
||||
DSR_STATUS_UPDATING_PC = 3u, // Updating program counter
|
||||
DSR_STATUS_WFE = 4u, // Waiting for event
|
||||
DSR_STATUS_FAULTING = 15u,
|
||||
DSR_STAT_STOPPED = 0u,
|
||||
DSR_STAT_EXECUTING = 1u,
|
||||
DSR_STAT_CACHE_MISS = 2u,
|
||||
DSR_STAT_UPDATING_PC = 3u, // Updating program counter.
|
||||
DSR_STAT_WFE = 4u, // Waiting for event.
|
||||
DSR_STAT_FAULTING = 15u,
|
||||
|
||||
DSR_STATUS_MASK = DSR_STATUS_FAULTING
|
||||
DSR_STAT_MASK = DSR_STAT_FAULTING
|
||||
};
|
||||
|
||||
// REG_DMA330_INTEN
|
||||
#define INTEN_SEL_IRQ(n) (1u<<(n)) // Select IRQ instead of event
|
||||
#define INTEN_SEL_IRQ(n) (1u<<(n)) // Select IRQ instead of event.
|
||||
|
||||
// REG_DMA330_INT_EVENT_RIS
|
||||
#define INT_EVENT_RIS_ACTIVE(n) (1u<<(n)) // Interrupt or event N is active
|
||||
#define INT_EVENT_RIS_ACTIVE(n) (1u<<(n)) // Interrupt or event N is active.
|
||||
|
||||
// REG_DMA330_INTMIS
|
||||
#define INTMIS_IRQ_ACTIVE(n) (1u<<(n)) // Interrupt N is active
|
||||
#define INTMIS_IRQ_ACTIVE(n) (1u<<(n)) // Interrupt N is active.
|
||||
|
||||
// REG_DMA330_INTCLR
|
||||
#define INTCLR_IRQ_CLR(n) (1u<<(n)) // Clear interrupt N
|
||||
#define INTCLR_IRQ_CLR(n) (1u<<(n)) // Clear interrupt N.
|
||||
|
||||
// REG_DMA330_FSRD
|
||||
#define FSRD_FAULTING (1u) // DMA manager is in faulting state
|
||||
#define FSRD_FAULTING (1u) // DMA manager is in faulting state.
|
||||
|
||||
// REG_DMA330_FSRC
|
||||
#define FSRC_FAULTING(n) (1u<<(n)) // DMA channel is in faulting or faulting completing state
|
||||
#define FSRC_FAULTING(n) (1u<<(n)) // DMA channel is in faulting or faulting completing state.
|
||||
|
||||
// REG_DMA330_FTRD
|
||||
#define FTRD_UNDEF_INSTR (1u)
|
||||
#define FTRD_OPERAND_INVALID (1u<<1)
|
||||
#define FTRD_DMAGO_ERR (1u<<4) // Starting a secure channel from a non-secure state
|
||||
#define FTRD_MGR_EVNT_ERR (1u<<5) // Waiting for or creating secure events/interrupts in no-secure state
|
||||
#define FTRD_DMAGO_ERR (1u<<4) // Starting a secure channel from a non-secure state.
|
||||
#define FTRD_MGR_EVNT_ERR (1u<<5) // Waiting for or creating secure events/interrupts in no-secure state.
|
||||
#define FTRD_INSTR_FETCH_ERR (1u<<16)
|
||||
#define FTRD_DBG_INSTR (1u<<30) // The erroneous instruction came from the debug interface
|
||||
#define FTRD_DBG_INSTR (1u<<30) // The erroneous instruction came from the debug interface.
|
||||
|
||||
// REG_DMA330_FTR0-7
|
||||
#define FTR_UNDEF_INSTR (1u)
|
||||
#define FTR_OPERAND_INVALID (1u<<1)
|
||||
#define FTR_CH_EVNT_ERR (1u<<5) // Waiting for or creating secure events/interrupts in no-secure state
|
||||
#define FTR_CH_PERIPH_ERR (1u<<6) // Accessing secure periphals in non-secure state (DMAWFP, DMALDP, DMASTP, DMAFLUSHP)
|
||||
#define FTR_CH_RDWR_ERR (1u<<7) // Secure read or write in non-secure state
|
||||
#define FTR_CH_MFIFO_ERR (1u<<12) // MFIFO too small to hold or store the data (DMALD, DMAST)
|
||||
#define FTR_CH_ST_DATA_UNAVAIL (1u<<13) // Not enough data in the MFIFO for DMAST to complete
|
||||
#define FTR_CH_EVNT_ERR (1u<<5) // Waiting for or creating secure events/interrupts in no-secure state.
|
||||
#define FTR_CH_PERIPH_ERR (1u<<6) // Accessing secure periphals in non-secure state (DMAWFP, DMALDP, DMASTP, DMAFLUSHP).
|
||||
#define FTR_CH_RDWR_ERR (1u<<7) // Secure read or write in non-secure state.
|
||||
#define FTR_CH_MFIFO_ERR (1u<<12) // MFIFO too small to hold or store the data (DMALD, DMAST).
|
||||
#define FTR_CH_ST_DATA_UNAVAIL (1u<<13) // Not enough data in the MFIFO for DMAST to complete.
|
||||
#define FTR_INSTR_FETCH_ERR (1u<<16)
|
||||
#define FTR_DATA_WRITE_ERR (1u<<17)
|
||||
#define FTR_DATA_READ_ERR (1u<<18)
|
||||
#define FTRD_DBG_INSTR (1u<<30) // The erroneous instruction came from the debug interface
|
||||
#define FTR_LOCKUP_ERR (1u<<31) // Channel locked up because of resource starvation
|
||||
#define FTR_DBG_INSTR (1u<<30) // The erroneous instruction came from the debug interface.
|
||||
#define FTR_LOCKUP_ERR (1u<<31) // Channel locked up because of resource starvation.
|
||||
|
||||
// REG_DMA330_CSR0-7
|
||||
#define CSR_WAKEUP_EVNT_SHIFT (4u)
|
||||
#define CSR_WAKEUP_EVNT_MASK (0x1Fu<<CSR_WAKEUP_EVNT_SHIFT)
|
||||
#define CSR_DMAWFP_B_NS (1u<<14) // DMAWFP executed with burst operand set
|
||||
#define CSR_DMAWFP_PERIPH (1u<<15) // DMAWFP executed with periph operand set
|
||||
#define CSR_CNS (1u<<21) // DMA channel is non-secure
|
||||
#define CSR_WAKE_EVNT_SHIFT (4u)
|
||||
#define CSR_WAKE_EVNT_MASK (0x1Fu<<CSR_WAKEUP_EVNT_SHIFT)
|
||||
#define CSR_DMAWFP_B_NS (1u<<14) // DMAWFP executed with burst operand set.
|
||||
#define CSR_DMAWFP_PERIPH (1u<<15) // DMAWFP executed with periph operand set.
|
||||
#define CSR_CNS (1u<<21) // DMA channel is non-secure.
|
||||
|
||||
enum
|
||||
{
|
||||
CSR_STATUS_STOPPED = 0u,
|
||||
CSR_STATUS_EXECUTING = 1u,
|
||||
CSR_STATUS_CACHE_MISS = 2u,
|
||||
CSR_STATUS_UPDATING_PC = 3u, // Updating program counter
|
||||
CSR_STATUS_WFE = 4u, // Waiting for event
|
||||
CSR_STATUS_AT_BARRIER = 5u,
|
||||
CSR_STATUS_WFP = 7u, // Waiting for periphal
|
||||
CSR_STATUS_KILLING = 8u,
|
||||
CSR_STATUS_COMPLETING = 9u,
|
||||
CSR_STATUS_FAULTING_COMPLETING = 14u,
|
||||
CSR_STATUS_FAULTING = 15u,
|
||||
CSR_STAT_STOPPED = 0u,
|
||||
CSR_STAT_EXECUTING = 1u,
|
||||
CSR_STAT_CACHE_MISS = 2u,
|
||||
CSR_STAT_UPDATING_PC = 3u, // Updating program counter.
|
||||
CSR_STAT_WFE = 4u, // Waiting for event.
|
||||
CSR_STAT_AT_BARRIER = 5u,
|
||||
CSR_STAT_WFP = 7u, // Waiting for periphal.
|
||||
CSR_STAT_KILLING = 8u,
|
||||
CSR_STAT_COMPLETING = 9u,
|
||||
CSR_STAT_FAULTING_COMPLETING = 14u,
|
||||
CSR_STAT_FAULTING = 15u,
|
||||
|
||||
CSR_STATUS_MASK = CSR_STATUS_FAULTING
|
||||
CSR_STAT_MASK = CSR_STAT_FAULTING
|
||||
};
|
||||
|
||||
// REG_DMA330_CCR0-7
|
||||
|
@ -123,7 +123,7 @@ enum
|
|||
#define CCR_DST_CACHE_CTRL_SHIFT (25u)
|
||||
#define CCR_DST_CACHE_CTRL_MASK (0x7u<<CCR_DST_CACHE_CTRL_SHIFT)
|
||||
|
||||
#define CCR_END_SWP_SIZE_SHIFT (28u) // END_SWP_SIZE = endian swap size
|
||||
#define CCR_END_SWP_SIZE_SHIFT (28u) // END_SWP_SIZE = endian swap size.
|
||||
#define CCR_END_SWP_SIZE_MASK (0x7u<<CCR_END_SWP_SIZE_SHIFT)
|
||||
|
||||
// REG_DMA330_DBGSTATUS
|
||||
|
@ -133,11 +133,10 @@ enum
|
|||
#define DBGCMD_EXECUTE (0u)
|
||||
|
||||
// REG_DMA330_DBGINST0
|
||||
#define DBGINST0_THREAD_MGR (0u) // Select DMA manager thread
|
||||
#define DBGINST0_THREAD_CH (1u) // Select DMA channel thread
|
||||
#define DBGINST0_CH_NUM(n) ((n)<<8) // Which channel thread is selected
|
||||
#define DBGINST0_BYTES01(b) ((b)<<16) // Byte 0 and 1 of the instruction
|
||||
// DBGINST1 stores the remaining 4 bytes ([7:0] byte 2...)
|
||||
#define DBGINST0_THR_MGR (0u) // Select DMA manager thread.
|
||||
#define DBGINST0_THR_CH (1u) // Select DMA channel thread (also needs a channel number).
|
||||
#define DBGINST0(b10, ch, t) ((b10)<<16 | (ch)<<8 | (t)) // b10 = byte 1 and 0, ch = channel num, t = thread.
|
||||
// DBGINST1 stores the remaining 4 instruction bytes.
|
||||
|
||||
|
||||
|
||||
|
@ -145,4 +144,9 @@ void DMA330_init(void);
|
|||
u8 DMA330_run(u8 ch, const u8 *const prog);
|
||||
u8 DMA330_status(u8 ch);
|
||||
void DMA330_ackIrq(u8 eventIrq);
|
||||
void DMA330_sev(u8 event);
|
||||
void DMA330_kill(u8 ch);
|
||||
|
||||
#ifdef ARM11
|
||||
//void DMA330_dbgPrint(void);
|
||||
#endif // ifdef ARM11
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2019 Aurora Wright, TuxSH, derrek, profi200
|
||||
|
|
|
@ -249,7 +249,7 @@ void CODEC_init(void)
|
|||
codecMaskReg(0, 0x39, 0x66, 0x66);
|
||||
codecWriteReg(0x65, 0x7A, 1);
|
||||
codecMaskReg(0x64, 0x22, 0x18, 0x18);
|
||||
GPIO_config(GPIO_2_0, GPIO_IRQ_ENABLE | GPIO_EDGE_RISING | GPIO_INPUT); // Headphone jack IRQ
|
||||
GPIO_config(GPIO_2_HEADPH_JACK, GPIO_IRQ_ENABLE | GPIO_EDGE_RISING | GPIO_INPUT); // Headphone jack IRQ.
|
||||
//codecMaskReg(0x64, 0x45, (*((vu8*)0x10147010) & 1u)<<4 | 1u<<5, 0x30); // GPIO bitmask 8.
|
||||
codecMaskReg(0x64, 0x45, 0, 0x30); // With automatic output switching
|
||||
codecMaskReg(0x64, 0x43, 0, 0x80);
|
||||
|
@ -276,8 +276,9 @@ void CODEC_init(void)
|
|||
codecWriteReg(0x64, 0x7B, cal->shutterVolume[1]);
|
||||
|
||||
// Sound stuff starts here
|
||||
GPIO_config(GPIO_4_0, GPIO_OUTPUT);
|
||||
GPIO_write(GPIO_4_0, 1); // GPIO bitmask 0x40
|
||||
// Speaker "depop circuit"? Whatever that is. Not existent on retail?
|
||||
GPIO_config(GPIO_3_0, GPIO_OUTPUT);
|
||||
GPIO_write(GPIO_3_0, 1); // GPIO bitmask 0x40
|
||||
TIMER_sleepMs(10); // Fixed 10 ms delay when setting this GPIO.
|
||||
*((vu16*)0x10145000) = 0xC800u | 0x20u<<6;
|
||||
*((vu16*)0x10145002) = 0xE000u;
|
||||
|
@ -354,7 +355,7 @@ void CODEC_init(void)
|
|||
codecWriteReg(0x65, 0x1B, cal->analogVolumeSP);
|
||||
codecWriteReg(0x65, 0x1C, cal->analogVolumeSP);
|
||||
TIMER_sleepMs(38);
|
||||
GPIO_write(GPIO_4_0, 0); // GPIO bitmask 0x40
|
||||
GPIO_write(GPIO_3_0, 0); // GPIO bitmask 0x40
|
||||
TIMER_sleepMs(18); // Fixed 18 ms delay when unsetting this GPIO.
|
||||
|
||||
|
||||
|
@ -382,7 +383,7 @@ bool legacySwitchState = false;
|
|||
|
||||
void CODEC_deinit(void)
|
||||
{
|
||||
GPIO_write(GPIO_4_0, 1); // GPIO bitmask 0x40
|
||||
GPIO_write(GPIO_3_0, 1); // GPIO bitmask 0x40
|
||||
TIMER_sleepMs(10); // Fixed 10 ms delay when setting this GPIO.
|
||||
legacySwitchState = (codecReadReg(0x67, 0x25) & 0x40u) != 0;
|
||||
if(!legacySwitchState) codecLegacyStuff(true);
|
||||
|
@ -406,13 +407,13 @@ void CODEC_deinit(void)
|
|||
*((vu16*)0x10145000) &= ~0x8000u;
|
||||
*((vu16*)0x10145002) &= ~0x8000u;
|
||||
*((vu8* )0x10141220) = 0;
|
||||
GPIO_write(GPIO_4_0, 0); // GPIO bitmask 0x40
|
||||
GPIO_write(GPIO_3_0, 0); // GPIO bitmask 0x40
|
||||
TIMER_sleepMs(18); // Fixed 18 ms delay when unsetting this GPIO.
|
||||
}
|
||||
|
||||
void CODEC_wakeup(void)
|
||||
{
|
||||
GPIO_write(GPIO_4_0, 1); // GPIO bitmask 0x40
|
||||
GPIO_write(GPIO_3_0, 1); // GPIO bitmask 0x40
|
||||
TIMER_sleepMs(10); // Fixed 10 ms delay when setting this GPIO.
|
||||
*((vu8* )0x10141220) = 2u;
|
||||
*((vu16*)0x10145000) |= 0x8000u;
|
||||
|
@ -437,7 +438,7 @@ void CODEC_wakeup(void)
|
|||
codecMaskReg(0x67, 0x25, 3, 3);
|
||||
codecLegacyStuff(legacySwitchState);
|
||||
if(touchscreenState) codecEnableTouchscreen();
|
||||
GPIO_write(GPIO_4_0, 0); // GPIO bitmask 0x40
|
||||
GPIO_write(GPIO_3_0, 0); // GPIO bitmask 0x40
|
||||
TIMER_sleepMs(18); // Fixed 18 ms delay when unsetting this GPIO.
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
static void NAKED core23Entry(void)
|
||||
{
|
||||
__cpsid(aif);
|
||||
REG_CPU_II_CNT = 1;
|
||||
REG_GIC_CPU_CTRL = 1;
|
||||
|
||||
const u32 cpuId = __getCpuId();
|
||||
// Tell core 0 we are here
|
||||
|
@ -42,8 +42,8 @@ static void NAKED core23Entry(void)
|
|||
do
|
||||
{
|
||||
__wfi();
|
||||
tmp = REG_CPU_II_AKN;
|
||||
REG_CPU_II_EOI = tmp;
|
||||
tmp = REG_GIC_CPU_INTACK;
|
||||
REG_GIC_CPU_EOI = tmp;
|
||||
} while(tmp != cpuId);
|
||||
|
||||
// Jump to real entrypoint
|
||||
|
@ -55,12 +55,12 @@ void core123Init(void)
|
|||
{
|
||||
if(REG_CFG11_SOCINFO & 2)
|
||||
{
|
||||
REG_CPU_II_CNT = 1;
|
||||
for(u32 i = 0; i < 4; i++) REGs_GID_ENA_CLR[i] = 0xFFFFFFFFu;
|
||||
REGs_GID_PEN_CLR[2] = 0x1000000; // Interrupt ID 88
|
||||
REGs_GID_IPRIO[22] = 0;
|
||||
REGs_GID_ITARG[22] = 1;
|
||||
REGs_GID_ENA_SET[2] = 0x1000000;
|
||||
REG_GIC_CPU_CTRL = 1;
|
||||
for(u32 i = 0; i < 4; i++) REGs_GIC_DIST_ENABLE_CLEAR[i] = 0xFFFFFFFFu;
|
||||
REGs_GIC_DIST_PENDING_CLEAR[2] = 0x1000000; // Interrupt ID 88
|
||||
REGs_GIC_DIST_PRI[22] = 0;
|
||||
REGs_GIC_DIST_TARGET[22] = 1;
|
||||
REGs_GIC_DIST_ENABLE_SET[2] = 0x1000000;
|
||||
|
||||
#ifdef CORE123_INIT
|
||||
u16 clkCnt;
|
||||
|
@ -78,7 +78,7 @@ void core123Init(void)
|
|||
wait(403);
|
||||
|
||||
CPU_setClock(clkCnt);
|
||||
REGs_GID_PEN_CLR[2] = 0x1000000;
|
||||
REGs_GIC_DIST_PENDING_CLEAR[2] = 0x1000000;
|
||||
REG_UNK_10140400 = 3; // Clock related?
|
||||
}
|
||||
REG_UNK_10140410 = 0x3FFFF; // Clock related?
|
||||
|
@ -96,7 +96,7 @@ void core123Init(void)
|
|||
if(clkCnt != tmpClkCnt)
|
||||
{
|
||||
CPU_setClock(tmpClkCnt);
|
||||
REGs_GID_PEN_CLR[2] = 0x1000000;
|
||||
REGs_GIC_DIST_PENDING_CLEAR[2] = 0x1000000;
|
||||
}
|
||||
|
||||
REG_CFG11_BOOTROM_OVERLAY_CNT = 1;
|
||||
|
@ -113,7 +113,7 @@ void core123Init(void)
|
|||
if(clkCnt != tmpClkCnt) CPU_setClock(clkCnt);
|
||||
}
|
||||
|
||||
REGs_GID_ENA_CLR[2] = 0x1000000;
|
||||
REGs_GIC_DIST_ENABLE_CLEAR[2] = 0x1000000;
|
||||
|
||||
// Wakeup core 2/3 and let them jump to their entrypoint.
|
||||
IRQ_softwareInterrupt(2, 0b0100);
|
||||
|
@ -122,7 +122,7 @@ void core123Init(void)
|
|||
// Just enables the New 3DS FCRAM extension (if not already done)
|
||||
if((REG_CFG11_MPCORE_CLKCNT & 7) != 1) CPU_setClock(1);
|
||||
|
||||
REGs_GID_ENA_CLR[2] = 0x1000000;
|
||||
REGs_GIC_DIST_ENABLE_CLEAR[2] = 0x1000000;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ BEGIN_ASM_FUNC irqHandler
|
|||
stmfd sp!, {r0-r3, r12, lr}
|
||||
ldr r12, =MPCORE_PRIV_REG_BASE
|
||||
ldr r2, =irqIsrTable
|
||||
ldr r0, [r12, #0x10C] @ REG_CPU_II_AKN
|
||||
ldr r0, [r12, #0x10C] @ REG_GIC_CPU_INTACK
|
||||
and r1, r0, #0x7F
|
||||
cmp r1, #32
|
||||
mrclo p15, 0, r3, c0, c0, 5 @ Get CPU ID
|
||||
|
@ -85,7 +85,7 @@ BEGIN_ASM_FUNC irqHandler
|
|||
ldr r12, =MPCORE_PRIV_REG_BASE
|
||||
cpsid i
|
||||
irqHandler_skip_processing:
|
||||
str r0, [r12, #0x110] @ REG_CPU_II_EOI
|
||||
str r0, [r12, #0x110] @ REG_GIC_CPU_EOI
|
||||
ldmfd sp!, {r0-r3, r12, lr}
|
||||
rfefd sp! @ Restore lr (pc) and spsr (cpsr)
|
||||
END_ASM_FUNC
|
||||
|
|
|
@ -98,12 +98,12 @@ void GFX_init(GfxFbFmt fmtTop, GfxFbFmt fmtBot)
|
|||
REG_LCD_UNK00C = 0x10001;
|
||||
|
||||
// Register IRQ handlers.
|
||||
IRQ_registerIsr(IRQ_PSC0, 14, 0, true, gfxIrqHandler);
|
||||
IRQ_registerIsr(IRQ_PSC1, 14, 0, true, gfxIrqHandler);
|
||||
IRQ_registerIsr(IRQ_PDC0, 14, 0, true, gfxIrqHandler);
|
||||
//IRQ_registerIsr(IRQ_PDC1, 14, 0, true, gfxIrqHandler);
|
||||
IRQ_registerIsr(IRQ_PPF, 14, 0, true, gfxIrqHandler);
|
||||
IRQ_registerIsr(IRQ_P3D, 14, 0, true, gfxIrqHandler);
|
||||
IRQ_registerIsr(IRQ_PSC0, 14, 0, gfxIrqHandler);
|
||||
IRQ_registerIsr(IRQ_PSC1, 14, 0, gfxIrqHandler);
|
||||
IRQ_registerIsr(IRQ_PDC0, 14, 0, gfxIrqHandler);
|
||||
//IRQ_registerIsr(IRQ_PDC1, 14, 0, gfxIrqHandler);
|
||||
IRQ_registerIsr(IRQ_PPF, 14, 0, gfxIrqHandler);
|
||||
IRQ_registerIsr(IRQ_P3D, 14, 0, gfxIrqHandler);
|
||||
|
||||
// Clear entire VRAM.
|
||||
GX_memoryFill((u32*)VRAM_BANK0, 1u<<9, VRAM_SIZE / 2, 0,
|
||||
|
|
|
@ -23,97 +23,90 @@
|
|||
|
||||
#define GPIO_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x47000)
|
||||
// 3 GPIOs (bits 0-2)
|
||||
#define REG_GPIO1_DAT *((vu16*)(GPIO_REGS_BASE + 0x00)) // Read-only?
|
||||
#define REG_GPIO1_UNK2 *((vu16*)(GPIO_REGS_BASE + 0x02)) // ?
|
||||
#define REG_GPIO1_UNK4 *((vu32*)(GPIO_REGS_BASE + 0x04)) // ?
|
||||
#define REG_GPIO1_DAT *((const vu8*)(GPIO_REGS_BASE + 0x00)) // Read-only.
|
||||
|
||||
// 2 GPIOs (bits 0-1)
|
||||
#define REG_GPIO2 *((vu32*)(GPIO_REGS_BASE + 0x10))
|
||||
#define REG_GPIO2_DAT *((vu8* )(GPIO_REGS_BASE + 0x10))
|
||||
#define REG_GPIO2_DIR *((vu8* )(GPIO_REGS_BASE + 0x11)) // 0 = input, 1 = output
|
||||
#define REG_GPIO2_EDGE *((vu8* )(GPIO_REGS_BASE + 0x12)) // IRQ edge 0 = falling, 1 = rising
|
||||
#define REG_GPIO2_IRQ *((vu8* )(GPIO_REGS_BASE + 0x13)) // 1 = IRQ enable
|
||||
|
||||
#define REG_GPIO2 *(( vu32*)(GPIO_REGS_BASE + 0x10))
|
||||
#define REG_GPIO2_DAT *(( vu8*)(GPIO_REGS_BASE + 0x10))
|
||||
#define REG_GPIO2_DIR *(( vu8*)(GPIO_REGS_BASE + 0x11)) // 0 = input, 1 = output.
|
||||
#define REG_GPIO2_EDGE *(( vu8*)(GPIO_REGS_BASE + 0x12)) // IRQ edge 0 = falling, 1 = rising.
|
||||
#define REG_GPIO2_IRQ *(( vu8*)(GPIO_REGS_BASE + 0x13)) // 1 = IRQ enable.
|
||||
// 1 GPIO (bit 0)
|
||||
#define REG_GPIO3 *((vu8* )(GPIO_REGS_BASE + 0x14))
|
||||
#define REG_GPIO3_DAT *((vu8* )(GPIO_REGS_BASE + 0x14)) // Only bit 0 writable
|
||||
#define REG_GPIO3_UNK5 *((vu8* )(GPIO_REGS_BASE + 0x15)) // Only 1 bit?
|
||||
#define REG_GPIO2_DAT2 *(( vu16*)(GPIO_REGS_BASE + 0x14)) // Only bit 0 writable.
|
||||
|
||||
// 12 GPIOs (bits 0-11)
|
||||
#define REG_GPIO4_H1 *((vu32*)(GPIO_REGS_BASE + 0x20)) // First half
|
||||
#define REG_GPIO4_DAT *((vu16*)(GPIO_REGS_BASE + 0x20))
|
||||
#define REG_GPIO4_DIR *((vu16*)(GPIO_REGS_BASE + 0x22))
|
||||
#define REG_GPIO4_H2 *((vu32*)(GPIO_REGS_BASE + 0x24)) // Second half
|
||||
#define REG_GPIO4_EDGE *((vu16*)(GPIO_REGS_BASE + 0x24))
|
||||
#define REG_GPIO4_IRQ *((vu16*)(GPIO_REGS_BASE + 0x26))
|
||||
|
||||
#define REG_GPIO3_H1 *(( vu32*)(GPIO_REGS_BASE + 0x20)) // First half.
|
||||
#define REG_GPIO3_DAT *(( vu16*)(GPIO_REGS_BASE + 0x20))
|
||||
#define REG_GPIO3_DIR *(( vu16*)(GPIO_REGS_BASE + 0x22))
|
||||
#define REG_GPIO3_H2 *(( vu32*)(GPIO_REGS_BASE + 0x24)) // Second half.
|
||||
#define REG_GPIO3_EDGE *(( vu16*)(GPIO_REGS_BASE + 0x24))
|
||||
#define REG_GPIO3_IRQ *(( vu16*)(GPIO_REGS_BASE + 0x26))
|
||||
// 1 GPIO (bit 0)
|
||||
#define REG_GPIO5_DAT *((vu16*)(GPIO_REGS_BASE + 0x28)) // WiFi
|
||||
#define REG_GPIO3_DAT2 *(( vu16*)(GPIO_REGS_BASE + 0x28)) // WiFi.
|
||||
|
||||
|
||||
static vu16 *const datRegs[5] = {®_GPIO1_DAT, (vu16*)®_GPIO2_DAT, (vu16*)®_GPIO3_DAT, ®_GPIO4_DAT, ®_GPIO5_DAT};
|
||||
static vu16 *const datRegs[5] = {(vu16*)®_GPIO1_DAT, (vu16*)®_GPIO2_DAT, ®_GPIO2_DAT2, ®_GPIO3_DAT, ®_GPIO3_DAT2};
|
||||
|
||||
|
||||
|
||||
void GPIO_config(Gpio gpio, u8 cfg)
|
||||
{
|
||||
const u8 bank = gpio & 7u;
|
||||
const u8 pin = gpio>>3;
|
||||
const u8 regIdx = gpio & 7u;
|
||||
const u8 pinNum = gpio>>3;
|
||||
|
||||
// GPIO1 and GPIO5 are not configurable.
|
||||
if(bank == 1)
|
||||
// GPIO1 and GPIO3_DAT2 are not configurable.
|
||||
if(regIdx == 1)
|
||||
{
|
||||
u32 reg = REG_GPIO2 & ~((1u<<24 | 1u<<16 | 1u<<8)<<pin);
|
||||
u32 reg = REG_GPIO2 & ~((1u<<24 | 1u<<16 | 1u<<8)<<pinNum);
|
||||
|
||||
if(cfg & GPIO_OUTPUT) reg |= (1u<<8)<<pin; // Direction
|
||||
if(cfg & GPIO_EDGE_RISING) reg |= (1u<<16)<<pin; // IRQ edge
|
||||
if(cfg & GPIO_IRQ_ENABLE) reg |= (1u<<24)<<pin; // IRQ enable
|
||||
if(cfg & GPIO_OUTPUT) reg |= (1u<<8)<<pinNum; // Direction.
|
||||
if(cfg & GPIO_EDGE_RISING) reg |= (1u<<16)<<pinNum; // IRQ edge.
|
||||
if(cfg & GPIO_IRQ_ENABLE) reg |= (1u<<24)<<pinNum; // IRQ enable.
|
||||
|
||||
REG_GPIO2 = reg;
|
||||
}
|
||||
else if(bank == 3)
|
||||
else if(regIdx == 3)
|
||||
{
|
||||
u32 reg = REG_GPIO4_H1 & ~((1u<<16)<<pin);
|
||||
u32 reg2 = REG_GPIO4_H2 & ~((1u<<16 | 1u)<<pin);
|
||||
u32 reg = REG_GPIO3_H1 & ~((1u<<16)<<pinNum);
|
||||
u32 reg2 = REG_GPIO3_H2 & ~((1u<<16 | 1u)<<pinNum);
|
||||
|
||||
if(cfg & GPIO_OUTPUT) reg |= (1u<<16)<<pin; // Direction
|
||||
if(cfg & GPIO_EDGE_RISING) reg2 |= 1u<<pin; // IRQ edge
|
||||
if(cfg & GPIO_IRQ_ENABLE) reg2 |= (1u<<16)<<pin; // IRQ enable
|
||||
if(cfg & GPIO_OUTPUT) reg |= (1u<<16)<<pinNum; // Direction.
|
||||
if(cfg & GPIO_EDGE_RISING) reg2 |= 1u<<pinNum; // IRQ edge.
|
||||
if(cfg & GPIO_IRQ_ENABLE) reg2 |= (1u<<16)<<pinNum; // IRQ enable.
|
||||
|
||||
REG_GPIO4_H1 = reg;
|
||||
REG_GPIO4_H2 = reg2;
|
||||
REG_GPIO3_H1 = reg;
|
||||
REG_GPIO3_H2 = reg2;
|
||||
}
|
||||
}
|
||||
|
||||
u8 GPIO_read(Gpio gpio)
|
||||
bool GPIO_read(Gpio gpio)
|
||||
{
|
||||
const u8 bank = gpio & 7u;
|
||||
const u8 pin = gpio>>3;
|
||||
const u8 regIdx = gpio & 7u;
|
||||
const u8 pinNum = gpio>>3;
|
||||
|
||||
if(bank > 4) return 0;
|
||||
if(regIdx > 4) return 0;
|
||||
|
||||
return *datRegs[bank]>>pin & 1u;
|
||||
return *datRegs[regIdx]>>pinNum & 1u;
|
||||
}
|
||||
|
||||
void GPIO_write(Gpio gpio, u8 val)
|
||||
void GPIO_write(Gpio gpio, bool val)
|
||||
{
|
||||
const u8 bank = gpio & 7u;
|
||||
const u8 pin = gpio>>3;
|
||||
const u8 regIdx = gpio & 7u;
|
||||
const u8 pinNum = gpio>>3;
|
||||
|
||||
if(bank == 0 || bank > 4) return;
|
||||
if(regIdx == 0 || regIdx > 4) return;
|
||||
|
||||
u16 tmp = *datRegs[bank];
|
||||
tmp &= ~(1u<<pin) | val<<pin;
|
||||
*datRegs[bank] = tmp;
|
||||
u16 tmp = *datRegs[regIdx];
|
||||
tmp &= ~(1u<<pinNum) | (u16)val<<pinNum;
|
||||
*datRegs[regIdx] = tmp;
|
||||
}
|
||||
|
||||
/*void GPIO_dbgPrint(void)
|
||||
/*#include "arm11/fmt.h"
|
||||
void GPIO_dbgPrint(void)
|
||||
{
|
||||
#include "arm11/fmt.h"
|
||||
|
||||
ee_printf("REG_GPIO1_DAT %04" PRIx16 "\nREG_GPIO1_UNK2 %04" PRIx16 "\nREG_GPIO1_UNK4 %08" PRIx32 "\n", REG_GPIO1_DAT, REG_GPIO1_UNK2, REG_GPIO1_UNK4);
|
||||
ee_printf("REG_GPIO1_DAT %04" PRIx8 "\n", REG_GPIO1_DAT);
|
||||
ee_printf("REG_GPIO2_DAT %02" PRIx8 "\nREG_GPIO2_DIR %02" PRIx8 "\nREG_GPIO2_EDGE %02" PRIx8 "\nREG_GPIO2_IRQ %02" PRIx8 "\n", REG_GPIO2_DAT, REG_GPIO2_DIR, REG_GPIO2_EDGE, REG_GPIO2_IRQ);
|
||||
ee_printf("REG_GPIO3_DAT %02" PRIx8 "\nREG_GPIO3_UNK5 %02" PRIx8 "\n", REG_GPIO3_DAT, REG_GPIO3_UNK5);
|
||||
ee_printf("REG_GPIO4_DAT %04" PRIx16 "\nREG_GPIO4_DIR %04" PRIx16 "\nREG_GPIO4_EDGE %04" PRIx16 "\nREG_GPIO4_IRQ %04" PRIx16 "\n", REG_GPIO4_DAT, REG_GPIO4_DIR, REG_GPIO4_EDGE, REG_GPIO4_IRQ);
|
||||
ee_printf("REG_GPIO5_DAT %04" PRIx16 "\n", REG_GPIO5_DAT);
|
||||
ee_printf("REG_GPIO2_DAT2 %04" PRIx16 "\n", REG_GPIO2_DAT2);
|
||||
ee_printf("REG_GPIO3_DAT %04" PRIx16 "\nREG_GPIO3_DIR %04" PRIx16 "\nREG_GPIO3_EDGE %04" PRIx16 "\nREG_GPIO3_IRQ %04" PRIx16 "\n", REG_GPIO3_DAT, REG_GPIO3_DIR, REG_GPIO3_EDGE, REG_GPIO3_IRQ);
|
||||
ee_printf("REG_GPIO3_DAT2 %04" PRIx16 "\n", REG_GPIO3_DAT2);
|
||||
}*/
|
||||
|
|
|
@ -127,9 +127,9 @@ void I2C_init(void)
|
|||
regs->I2C_CNTEX = I2C_CLK_STRETCH;
|
||||
regs->I2C_SCL = I2C_DELAYS(5u, 0u);
|
||||
|
||||
IRQ_registerIsr(IRQ_I2C1, 14, 0, true, NULL);
|
||||
IRQ_registerIsr(IRQ_I2C2, 14, 0, true, NULL);
|
||||
IRQ_registerIsr(IRQ_I2C3, 14, 0, true, NULL);
|
||||
IRQ_registerIsr(IRQ_I2C1, 14, 0, NULL);
|
||||
IRQ_registerIsr(IRQ_I2C2, 14, 0, NULL);
|
||||
IRQ_registerIsr(IRQ_I2C3, 14, 0, NULL);
|
||||
}
|
||||
|
||||
static bool i2cStartTransfer(u8 devAddr, u8 regAddr, bool read, I2cRegs *const regs)
|
||||
|
|
|
@ -18,77 +18,172 @@
|
|||
|
||||
#include "types.h"
|
||||
#include "arm11/hardware/interrupt.h"
|
||||
#include "mmio.h"
|
||||
#include "arm.h"
|
||||
#include "arm11/hardware/cfg11.h"
|
||||
|
||||
|
||||
// Level high active keeps firing until acknowledged (on the periphal side).
|
||||
// Rising edge sensitive only fires on rising edges.
|
||||
#define ICONF_RSVD (0u) // Unused/reserved.
|
||||
#define ICONF_L_NN (0u) // Level high active, N-N software model.
|
||||
#define ICONF_L_1N (1u) // Level high active, 1-N software model.
|
||||
#define ICONF_E_NN (2u) // Rising edge sinsitive, N-N software model.
|
||||
#define ICONF_E_1N (3u) // Rising edge sinsitive, 1-N software model.
|
||||
#define MAKE_ICONF(c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15) \
|
||||
((c15)<<30 | (c14)<<28 | (c13)<<26 | (c12)<<24 | (c11)<<22 | \
|
||||
(c10)<<20 | (c9)<<18 | (c8)<<16 | (c7)<<14 | (c6)<<12 | \
|
||||
(c5)<<10 | (c4)<<8 | (c3)<<6 | (c2)<<4 | (c1)<<2 | (c0))
|
||||
|
||||
|
||||
// First 32 interrupts are private to each core (4 * 32).
|
||||
// 96 external interrupts (total 128).
|
||||
IrqIsr irqIsrTable[224] = {0};
|
||||
|
||||
|
||||
|
||||
void IRQ_init(void)
|
||||
// Per core interrupts.
|
||||
static void configPrivateInterrupts(void)
|
||||
{
|
||||
REG_CPU_II_CNT = 0; // Disable the interrupt interface for this CPU.
|
||||
// Disable first 32 interrupts.
|
||||
// Interrupts 0-15 cant be disabled.
|
||||
REGs_GIC_DIST_ENABLE_CLEAR[0] = 0xFFFFFFFFu;
|
||||
|
||||
if(!__getCpuId()) // Core 0
|
||||
{
|
||||
REG_CFG11_FIQ_CNT = 2; // Disable FIQs.
|
||||
// Set first 32 interrupts to inactive state.
|
||||
// Interrupt 0-15 can't be set to inactive.
|
||||
REGs_GIC_DIST_PENDING_CLEAR[0] = 0xFFFFFFFFu;
|
||||
|
||||
REG_GID_CNT = 0; // Disable the global interrupt distributor.
|
||||
// Set first 32 interrupts to lowest priority.
|
||||
for(u32 i = 0; i < 8; i++) REGs_GIC_DIST_PRI[i] = 0xF0F0F0F0u;
|
||||
|
||||
// Disable all 128 interrupts.
|
||||
REGs_GID_ENA_CLR[0] = 0xFFFFFFFFu; // Interrupts 0-15 cant be disabled.
|
||||
REGs_GID_ENA_CLR[1] = 0xFFFFFFFFu;
|
||||
REGs_GID_ENA_CLR[2] = 0xFFFFFFFFu;
|
||||
REGs_GID_ENA_CLR[3] = 0xFFFFFFFFu;
|
||||
// Interrupt target 0-31 can't be changed.
|
||||
|
||||
// Set all pending interrupts to inactive state.
|
||||
REGs_GID_PEN_CLR[0] = 0xFFFFFFFFu; // Interrupt 0-15 can't be set to inactive apparently.
|
||||
REGs_GID_PEN_CLR[1] = 0xFFFFFFFFu;
|
||||
REGs_GID_PEN_CLR[2] = 0xFFFFFFFFu;
|
||||
REGs_GID_PEN_CLR[3] = 0xFFFFFFFFu;
|
||||
|
||||
// Set all 128 interrupts to lowest priority.
|
||||
for(u32 i = 0; i < 32; i++) REGs_GID_IPRIO[i] = 0xE0E0E0E0u;
|
||||
|
||||
// Set all 128 interrupts to target no CPU.
|
||||
// Interrupt 0-31 can't be changed.
|
||||
for(u32 i = 8; i < 32; i++) REGs_GID_ITARG[i] = 0;
|
||||
|
||||
// Set all interrupts to rising edge sensitive and 1-N software model.
|
||||
for(u32 i = 0; i < 8; i++) REGs_GID_ICONF[i] = 0xFFFFFFFFu;
|
||||
|
||||
REG_GID_CNT = 1; // Enable the global interrupt distributor.
|
||||
}
|
||||
else // Other core. Same as above but for core specific IRQs.
|
||||
{
|
||||
REGs_GID_ENA_CLR[0] = 0xFFFFFFFFu;
|
||||
|
||||
REGs_GID_PEN_CLR[0] = 0xFFFFFFFFu;
|
||||
|
||||
for(u32 i = 0; i < 8; i++) REGs_GID_IPRIO[i] = 0xE0E0E0E0u;
|
||||
|
||||
REGs_GID_ICONF[0] = 0xFFFFFFFFu;
|
||||
REGs_GID_ICONF[1] = 0xFFFFFFFFu;
|
||||
}
|
||||
|
||||
|
||||
REG_CPU_II_MASK = 0xF0; // Mask no interrupt.
|
||||
REG_CPU_II_BIN_POI = 3; // All priority bits are compared for pre-emption.
|
||||
REG_CPU_II_CNT = 1; // Enable the interrupt interface for this CPU.
|
||||
|
||||
// Get rid of all interrupts stuck in pending/active state.
|
||||
u32 tmp;
|
||||
do
|
||||
{
|
||||
tmp = REG_CPU_II_AKN; // Aknowledge
|
||||
REG_CPU_II_EOI = tmp; // End of interrupt
|
||||
} while(tmp != 1023);
|
||||
// Kernel11 config.
|
||||
// Interrupts 0-15.
|
||||
REGs_GIC_DIST_CONFIG[0] = MAKE_ICONF(ICONF_E_NN, ICONF_E_NN, ICONF_E_NN, ICONF_E_NN, // 0-3
|
||||
ICONF_E_NN, ICONF_E_NN, ICONF_E_NN, ICONF_E_NN, // 4-7
|
||||
ICONF_E_NN, ICONF_E_NN, ICONF_E_NN, ICONF_E_NN, // 8-11
|
||||
ICONF_E_NN, ICONF_E_NN, ICONF_E_NN, ICONF_E_NN); // 12-15
|
||||
// Interrupts 16-31.
|
||||
REGs_GIC_DIST_CONFIG[1] = MAKE_ICONF(ICONF_RSVD, ICONF_RSVD, ICONF_RSVD, ICONF_RSVD, // 16-19
|
||||
ICONF_RSVD, ICONF_RSVD, ICONF_RSVD, ICONF_RSVD, // 20-23
|
||||
ICONF_RSVD, ICONF_RSVD, ICONF_RSVD, ICONF_RSVD, // 24-27
|
||||
ICONF_RSVD, ICONF_E_NN, ICONF_E_NN, ICONF_RSVD); // 28-31
|
||||
}
|
||||
|
||||
void IRQ_registerIsr(Interrupt id, u8 prio, u8 cpuMask, bool edgeTriggered, IrqIsr isr)
|
||||
static void configExternalInterrupts(void)
|
||||
{
|
||||
// Kernel11 config.
|
||||
/*static const u32 iconfTable[6] =
|
||||
{
|
||||
// Interrupts 32-47.
|
||||
MAKE_ICONF(ICONF_L_1N, ICONF_L_1N, ICONF_L_1N, ICONF_L_1N, // 32-35
|
||||
ICONF_E_1N, ICONF_L_1N, ICONF_RSVD, ICONF_RSVD, // 36-39
|
||||
ICONF_L_1N, ICONF_L_1N, ICONF_L_1N, ICONF_L_1N, // 40-43
|
||||
ICONF_L_1N, ICONF_L_1N, ICONF_RSVD, ICONF_RSVD), // 44-47
|
||||
// Interrupts 48-63.
|
||||
MAKE_ICONF(ICONF_L_1N, ICONF_L_1N, ICONF_L_1N, ICONF_L_1N, // 48-51
|
||||
ICONF_L_1N, ICONF_L_1N, ICONF_L_1N, ICONF_L_1N, // 52-55
|
||||
ICONF_L_1N, ICONF_L_1N, ICONF_L_1N, ICONF_L_1N, // 56-59
|
||||
ICONF_RSVD, ICONF_RSVD, ICONF_RSVD, ICONF_RSVD), // 60-63
|
||||
// Interrupts 64-79.
|
||||
MAKE_ICONF(ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, // 64-67
|
||||
ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, ICONF_RSVD, // 68-71
|
||||
ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, // 72-75
|
||||
ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, ICONF_L_1N), // 76-79
|
||||
// Interrupts 80-95.
|
||||
MAKE_ICONF(ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, // 80-83
|
||||
ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, // 84-87
|
||||
ICONF_L_1N, ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, // 88-91
|
||||
ICONF_RSVD, ICONF_RSVD, ICONF_RSVD, ICONF_E_1N), // 92-95
|
||||
// Interrupts 96-111.
|
||||
MAKE_ICONF(ICONF_E_1N, ICONF_E_1N, ICONF_RSVD, ICONF_RSVD, // 96-99
|
||||
ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, ICONF_RSVD, // 100-103
|
||||
ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, // 104-107
|
||||
ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, ICONF_E_1N), // 108-111
|
||||
// Interrupts 112-127.
|
||||
MAKE_ICONF(ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, // 112-115
|
||||
ICONF_E_1N, ICONF_E_1N, ICONF_L_1N, ICONF_L_1N, // 116-119
|
||||
ICONF_E_1N, ICONF_L_1N, ICONF_L_1N, ICONF_L_1N, // 120-123
|
||||
ICONF_L_1N, ICONF_L_1N, ICONF_RSVD, ICONF_RSVD) // 124-127
|
||||
};*/
|
||||
// Modified.
|
||||
static const u32 iconfTable[6] =
|
||||
{
|
||||
// Interrupts 32-47.
|
||||
MAKE_ICONF(ICONF_L_1N, ICONF_L_1N, ICONF_L_1N, ICONF_L_1N, // 32-35
|
||||
ICONF_E_1N, ICONF_L_1N, ICONF_RSVD, ICONF_RSVD, // 36-39
|
||||
ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, // 40-43
|
||||
ICONF_E_1N, ICONF_E_1N, ICONF_RSVD, ICONF_RSVD), // 44-47
|
||||
// Interrupts 48-63.
|
||||
MAKE_ICONF(ICONF_L_1N, ICONF_L_1N, ICONF_L_1N, ICONF_L_1N, // 48-51
|
||||
ICONF_L_1N, ICONF_L_1N, ICONF_L_1N, ICONF_L_1N, // 52-55
|
||||
ICONF_L_1N, ICONF_L_1N, ICONF_L_1N, ICONF_L_1N, // 56-59
|
||||
ICONF_RSVD, ICONF_RSVD, ICONF_RSVD, ICONF_RSVD), // 60-63
|
||||
// Interrupts 64-79.
|
||||
MAKE_ICONF(ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, // 64-67
|
||||
ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, ICONF_RSVD, // 68-71
|
||||
ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, // 72-75
|
||||
ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, ICONF_L_1N), // 76-79
|
||||
// Interrupts 80-95.
|
||||
MAKE_ICONF(ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, // 80-83
|
||||
ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, // 84-87
|
||||
ICONF_L_1N, ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, // 88-91
|
||||
ICONF_RSVD, ICONF_RSVD, ICONF_RSVD, ICONF_E_1N), // 92-95
|
||||
// Interrupts 96-111.
|
||||
MAKE_ICONF(ICONF_E_1N, ICONF_E_1N, ICONF_RSVD, ICONF_RSVD, // 96-99
|
||||
ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, ICONF_RSVD, // 100-103
|
||||
ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, // 104-107
|
||||
ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, ICONF_E_1N), // 108-111
|
||||
// Interrupts 112-127.
|
||||
MAKE_ICONF(ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, ICONF_E_1N, // 112-115
|
||||
ICONF_E_1N, ICONF_E_1N, ICONF_L_1N, ICONF_L_1N, // 116-119
|
||||
ICONF_E_1N, ICONF_L_1N, ICONF_L_1N, ICONF_L_1N, // 120-123
|
||||
ICONF_L_1N, ICONF_L_1N, ICONF_RSVD, ICONF_RSVD) // 124-127
|
||||
};
|
||||
|
||||
iomemcpy(®s_GIC_DIST_CONFIG[2], iconfTable, 24);
|
||||
}
|
||||
|
||||
// Note: Core 0 must execute this last.
|
||||
void IRQ_init(void)
|
||||
{
|
||||
REG_GIC_DIST_CTRL = 0; // Disable the global interrupt distributor.
|
||||
|
||||
configPrivateInterrupts();
|
||||
|
||||
if(__getCpuId() == 0)
|
||||
{
|
||||
// Disable the remaining 96 interrupts.
|
||||
// Set the remaining 96 pending interrupts to inactive state.
|
||||
for(u32 i = 1; i < 4; i++)
|
||||
{
|
||||
REGs_GIC_DIST_ENABLE_CLEAR[i] = 0xFFFFFFFFu;
|
||||
REGs_GIC_DIST_PENDING_CLEAR[i] = 0xFFFFFFFFu;
|
||||
}
|
||||
|
||||
// Set the remaining 96 interrupts to lowest priority.
|
||||
// Set the remaining 96 interrupts to target no CPU.
|
||||
for(u32 i = 8; i < 32; i++)
|
||||
{
|
||||
REGs_GIC_DIST_PRI[i] = 0xF0F0F0F0u;
|
||||
REGs_GIC_DIST_TARGET[i] = 0;
|
||||
}
|
||||
|
||||
configExternalInterrupts();
|
||||
|
||||
REG_GIC_DIST_CTRL = 1; // Enable the global interrupt distributor.
|
||||
}
|
||||
|
||||
|
||||
REG_GIC_CPU_PRIMASK = 0xF0; // Mask no interrupt.
|
||||
REG_GIC_CPU_BINPOINT = 3; // All priority bits are compared for pre-emption.
|
||||
REG_GIC_CPU_CTRL = 1; // Enable the interrupt interface for this CPU.
|
||||
|
||||
REG_CFG11_FIQ_CNT = 2; // Disable FIQs.
|
||||
}
|
||||
|
||||
void IRQ_registerIsr(Interrupt id, u8 prio, u8 cpuMask, IrqIsr isr)
|
||||
{
|
||||
const u32 cpuId = __getCpuId();
|
||||
if(!cpuMask) cpuMask = 1u<<cpuId;
|
||||
|
@ -99,21 +194,42 @@ void IRQ_registerIsr(Interrupt id, u8 prio, u8 cpuMask, bool edgeTriggered, IrqI
|
|||
|
||||
// Priority
|
||||
u32 shift = (id % 4 * 8) + 4;
|
||||
u32 tmp = REGs_GID_IPRIO[id>>2] & ~(0xFu<<shift);
|
||||
REGs_GID_IPRIO[id>>2] = tmp | (u32)prio<<shift;
|
||||
u32 tmp = REGs_GIC_DIST_PRI[id / 4] & ~(0xFu<<shift);
|
||||
REGs_GIC_DIST_PRI[id / 4] = tmp | (u32)prio<<shift;
|
||||
|
||||
// Target
|
||||
shift = id % 4 * 8;
|
||||
tmp = REGs_GID_ITARG[id>>2] & ~(0xFu<<shift);
|
||||
REGs_GID_ITARG[id>>2] = tmp | (u32)cpuMask<<shift;
|
||||
|
||||
// Trigger level
|
||||
shift = (id % 16 * 2) + 1;
|
||||
tmp = REGs_GID_ICONF[id>>4] & ~(1u<<shift);
|
||||
REGs_GID_ICONF[id>>4] = tmp | (u32)edgeTriggered<<shift;
|
||||
tmp = REGs_GIC_DIST_TARGET[id / 4] & ~(0xFu<<shift);
|
||||
REGs_GIC_DIST_TARGET[id / 4] = tmp | (u32)cpuMask<<shift;
|
||||
|
||||
// Enable it.
|
||||
REGs_GID_ENA_SET[id>>5] = 1u<<(id % 32);
|
||||
REGs_GIC_DIST_ENABLE_SET[id / 32] = 1u<<(id % 32);
|
||||
|
||||
leaveCriticalSection(oldState);
|
||||
}
|
||||
|
||||
void IRQ_enable(Interrupt id)
|
||||
{
|
||||
REGs_GIC_DIST_ENABLE_SET[id / 32] = 1u<<(id % 32);
|
||||
}
|
||||
|
||||
void IRQ_disable(Interrupt id)
|
||||
{
|
||||
REGs_GIC_DIST_ENABLE_CLEAR[id / 32] = 1u<<(id % 32);
|
||||
}
|
||||
|
||||
void IRQ_softwareInterrupt(Interrupt id, u8 cpuMask)
|
||||
{
|
||||
REG_GIC_DIST_SOFTINT = (u32)cpuMask<<16 | id;
|
||||
}
|
||||
|
||||
void IRQ_setPriority(Interrupt id, u8 prio)
|
||||
{
|
||||
const u32 oldState = enterCriticalSection();
|
||||
|
||||
const u32 shift = (id % 4 * 8) + 4;
|
||||
u32 tmp = REGs_GIC_DIST_PRI[id / 4] & ~(0xFu<<shift);
|
||||
REGs_GIC_DIST_PRI[id / 4] = tmp | (u32)prio<<shift;
|
||||
|
||||
leaveCriticalSection(oldState);
|
||||
}
|
||||
|
@ -122,35 +238,9 @@ void IRQ_unregisterIsr(Interrupt id)
|
|||
{
|
||||
const u32 oldState = enterCriticalSection();
|
||||
|
||||
REGs_GID_ENA_CLR[id>>5] = 1u<<(id % 32);
|
||||
REGs_GIC_DIST_ENABLE_CLEAR[id / 32] = 1u<<(id % 32);
|
||||
|
||||
irqIsrTable[(id < 32 ? 32 * __getCpuId() + id : 96u + id)] = (IrqIsr)NULL;
|
||||
|
||||
leaveCriticalSection(oldState);
|
||||
}
|
||||
|
||||
void IRQ_enable(Interrupt id)
|
||||
{
|
||||
REGs_GID_ENA_SET[id>>5] = 1u<<(id % 32);
|
||||
}
|
||||
|
||||
void IRQ_disable(Interrupt id)
|
||||
{
|
||||
REGs_GID_ENA_CLR[id>>5] = 1u<<(id % 32);
|
||||
}
|
||||
|
||||
void IRQ_setPriority(Interrupt id, u8 prio)
|
||||
{
|
||||
const u32 oldState = enterCriticalSection();
|
||||
|
||||
const u32 shift = (id % 4 * 8) + 4;
|
||||
u32 tmp = REGs_GID_IPRIO[id>>2] & ~(0xFu<<shift);
|
||||
REGs_GID_IPRIO[id>>2] = tmp | (u32)prio<<shift;
|
||||
|
||||
leaveCriticalSection(oldState);
|
||||
}
|
||||
|
||||
void IRQ_softwareInterrupt(Interrupt id, u8 cpuMask)
|
||||
{
|
||||
REG_GID_SW_INT = (u32)cpuMask<<16 | id;
|
||||
}
|
||||
|
|
|
@ -60,8 +60,8 @@ Result LGY_prepareGbaMode(bool gbaBios, u16 saveType)
|
|||
while(*((vu8*)0x10141210) & 4u); // Wait for acknowledge?
|
||||
|
||||
REG_LGY_SLEEP = 1u<<15;
|
||||
IRQ_registerIsr(IRQ_LGY_SLEEP, 14, 0, true, lgySleepIrqHandler);
|
||||
IRQ_registerIsr(IRQ_HID_PADCNT, 14, 0, true, lgySleepIrqHandler);
|
||||
IRQ_registerIsr(IRQ_LGY_SLEEP, 14, 0, lgySleepIrqHandler);
|
||||
IRQ_registerIsr(IRQ_HID_PADCNT, 14, 0, lgySleepIrqHandler);
|
||||
|
||||
return RES_OK;
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ void LGYFB_init(void)
|
|||
REG_LGYFB_TOP_ALPHA = 0xFF;
|
||||
REG_LGYFB_TOP_CNT = LGYFB_DMA_E | LGYFB_OUT_SWIZZLE | LGYFB_OUT_FMT_5551 | LGYFB_ENABLE;
|
||||
|
||||
IRQ_registerIsr(IRQ_CDMA_EVENT0, 13, 0, true, lgyFbDmaIrqHandler);
|
||||
IRQ_registerIsr(IRQ_CDMA_EVENT0, 13, 0, lgyFbDmaIrqHandler);
|
||||
}
|
||||
|
||||
void rotateFrame(void)
|
||||
|
|
|
@ -43,8 +43,8 @@ void MCU_init(void)
|
|||
|
||||
MCU_setEventMask(0xC0BF3F80);
|
||||
// Configure GPIO for MCU event IRQs
|
||||
GPIO_config(GPIO_4_MCU, GPIO_INPUT | GPIO_EDGE_FALLING | GPIO_IRQ_ENABLE);
|
||||
IRQ_registerIsr(IRQ_CTR_MCU, 14, 0, true, mcuIrqHandler);
|
||||
GPIO_config(GPIO_3_MCU, GPIO_INPUT | GPIO_EDGE_FALLING | GPIO_IRQ_ENABLE);
|
||||
IRQ_registerIsr(IRQ_CTR_MCU, 14, 0, mcuIrqHandler);
|
||||
}
|
||||
|
||||
static void mcuIrqHandler(UNUSED u32 intSource)
|
||||
|
|
|
@ -126,9 +126,9 @@ void NSPI_init(void)
|
|||
regs->NSPI_INT_MASK = NSPI_INT_TRANSF_END;
|
||||
regs->NSPI_INT_STAT = NSPI_INT_AP_TIMEOUT | NSPI_INT_AP_SUCCESS | NSPI_INT_TRANSF_END;
|
||||
|
||||
IRQ_registerIsr(IRQ_SPI2, 14, 0, true, NULL);
|
||||
IRQ_registerIsr(IRQ_SPI3, 14, 0, true, NULL);
|
||||
IRQ_registerIsr(IRQ_SPI1, 14, 0, true, NULL);
|
||||
IRQ_registerIsr(IRQ_SPI2, 14, 0, NULL);
|
||||
IRQ_registerIsr(IRQ_SPI3, 14, 0, NULL);
|
||||
IRQ_registerIsr(IRQ_SPI1, 14, 0, NULL);
|
||||
}
|
||||
|
||||
bool _NSPI_autoPollBit(SpiDevice dev, u32 params)
|
||||
|
|
|
@ -37,7 +37,7 @@ void TIMER_init(void)
|
|||
REG_TIMER_CNT = 0;
|
||||
REG_TIMER_INT_STAT = 1;
|
||||
|
||||
IRQ_registerIsr(IRQ_TIMER, 12, 0, true, NULL);
|
||||
IRQ_registerIsr(IRQ_TIMER, 12, 0, NULL);
|
||||
}
|
||||
|
||||
void TIMER_start(u8 prescaler, u32 ticks, bool autoReload, bool enableIrq)
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#define ARM7_STUB_LOC (0x3007E00u)
|
||||
#define ARM7_STUB_LOC9 (0x80BFE00u)
|
||||
#define ROM_LOC (0x20000000u)
|
||||
#define SAVE_LOC (0x08080000u)
|
||||
#define SAVE_LOC (0x8080000u)
|
||||
|
||||
|
||||
static FATFS g_sd = {0};
|
||||
|
@ -165,7 +165,7 @@ Result LGY_setGbaRtc(const GbaRtc rtc)
|
|||
REG_LGY_GBA_RTC_BCD_TIME = rtc.time;
|
||||
REG_LGY_GBA_RTC_BCD_DATE = rtc.date;
|
||||
|
||||
while(REG_LGY_GBA_RTC_CNT & LGY_RTC_CNT_BUSY);
|
||||
//while(REG_LGY_GBA_RTC_CNT & LGY_RTC_CNT_BUSY);
|
||||
//REG_LGY_GBA_RTC_CNT = 0; // Legacy P9 does this. Useless?
|
||||
REG_LGY_GBA_RTC_HEX_TIME = 1u<<15; // Time offset 0 and 24h format.
|
||||
REG_LGY_GBA_RTC_HEX_DATE = 0; // Date offset 0.
|
||||
|
@ -178,7 +178,7 @@ Result LGY_setGbaRtc(const GbaRtc rtc)
|
|||
|
||||
Result LGY_getGbaRtc(GbaRtc *const out)
|
||||
{
|
||||
while(REG_LGY_GBA_RTC_CNT & LGY_RTC_CNT_BUSY);
|
||||
//while(REG_LGY_GBA_RTC_CNT & LGY_RTC_CNT_BUSY);
|
||||
//REG_LGY_GBA_RTC_CNT = 0; // Legacy P9 does this. Useless?
|
||||
REG_LGY_GBA_RTC_CNT = LGY_RTC_CNT_RD;
|
||||
while(REG_LGY_GBA_RTC_CNT & LGY_RTC_CNT_BUSY);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "types.h"
|
||||
#include "arm9/hardware/interrupt.h"
|
||||
#include "arm9/hardware/ndma.h"
|
||||
#include "hardware/corelink_dma-330.h"
|
||||
#include "arm9/hardware/timer.h"
|
||||
#include "hardware/pxi.h"
|
||||
#include "arm9/hardware/crypto.h"
|
||||
|
@ -31,6 +32,7 @@ void WEAK __systemInit(void)
|
|||
leaveCriticalSection(0); // Enables interrupts
|
||||
TIMER_init();
|
||||
NDMA_init();
|
||||
//DMA330_init();
|
||||
//AES_init();
|
||||
//RSA_init();
|
||||
PXI_init();
|
||||
|
|
|
@ -19,141 +19,102 @@
|
|||
#include "types.h"
|
||||
#include "mem_map.h"
|
||||
#include "hardware/corelink_dma-330.h"
|
||||
//#include "arm9/hardware/cfg9.h"
|
||||
//#include "arm11/hardware/interrupt.h"
|
||||
#include "hardware/cache.h"
|
||||
//#include "arm11/fmt.h"
|
||||
|
||||
|
||||
#ifdef ARM9
|
||||
#define DMA330_REGS_BASE (IO_MEM_ARM9_ONLY + 0xC000)
|
||||
#elif ARM11
|
||||
//#define USE_NEW_CDMA 1
|
||||
|
||||
#ifdef ARM11
|
||||
#ifdef USE_NEW_CDMA
|
||||
#define DMA330_REGS_BASE (IO_MEM_ARM11_ONLY + 0x6000)
|
||||
#else
|
||||
#define DMA330_REGS_BASE (IO_MEM_ARM11_ONLY + 0x0000)
|
||||
#endif
|
||||
#define REG_DMA330_DSR *((const vu32*)(DMA330_REGS_BASE + 0x000)) // DMA Manager Status Register
|
||||
#define REG_DMA330_DPC *((const vu32*)(DMA330_REGS_BASE + 0x004)) // DMA Program Counter Register (manager)
|
||||
#define REG_DMA330_INTEN *(( vu32*)(DMA330_REGS_BASE + 0x020)) // Interrupt Enable Register
|
||||
#define REG_DMA330_INT_EVENT_RIS *((const vu32*)(DMA330_REGS_BASE + 0x024)) // Event-Interrupt Raw Status Register
|
||||
#define REG_DMA330_INTMIS *((const vu32*)(DMA330_REGS_BASE + 0x028)) // Interrupt Status Register
|
||||
#define REG_DMA330_INTCLR *(( vu32*)(DMA330_REGS_BASE + 0x02C)) // Interrupt Clear Register (write-only)
|
||||
#define REG_DMA330_FSRD *((const vu32*)(DMA330_REGS_BASE + 0x030)) // Fault Status DMA Manager Register
|
||||
#define REG_DMA330_FSRC *((const vu32*)(DMA330_REGS_BASE + 0x034)) // Fault Status DMA Channel Register
|
||||
#define REG_DMA330_FTRD *((const vu32*)(DMA330_REGS_BASE + 0x038)) // Fault Type DMA Manager Register
|
||||
#endif // ifdef USE_NEW_CDMA
|
||||
#elif ARM9
|
||||
#define DMA330_REGS_BASE (IO_MEM_ARM9_ONLY + 0xC000)
|
||||
#endif // ifdef ARM11
|
||||
#define REG_DMA330_DSR *((const vu32*)(DMA330_REGS_BASE + 0x000)) // DMA Manager Status Register.
|
||||
#define REG_DMA330_DPC *((const vu32*)(DMA330_REGS_BASE + 0x004)) // DMA Program Counter Register (manager).
|
||||
#define REG_DMA330_INTEN *(( vu32*)(DMA330_REGS_BASE + 0x020)) // Interrupt Enable Register.
|
||||
#define REG_DMA330_INT_EVENT_RIS *((const vu32*)(DMA330_REGS_BASE + 0x024)) // Event-Interrupt Raw Status Register.
|
||||
#define REG_DMA330_INTMIS *((const vu32*)(DMA330_REGS_BASE + 0x028)) // Interrupt Status Register.
|
||||
#define REG_DMA330_INTCLR *(( vu32*)(DMA330_REGS_BASE + 0x02C)) // Interrupt Clear Register (write-only).
|
||||
#define REG_DMA330_FSRD *((const vu32*)(DMA330_REGS_BASE + 0x030)) // Fault Status DMA Manager Register.
|
||||
#define REG_DMA330_FSRC *((const vu32*)(DMA330_REGS_BASE + 0x034)) // Fault Status DMA Channel Register.
|
||||
#define REG_DMA330_FTRD *((const vu32*)(DMA330_REGS_BASE + 0x038)) // Fault Type DMA Manager Register.
|
||||
|
||||
// Fault Type DMA Channel Registers
|
||||
#define REG_DMA330_FTR0 *((const vu32*)(DMA330_REGS_BASE + 0x040))
|
||||
#define REG_DMA330_FTR1 *((const vu32*)(DMA330_REGS_BASE + 0x044))
|
||||
#define REG_DMA330_FTR2 *((const vu32*)(DMA330_REGS_BASE + 0x048))
|
||||
#define REG_DMA330_FTR3 *((const vu32*)(DMA330_REGS_BASE + 0x04C))
|
||||
#define REG_DMA330_FTR4 *((const vu32*)(DMA330_REGS_BASE + 0x050))
|
||||
#define REG_DMA330_FTR5 *((const vu32*)(DMA330_REGS_BASE + 0x054))
|
||||
#define REG_DMA330_FTR6 *((const vu32*)(DMA330_REGS_BASE + 0x058))
|
||||
#define REG_DMA330_FTR7 *((const vu32*)(DMA330_REGS_BASE + 0x05C))
|
||||
// Fault Type DMA Channel 0-7 Registers.
|
||||
#define REG_DMA330_FTR(n) *((const vu32*)(DMA330_REGS_BASE + 0x040 + ((n) * 4)))
|
||||
|
||||
// Channel Status Registers
|
||||
#define REG_DMA330_CSR0 *((const vu32*)(DMA330_REGS_BASE + 0x100))
|
||||
#define REG_DMA330_CSR1 *((const vu32*)(DMA330_REGS_BASE + 0x108))
|
||||
#define REG_DMA330_CSR2 *((const vu32*)(DMA330_REGS_BASE + 0x110))
|
||||
#define REG_DMA330_CSR3 *((const vu32*)(DMA330_REGS_BASE + 0x118))
|
||||
#define REG_DMA330_CSR4 *((const vu32*)(DMA330_REGS_BASE + 0x120))
|
||||
#define REG_DMA330_CSR5 *((const vu32*)(DMA330_REGS_BASE + 0x128))
|
||||
#define REG_DMA330_CSR6 *((const vu32*)(DMA330_REGS_BASE + 0x130))
|
||||
#define REG_DMA330_CSR7 *((const vu32*)(DMA330_REGS_BASE + 0x138))
|
||||
// Channel Status 0-7 Registers.
|
||||
#define REG_DMA330_CSR(n) *((const vu32*)(DMA330_REGS_BASE + 0x100 + ((n) * 8)))
|
||||
|
||||
// Channel Program Counter Registers
|
||||
#define REG_DMA330_CPC0 *((const vu32*)(DMA330_REGS_BASE + 0x104))
|
||||
#define REG_DMA330_CPC1 *((const vu32*)(DMA330_REGS_BASE + 0x10C))
|
||||
#define REG_DMA330_CPC2 *((const vu32*)(DMA330_REGS_BASE + 0x114))
|
||||
#define REG_DMA330_CPC3 *((const vu32*)(DMA330_REGS_BASE + 0x11C))
|
||||
#define REG_DMA330_CPC4 *((const vu32*)(DMA330_REGS_BASE + 0x124))
|
||||
#define REG_DMA330_CPC5 *((const vu32*)(DMA330_REGS_BASE + 0x12C))
|
||||
#define REG_DMA330_CPC6 *((const vu32*)(DMA330_REGS_BASE + 0x134))
|
||||
#define REG_DMA330_CPC7 *((const vu32*)(DMA330_REGS_BASE + 0x13C))
|
||||
// Channel Program Counter 0-7 Registers.
|
||||
#define REG_DMA330_CPC(n) *((const vu32*)(DMA330_REGS_BASE + 0x104 + ((n) * 8)))
|
||||
|
||||
// Source Address Registers
|
||||
#define REG_DMA330_SAR0 *((const vu32*)(DMA330_REGS_BASE + 0x400))
|
||||
#define REG_DMA330_SAR1 *((const vu32*)(DMA330_REGS_BASE + 0x420))
|
||||
#define REG_DMA330_SAR2 *((const vu32*)(DMA330_REGS_BASE + 0x440))
|
||||
#define REG_DMA330_SAR3 *((const vu32*)(DMA330_REGS_BASE + 0x460))
|
||||
#define REG_DMA330_SAR4 *((const vu32*)(DMA330_REGS_BASE + 0x480))
|
||||
#define REG_DMA330_SAR5 *((const vu32*)(DMA330_REGS_BASE + 0x4A0))
|
||||
#define REG_DMA330_SAR6 *((const vu32*)(DMA330_REGS_BASE + 0x4C0))
|
||||
#define REG_DMA330_SAR7 *((const vu32*)(DMA330_REGS_BASE + 0x4E0))
|
||||
// Source Address 0-7 Registers.
|
||||
#define REG_DMA330_SAR(n) *((const vu32*)(DMA330_REGS_BASE + 0x400 + ((n) * 0x20)))
|
||||
|
||||
// Destination Address Registers
|
||||
#define REG_DMA330_DAR0 *((const vu32*)(DMA330_REGS_BASE + 0x404))
|
||||
#define REG_DMA330_DAR1 *((const vu32*)(DMA330_REGS_BASE + 0x424))
|
||||
#define REG_DMA330_DAR2 *((const vu32*)(DMA330_REGS_BASE + 0x444))
|
||||
#define REG_DMA330_DAR3 *((const vu32*)(DMA330_REGS_BASE + 0x464))
|
||||
#define REG_DMA330_DAR4 *((const vu32*)(DMA330_REGS_BASE + 0x484))
|
||||
#define REG_DMA330_DAR5 *((const vu32*)(DMA330_REGS_BASE + 0x4A4))
|
||||
#define REG_DMA330_DAR6 *((const vu32*)(DMA330_REGS_BASE + 0x4C4))
|
||||
#define REG_DMA330_DAR7 *((const vu32*)(DMA330_REGS_BASE + 0x4E4))
|
||||
// Destination Address 0-7 Registers.
|
||||
#define REG_DMA330_DAR(n) *((const vu32*)(DMA330_REGS_BASE + 0x404 + ((n) * 0x20)))
|
||||
|
||||
// Channel Control Registers
|
||||
#define REG_DMA330_CCR0 *((const vu32*)(DMA330_REGS_BASE + 0x408))
|
||||
#define REG_DMA330_CCR1 *((const vu32*)(DMA330_REGS_BASE + 0x428))
|
||||
#define REG_DMA330_CCR2 *((const vu32*)(DMA330_REGS_BASE + 0x448))
|
||||
#define REG_DMA330_CCR3 *((const vu32*)(DMA330_REGS_BASE + 0x468))
|
||||
#define REG_DMA330_CCR4 *((const vu32*)(DMA330_REGS_BASE + 0x488))
|
||||
#define REG_DMA330_CCR5 *((const vu32*)(DMA330_REGS_BASE + 0x4A8))
|
||||
#define REG_DMA330_CCR6 *((const vu32*)(DMA330_REGS_BASE + 0x4C8))
|
||||
#define REG_DMA330_CCR7 *((const vu32*)(DMA330_REGS_BASE + 0x4E8))
|
||||
// Channel Control 0-7 Registers.
|
||||
#define REG_DMA330_CCR(n) *((const vu32*)(DMA330_REGS_BASE + 0x408 + ((n) * 0x20)))
|
||||
|
||||
// Loop Counter 0 Registers
|
||||
#define REG_DMA330_LC0_0 *((const vu32*)(DMA330_REGS_BASE + 0x40C))
|
||||
#define REG_DMA330_LC0_1 *((const vu32*)(DMA330_REGS_BASE + 0x42C))
|
||||
#define REG_DMA330_LC0_2 *((const vu32*)(DMA330_REGS_BASE + 0x44C))
|
||||
#define REG_DMA330_LC0_3 *((const vu32*)(DMA330_REGS_BASE + 0x46C))
|
||||
#define REG_DMA330_LC0_4 *((const vu32*)(DMA330_REGS_BASE + 0x48C))
|
||||
#define REG_DMA330_LC0_5 *((const vu32*)(DMA330_REGS_BASE + 0x4AC))
|
||||
#define REG_DMA330_LC0_6 *((const vu32*)(DMA330_REGS_BASE + 0x4CC))
|
||||
#define REG_DMA330_LC0_7 *((const vu32*)(DMA330_REGS_BASE + 0x4EC))
|
||||
// Loop Counter 0 0-7 Registers.
|
||||
#define REG_DMA330_LC0_(n) *((const vu32*)(DMA330_REGS_BASE + 0x40C + ((n) * 0x20)))
|
||||
|
||||
// Loop Counter 1 Registers
|
||||
#define REG_DMA330_LC1_0 *((const vu32*)(DMA330_REGS_BASE + 0x410))
|
||||
#define REG_DMA330_LC1_1 *((const vu32*)(DMA330_REGS_BASE + 0x430))
|
||||
#define REG_DMA330_LC1_2 *((const vu32*)(DMA330_REGS_BASE + 0x450))
|
||||
#define REG_DMA330_LC1_3 *((const vu32*)(DMA330_REGS_BASE + 0x470))
|
||||
#define REG_DMA330_LC1_4 *((const vu32*)(DMA330_REGS_BASE + 0x490))
|
||||
#define REG_DMA330_LC1_5 *((const vu32*)(DMA330_REGS_BASE + 0x4B0))
|
||||
#define REG_DMA330_LC1_6 *((const vu32*)(DMA330_REGS_BASE + 0x4D0))
|
||||
#define REG_DMA330_LC1_7 *((const vu32*)(DMA330_REGS_BASE + 0x4F0))
|
||||
// Loop Counter 1 0-7 Registers.
|
||||
#define REG_DMA330_LC1_(n) *((const vu32*)(DMA330_REGS_BASE + 0x410 + ((n) * 0x20)))
|
||||
|
||||
#define REG_DMA330_DBGSTATUS *((const vu32*)(DMA330_REGS_BASE + 0xD00)) // Debug Status Register
|
||||
#define REG_DMA330_DBGCMD *(( vu32*)(DMA330_REGS_BASE + 0xD04)) // Debug Command Register (write-only)
|
||||
#define REG_DMA330_DBGINST0 *(( vu32*)(DMA330_REGS_BASE + 0xD08)) // Debug Instruction-0 Register (write-only)
|
||||
#define REG_DMA330_DBGINST1 *(( vu32*)(DMA330_REGS_BASE + 0xD0C)) // Debug Instruction-1 Register (write-only)
|
||||
#define REG_DMA330_DBGSTATUS *((const vu32*)(DMA330_REGS_BASE + 0xD00)) // Debug Status Register.
|
||||
#define REG_DMA330_DBGCMD *(( vu32*)(DMA330_REGS_BASE + 0xD04)) // Debug Command Register (write-only).
|
||||
#define REG_DMA330_DBGINST0 *(( vu32*)(DMA330_REGS_BASE + 0xD08)) // Debug Instruction-0 Register (write-only).
|
||||
#define REG_DMA330_DBGINST1 *(( vu32*)(DMA330_REGS_BASE + 0xD0C)) // Debug Instruction-1 Register (write-only).
|
||||
|
||||
// Configuration Registers
|
||||
// Configuration Registers.
|
||||
#define REG_DMA330_CR0 *((const vu32*)(DMA330_REGS_BASE + 0xE00))
|
||||
#define REG_DMA330_CR1 *((const vu32*)(DMA330_REGS_BASE + 0xE04))
|
||||
#define REG_DMA330_CR2 *((const vu32*)(DMA330_REGS_BASE + 0xE08))
|
||||
#define REG_DMA330_CR3 *((const vu32*)(DMA330_REGS_BASE + 0xE0C))
|
||||
#define REG_DMA330_CR4 *((const vu32*)(DMA330_REGS_BASE + 0xE10))
|
||||
#define REG_DMA330_CRD *((const vu32*)(DMA330_REGS_BASE + 0xE14)) // DMA Configuration Register
|
||||
#define REG_DMA330_CR(n) *((const vu32*)(DMA330_REGS_BASE + 0xE00 + ((n) * 4)))
|
||||
#define REG_DMA330_CRD *((const vu32*)(DMA330_REGS_BASE + 0xE14)) // DMA Configuration Register.
|
||||
|
||||
#define REG_DMA330_WD *(( vu32*)(DMA330_REGS_BASE + 0xE80)) // Watchdog Register
|
||||
// Watchdog Register (r1p0 only).
|
||||
#define REG_DMA330_WD *(( vu32*)(DMA330_REGS_BASE + 0xE80))
|
||||
|
||||
// Periphal and component identification registers.
|
||||
#define REG_DMA330_PERIPH_ID_0 *((const vu32*)(DMA330_REGS_BASE + 0xFE0))
|
||||
#define REG_DMA330_PERIPH_ID_1 *((const vu32*)(DMA330_REGS_BASE + 0xFE4))
|
||||
#define REG_DMA330_PERIPH_ID_2 *((const vu32*)(DMA330_REGS_BASE + 0xFE8))
|
||||
#define REG_DMA330_PERIPH_ID_3 *((const vu32*)(DMA330_REGS_BASE + 0xFEC))
|
||||
#define REG_DMA330_PCELL_ID_0 *((const vu32*)(DMA330_REGS_BASE + 0xFF0))
|
||||
#define REG_DMA330_PCELL_ID_1 *((const vu32*)(DMA330_REGS_BASE + 0xFF4))
|
||||
#define REG_DMA330_PCELL_ID_2 *((const vu32*)(DMA330_REGS_BASE + 0xFF8))
|
||||
#define REG_DMA330_PCELL_ID_3 *((const vu32*)(DMA330_REGS_BASE + 0xFFC))
|
||||
|
||||
|
||||
//#define CHANNELS (8u)
|
||||
//#define PERIPHALS (18u)
|
||||
//#define IRQ_LINES (16u)
|
||||
#ifdef ARM11
|
||||
#ifdef USE_NEW_CDMA
|
||||
#error "TODO: New3DS CDMA"
|
||||
#else
|
||||
#define CHANNELS (8u)
|
||||
#define PERIPHALS (18u)
|
||||
#define IRQ_LINES (9u) // The controller reports 16 but we only have 9 physical lines.
|
||||
#endif // ifdef USE_NEW_CDMA
|
||||
#elif ARM9
|
||||
#define CHANNELS (4u)
|
||||
#define PERIPHALS (8u)
|
||||
#define IRQ_LINES (12u)
|
||||
#endif // ifdef ARM11
|
||||
|
||||
#define INTEN_VAL ((1u<<IRQ_LINES) - 1) // Not 32 bit safe!
|
||||
|
||||
|
||||
|
||||
static inline void waitForChannelStatus(u8 ch, u8 status)
|
||||
{
|
||||
while((REG_DMA330_CSR(ch) & CSR_STATUS_MASK) != status);
|
||||
while((REG_DMA330_CSR(ch) & CSR_STAT_MASK) != status);
|
||||
}
|
||||
|
||||
static inline void waitDebugBusy(void)
|
||||
|
@ -175,76 +136,86 @@ void DMA330_init(void)
|
|||
if(inited) return;
|
||||
inited = true;
|
||||
|
||||
const u32 cr0 = REG_DMA330_CR0;
|
||||
const u8 numChannels = (cr0>>4 & 7u) + 1;
|
||||
const u8 numPeriphals = (cr0 & 1u ? (cr0>>12 & 0x1Fu) + 1 : 0);
|
||||
//const u8 numIrqs = (cr0>>17 & 0x1Fu) + 1;
|
||||
// Kill manager thread.
|
||||
sendDebugCmd(DBGINST0(0x01u, 0, DBGINST0_THR_MGR), 0);
|
||||
|
||||
// Kill manager thread
|
||||
sendDebugCmd(DBGINST0_BYTES01(0x01u) | DBGINST0_THREAD_MGR, 0);
|
||||
|
||||
// Kill all channels
|
||||
for(u32 i = 0; i < numChannels; i++)
|
||||
// Kill all channels.
|
||||
for(u32 i = 0; i < CHANNELS; i++)
|
||||
{
|
||||
// DMAKILL channel
|
||||
sendDebugCmd(DBGINST0_BYTES01(0x01u) | DBGINST0_CH_NUM(i) | DBGINST0_THREAD_CH, 0);
|
||||
// DMAKILL channel.
|
||||
sendDebugCmd(DBGINST0(0x01u, i, DBGINST0_THR_CH), 0);
|
||||
}
|
||||
waitForChannelStatus(numChannels - 1, CSR_STATUS_STOPPED);
|
||||
waitForChannelStatus(CHANNELS - 1, CSR_STAT_STOPPED);
|
||||
|
||||
// TODO: Hardcode number of IRQs or configurable?
|
||||
REG_DMA330_INTEN = 0x1FF; // First 9 are interrupts and remaining events
|
||||
REG_DMA330_INTCLR = 0xFFFFFFFF; // Clear all interrupts
|
||||
REG_DMA330_WD = 0; // Watchdog aborts hanging channels
|
||||
REG_DMA330_INTEN = INTEN_VAL;
|
||||
REG_DMA330_INTCLR = 0xFFFFFFFF; // Clear all interrupts.
|
||||
REG_DMA330_WD = 0; // Watchdog aborts hanging channels.
|
||||
|
||||
if(numPeriphals)
|
||||
if(PERIPHALS > 0)
|
||||
{
|
||||
u8 progBuf[3] = {0x35, 0, 0}; // DMAFLUSHP 0, DMAEND
|
||||
for(u32 i = 0; i < numPeriphals; i++)
|
||||
#ifdef ARM11
|
||||
u16 progBuf[33]; // Max 32 periphals + 1 for DMAEND.
|
||||
#elif ARM9
|
||||
u16 *progBuf = (u16*)(A9_RAM_BASE + A9_RAM_SIZE - 33 * 2); // ARM9 DTCM stack workaround.
|
||||
#endif // ifdef ARM11
|
||||
for(u32 i = 0; i < PERIPHALS; i++)
|
||||
{
|
||||
waitForChannelStatus(0, CSR_STATUS_STOPPED);
|
||||
|
||||
progBuf[1] = i<<3; // Periphal ID
|
||||
cleanDCacheRange(progBuf, 3);
|
||||
// DMAGO channel 0 non-secure
|
||||
sendDebugCmd(DBGINST0_BYTES01(0x00A2u) | DBGINST0_THREAD_MGR, (u32)progBuf);
|
||||
// DMAFLUSHP i.
|
||||
progBuf[i] = i<<11 | 0x35u;
|
||||
}
|
||||
progBuf[PERIPHALS] = 0; // DMAEND.
|
||||
cleanDCacheRange(progBuf, 33 * 2);
|
||||
// DMAGO channel 0 non-secure.
|
||||
sendDebugCmd(DBGINST0(0u<<8 | 0xA2u, 0, DBGINST0_THR_MGR), (u32)progBuf);
|
||||
waitForChannelStatus(0, CSR_STAT_STOPPED); // Wait for IRQ instead?
|
||||
}
|
||||
|
||||
/*ee_printf("DSR%lX FTRD%lX", REG_DMA330_DSR, REG_DMA330_FTRD);
|
||||
for(u32 i = 0; i < 8; i++)
|
||||
{
|
||||
ee_printf(" CSR%lX FTR%lX", REG_DMA330_CSR(i), REG_DMA330_FTR(i));
|
||||
}
|
||||
ee_printf("\n");*/
|
||||
}
|
||||
|
||||
u8 DMA330_run(u8 ch, const u8 *const prog)
|
||||
{
|
||||
u8 status;
|
||||
if((status = (REG_DMA330_CSR(ch) & CSR_STATUS_MASK)) != CSR_STATUS_STOPPED)
|
||||
if((status = (REG_DMA330_CSR(ch) & CSR_STAT_MASK)) != CSR_STAT_STOPPED)
|
||||
return status;
|
||||
|
||||
// DMAGO non-secure
|
||||
sendDebugCmd(DBGINST0_BYTES01(ch<<8 | 0xA2u) | DBGINST0_THREAD_MGR, (u32)prog);
|
||||
// DMAGO non-secure.
|
||||
sendDebugCmd(DBGINST0(ch<<8 | 0xA2u, 0, DBGINST0_THR_MGR), (u32)prog);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
u8 DMA330_status(u8 ch)
|
||||
{
|
||||
return REG_DMA330_CSR(ch) & CSR_STATUS_MASK;
|
||||
return REG_DMA330_CSR(ch) & CSR_STAT_MASK;
|
||||
}
|
||||
|
||||
void DMA330_ackIrq(u8 eventIrq)
|
||||
{
|
||||
REG_DMA330_INTCLR = 1u<<eventIrq;
|
||||
REG_DMA330_INTCLR = INTCLR_IRQ_CLR(eventIrq);
|
||||
}
|
||||
|
||||
void DMA330_sev(u8 event)
|
||||
{
|
||||
// DMASEV.
|
||||
sendDebugCmd(DBGINST0(event<<11 | 0x34u, 0, DBGINST0_THR_MGR), 0);
|
||||
}
|
||||
|
||||
void DMA330_kill(u8 ch)
|
||||
{
|
||||
if((REG_DMA330_CSR(ch) & CSR_STATUS_MASK) != CSR_STATUS_STOPPED)
|
||||
if((REG_DMA330_CSR(ch) & CSR_STAT_MASK) != CSR_STAT_STOPPED)
|
||||
{
|
||||
sendDebugCmd(DBGINST0_BYTES01(0x01u) | DBGINST0_CH_NUM(ch) | DBGINST0_THREAD_CH, 0);
|
||||
waitForChannelStatus(ch, CSR_STATUS_STOPPED);
|
||||
sendDebugCmd(DBGINST0(0x01u, ch, DBGINST0_THR_CH), 0);
|
||||
waitForChannelStatus(ch, CSR_STAT_STOPPED);
|
||||
}
|
||||
}
|
||||
|
||||
/*#ifdef ARM11
|
||||
#include "arm11/fmt.h"
|
||||
void DMA330_dbgPrint(void)
|
||||
{
|
||||
ee_printf("DSR: %08lX FTRD: %08lX\n", REG_DMA330_DSR, REG_DMA330_FTRD);
|
||||
for(u32 i = 0; i < CHANNELS; i++)
|
||||
{
|
||||
ee_printf(" CSR/FTR%lu: %08lX %08lX\n", i, REG_DMA330_CSR(i), REG_DMA330_FTR(i));
|
||||
}
|
||||
}
|
||||
#endif*/ // ifdef ARM11
|
||||
|
|
|
@ -72,7 +72,7 @@ void PXI_init(void)
|
|||
while(pxiRecvWord() != 0x99);
|
||||
pxiSendWord(0x11);
|
||||
|
||||
IRQ_registerIsr(IRQ_PXI_SYNC, 13, 0, true, pxiIrqHandler);
|
||||
IRQ_registerIsr(IRQ_PXI_SYNC, 13, 0, pxiIrqHandler);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue