Enable the FCRAM extension on N3DS

... this means a larger RAM drive on N3DS
This commit is contained in:
Wolfvak 2018-03-14 23:18:29 +01:00 committed by d0k3
parent 7a85615a42
commit 07e419f514
5 changed files with 99 additions and 72 deletions

View File

@ -2,54 +2,50 @@
#include <cpu.h>
#include <gic.h>
#include <string.h>
#define IRQVECTOR_BASE ((vu32*)0x1FFFFFA0)
irq_handler handler_table[MAX_IRQ];
extern void (*main_irq_handler)(void);
irq_handler GIC_AckIRQ(void)
{
u32 xrq = *GIC_IRQACK;
irq_handler ret = NULL;
if (xrq < MAX_IRQ && handler_table[xrq]) {
ret = handler_table[xrq];
}
*GIC_IRQEND = xrq;
return ret;
}
void GIC_SetIRQ(u32 irq_id, irq_handler hndl)
{
handler_table[irq_id] = hndl;
DIC_CLRENABLE[irq_id/32] |= BIT(irq_id & 0x1F);
DIC_SETENABLE[irq_id/32] |= BIT(irq_id & 0x1F);
DIC_PROCTGT[irq_id] = 1;
return;
}
irq_handler GIC_Handlers[128];
void GIC_Reset(void)
{
*GIC_CONTROL = 1;
*DIC_CONTROL = 1;
u32 irq_s;
*GIC_PRIOMASK = ~0;
for (int i = 0; i < MAX_IRQ; i++) {
handler_table[i] = NULL;
*GIC_IRQEND = i;
}
REG_GIC_CONTROL = 0;
memset(GIC_Handlers, 0, sizeof(GIC_Handlers));
for (int i = 0; i < (0x08); i++) {
DIC_CLRENABLE[i] = ~0;
DIC_PRIORITY[i] = 0;
REG_DIC_CONTROL = 0;
for (int i = 0; i < 4; i++) {
REG_DIC_CLRENABLE[i] = ~0;
REG_DIC_CLRPENDING[i] = ~0;
}
for (int i = 0; i < 32; i++) REG_DIC_PRIORITY[i] = 0;
for (int i = 32; i < 128; i++) REG_DIC_TARGETPROC[i] = 0;
for (int i = 0; i < 8; i++) REG_DIC_CFGREG[i] = ~0;
REG_DIC_CONTROL = 1;
while(*GIC_PENDING != SPURIOUS_IRQ) {
for (int i=0; i < (0x08); i++) {
DIC_CLRPENDING[i] = ~0;
}
}
REG_DIC_CLRENABLE[0] = ~0;
for (int i = 0; i < 32; i++) REG_DIC_PRIORITY[i] = 0;
for (int i = 0; i < 2; i++) REG_DIC_CFGREG[i] = ~0;
REG_GIC_POI = 3;
REG_GIC_PRIOMASK = 0xF << 4;
REG_GIC_CONTROL = 1;
do {
irq_s = REG_GIC_PENDING;
REG_GIC_IRQEND = irq_s;
} while(irq_s != 1023);
IRQVECTOR_BASE[1] = (u32)&main_irq_handler;
IRQVECTOR_BASE[0] = 0xE51FF004;
return;
}
void GIC_SetIRQ(u32 irq, irq_handler handler)
{
GIC_Handlers[irq] = handler;
REG_DIC_CLRPENDING[irq >> 5] |= BIT(irq & 0x1F);
REG_DIC_SETENABLE[irq >> 5] |= BIT(irq & 0x1F);
REG_DIC_TARGETPROC[irq] = 1;
}

View File

@ -3,27 +3,25 @@
typedef void (*irq_handler)(void);
#define MAX_IRQ (0x80)
#define REG_GIC_BASE (0x17E00100) // MPCore PMR
#define REG_DIC_BASE (0x17E01000)
#define SPURIOUS_IRQ (1023)
#define REG_GIC_CONTROL (*(vu32*)(REG_GIC_BASE + 0x00))
#define REG_GIC_PRIOMASK (*(vu32*)(REG_GIC_BASE + 0x04))
#define REG_GIC_POI (*(vu32*)(REG_GIC_BASE + 0x08))
#define REG_GIC_IRQACK (*(vu32*)(REG_GIC_BASE + 0x0C))
#define REG_GIC_IRQEND (*(vu32*)(REG_GIC_BASE + 0x10))
#define REG_GIC_LASTPRIO (*(vu32*)(REG_GIC_BASE + 0x14))
#define REG_GIC_PENDING (*(vu32*)(REG_GIC_BASE + 0x18))
#define GIC_BASE (0x17E00100)
#define DIC_BASE (0x17E01000)
#define GIC_CONTROL ((vu32*)(GIC_BASE + 0x00))
#define GIC_PRIOMASK ((vu32*)(GIC_BASE + 0x04))
#define GIC_IRQACK ((vu32*)(GIC_BASE + 0x0C))
#define GIC_IRQEND ((vu32*)(GIC_BASE + 0x10))
#define GIC_PENDING ((vu32*)(GIC_BASE + 0x18))
#define DIC_CONTROL ((vu32*)(DIC_BASE + 0x000))
#define DIC_SETENABLE ((vu32*)(DIC_BASE + 0x100))
#define DIC_CLRENABLE ((vu32*)(DIC_BASE + 0x180))
#define DIC_SETPENDING ((vu32*)(DIC_BASE + 0x200))
#define DIC_CLRPENDING ((vu32*)(DIC_BASE + 0x280))
#define DIC_PRIORITY ((vu32*)(DIC_BASE + 0x400))
#define DIC_PROCTGT ((vu8*) (DIC_BASE + 0x800))
#define DIC_CFGREG ((vu32*)(DIC_BASE + 0xC00))
#define REG_DIC_CONTROL (*(vu32*)(REG_DIC_BASE + 0x00))
#define REG_DIC_SETENABLE ((vu32*)(REG_DIC_BASE + 0x100))
#define REG_DIC_CLRENABLE ((vu32*)(REG_DIC_BASE + 0x180))
#define REG_DIC_SETPENDING ((vu32*)(REG_DIC_BASE + 0x200))
#define REG_DIC_CLRPENDING ((vu32*)(REG_DIC_BASE + 0x280))
#define REG_DIC_PRIORITY ((vu32*)(REG_DIC_BASE + 0x400))
#define REG_DIC_TARGETPROC ((vu8*) (REG_DIC_BASE + 0x800))
#define REG_DIC_CFGREG ((vu32*)(REG_DIC_BASE + 0xC00))
void GIC_SetIRQ(u32 irq_id, irq_handler hndl);
void GIC_Reset(void);

View File

@ -3,25 +3,44 @@
#include <arm.h>
#define MPCORE_PMR (0x17E00000)
#define IRQ_SPURIOUS (1023)
#define IRQ_COUNT (128)
.global main_irq_handler
.type main_irq_handler, %function
main_irq_handler:
sub lr, lr, #4 @ Fix return address
srsdb sp!, #(SR_SVC_MODE) @ Store IRQ mode LR and SPSR on the SVC stack
cpsid i, #(SR_SVC_MODE) @ Switch to SVC mode
push {r0-r3,r12} @ Preserve registers
and r1, sp, #4
sub sp, sp, r1 @ Word-align stack
push {r1,lr}
srsfd sp!, #0x13 @ Store IRQ mode LR and SPSR on the SVC stack
cps #0x13 @ Switch to SVC mode
push {r0-r3, r12, lr} @ Preserve registers
bl GIC_AckIRQ @ Acknowledge interrupt, get handler address
cmp r0, #0
beq .Lskip_irq
1:
ldr lr, =MPCORE_PMR
ldr r0, [lr, #0x10C] @ Get pending interrupt
blx r0 @ Branch to interrupt handler
ldr r1, =IRQ_SPURIOUS
cmp r0, r1
beq 3f @ Spurious interrupt, no interrupts pending
.Lskip_irq:
pop {r1,lr}
add sp, sp, r1 @ Restore stack pointer
pop {r0-r3,r12} @ Restore registers
cmp r0, #IRQ_COUNT
bhs 2f @ Invalid interrupt ID
ldr r12, =GIC_Handlers
ldr r12, [r12, r0, lsl #2]
cmp r12, #0
beq 2f
push {r0, r12}
blx r12
pop {r0, r12}
2:
ldr lr, =MPCORE_PMR
str r0, [lr, #0x110] @ End of interrupt
b 1b @ Check for any other pending interrupts
3:
pop {r0-r3, r12, lr} @ Restore registers
rfeia sp! @ Return From Exception

View File

@ -59,11 +59,25 @@ void PXI_IRQHandler(void)
return;
}
vu16 *CFG11_MPCORE_CLKCNT = (vu16*)(0x10141300);
vu16 *CFG11_SOCINFO = (vu16*)(0x10140FFC);
void main(void)
{
u32 entry;
PXI_Reset();
if ((*CFG11_SOCINFO & 2) && (!(*CFG11_MPCORE_CLKCNT & 1))) {
GIC_Reset();
GIC_SetIRQ(88, NULL);
CPU_EnableIRQ();
*CFG11_MPCORE_CLKCNT = 0x8001;
do {
asm("wfi\n\t");
} while(!(*CFG11_MPCORE_CLKCNT & 0x8000));
CPU_DisableIRQ();
}
PXI_Reset();
GIC_Reset();
GIC_SetIRQ(IRQ_PXI_SYNC, PXI_IRQHandler);
PXI_EnableIRQ();

View File

@ -28,5 +28,5 @@ u64 GetRamDriveSize(void) {
void InitRamDrive(void) {
ramdrv_buffer = (u8*) __RAMDRV_ADDR;
ramdrv_size = ((IS_O3DS || IS_SIGHAX) ? __RAMDRV_END : __RAMDRV_END_N) - __RAMDRV_ADDR;
ramdrv_size = (IS_O3DS ? __RAMDRV_END : __RAMDRV_END_N) - __RAMDRV_ADDR;
}