From cdeec87351d34f455a9735780c89009b1208ada6 Mon Sep 17 00:00:00 2001 From: profi200 Date: Sat, 6 Jun 2020 00:25:10 +0200 Subject: [PATCH] Lots of small changes related to recent findings. Some cleanup. --- include/arm11/hardware/gpio.h | 61 ++++--- include/arm11/hardware/interrupt.h | 215 ++++++++++++---------- include/hardware/corelink_dma-330.h | 102 ++++++----- include/mmio.h | 2 + source/arm11/hardware/codec.c | 17 +- source/arm11/hardware/cpu.c | 26 +-- source/arm11/hardware/exception.s | 4 +- source/arm11/hardware/gfx.c | 12 +- source/arm11/hardware/gpio.c | 105 +++++------ source/arm11/hardware/i2c.c | 6 +- source/arm11/hardware/interrupt.c | 272 ++++++++++++++++++---------- source/arm11/hardware/lgy.c | 4 +- source/arm11/hardware/lgyfb.c | 2 +- source/arm11/hardware/mcu.c | 4 +- source/arm11/hardware/spi.c | 6 +- source/arm11/hardware/timer.c | 2 +- source/arm9/hardware/lgy.c | 6 +- source/arm9/system.c | 2 + source/hardware/corelink_dma-330.c | 251 ++++++++++++------------- source/hardware/pxi.c | 2 +- 20 files changed, 593 insertions(+), 508 deletions(-) diff --git a/include/arm11/hardware/gpio.h b/include/arm11/hardware/gpio.h index ac82eae..29bf757 100644 --- a/include/arm11/hardware/gpio.h +++ b/include/arm11/hardware/gpio.h @@ -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); diff --git a/include/arm11/hardware/interrupt.h b/include/arm11/hardware/interrupt.h index a5b7c25..99f5863 100644 --- a/include/arm11/hardware/interrupt.h +++ b/include/arm11/hardware/interrupt.h @@ -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__ diff --git a/include/hardware/corelink_dma-330.h b/include/hardware/corelink_dma-330.h index b8a76d0..864b80b 100644 --- a/include/hardware/corelink_dma-330.h +++ b/include/hardware/corelink_dma-330.h @@ -22,84 +22,84 @@ // REG_DMA330_DSR -#define DSR_WAKEUP_EVNT_SHIFT (4u) -#define DSR_WAKEUP_EVNT_MASK (0x1Fu<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. } diff --git a/source/arm11/hardware/cpu.c b/source/arm11/hardware/cpu.c index 61c4c3b..b343c5b 100644 --- a/source/arm11/hardware/cpu.c +++ b/source/arm11/hardware/cpu.c @@ -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 } diff --git a/source/arm11/hardware/exception.s b/source/arm11/hardware/exception.s index 12480f8..1f66b90 100644 --- a/source/arm11/hardware/exception.s +++ b/source/arm11/hardware/exception.s @@ -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 diff --git a/source/arm11/hardware/gfx.c b/source/arm11/hardware/gfx.c index 268d51a..94e96a4 100644 --- a/source/arm11/hardware/gfx.c +++ b/source/arm11/hardware/gfx.c @@ -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, diff --git a/source/arm11/hardware/gpio.c b/source/arm11/hardware/gpio.c index dae8e6c..fbeeb01 100644 --- a/source/arm11/hardware/gpio.c +++ b/source/arm11/hardware/gpio.c @@ -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)<>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<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) diff --git a/source/arm11/hardware/interrupt.c b/source/arm11/hardware/interrupt.c index 564aed0..f7969d6 100644 --- a/source/arm11/hardware/interrupt.c +++ b/source/arm11/hardware/interrupt.c @@ -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<>2] & ~(0xFu<>2] = tmp | (u32)prio<>2] & ~(0xFu<>2] = tmp | (u32)cpuMask<>4] & ~(1u<>4] = tmp | (u32)edgeTriggered<>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<>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<>2] = tmp | (u32)prio<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) diff --git a/source/arm11/hardware/timer.c b/source/arm11/hardware/timer.c index 9ef0a41..9236df5 100644 --- a/source/arm11/hardware/timer.c +++ b/source/arm11/hardware/timer.c @@ -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) diff --git a/source/arm9/hardware/lgy.c b/source/arm9/hardware/lgy.c index da3b173..c0797a2 100644 --- a/source/arm9/hardware/lgy.c +++ b/source/arm9/hardware/lgy.c @@ -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); diff --git a/source/arm9/system.c b/source/arm9/system.c index 0f53fd9..fd79b65 100644 --- a/source/arm9/system.c +++ b/source/arm9/system.c @@ -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(); diff --git a/source/hardware/corelink_dma-330.c b/source/hardware/corelink_dma-330.c index 92ea9cf..f3c1005 100644 --- a/source/hardware/corelink_dma-330.c +++ b/source/hardware/corelink_dma-330.c @@ -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<>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<