From 2f8668638862067e50241a04a55b141554669e84 Mon Sep 17 00:00:00 2001 From: Wolfvak Date: Thu, 11 Apr 2019 18:16:20 -0300 Subject: [PATCH] renamed most low level functions and other stuff to fit with the current theme - added initial SCU twiddling - added very untested and unusable SMP code - fixed race condition that happened on boot - added initial MMU code (just super basic identity mapping, no caching set up or anything) - enabled some of the fancier ARMv6 features - reorganized ARM11 files into their own folders - possibly more stuff I'm forgetting about --- arm11/link.ld | 4 +- arm11/source/arm/gic.c | 204 +++++++++++++++++++++++++++++++ arm11/source/arm/gic.h | 26 ++++ arm11/source/arm/mmu.c | 28 +++++ arm11/source/arm/mmu.h | 6 + arm11/source/arm/scu.c | 14 +++ arm11/source/arm/scu.h | 5 + arm11/source/arm/vectors.s | 26 ++++ arm11/source/boot.s | 48 ++++++-- arm11/source/gic.c | 49 -------- arm11/source/gic.h | 27 ---- arm11/source/gpulcd.c | 184 ---------------------------- arm11/source/gpulcd.h | 47 ------- arm11/source/hw/gpulcd.c | 203 ++++++++++++++++++++++++++++++ arm11/source/hw/gpulcd.h | 16 +++ arm11/source/{ => hw}/i2c.c | 5 +- arm11/source/{ => hw}/i2c.h | 2 +- arm11/source/{ => hw}/mcu.c | 0 arm11/source/{ => hw}/mcu.h | 0 arm11/source/irq.s | 46 ------- arm11/source/main.c | 75 ++++++------ arm11/source/sys.c | 68 +++++++++++ arm9/source/common/power.c | 8 +- arm9/source/godmode.c | 2 +- arm9/source/main.c | 4 + arm9/source/start.s | 4 +- arm9/source/system/i2c.c | 10 +- arm9/source/system/xrq_handler.s | 2 +- common/arm.h | 95 ++++++++------ common/pxi.h | 44 +++++-- common/types.h | 1 + 31 files changed, 784 insertions(+), 469 deletions(-) create mode 100644 arm11/source/arm/gic.c create mode 100644 arm11/source/arm/gic.h create mode 100755 arm11/source/arm/mmu.c create mode 100755 arm11/source/arm/mmu.h create mode 100755 arm11/source/arm/scu.c create mode 100755 arm11/source/arm/scu.h create mode 100644 arm11/source/arm/vectors.s delete mode 100644 arm11/source/gic.c delete mode 100644 arm11/source/gic.h delete mode 100644 arm11/source/gpulcd.c delete mode 100644 arm11/source/gpulcd.h create mode 100644 arm11/source/hw/gpulcd.c create mode 100644 arm11/source/hw/gpulcd.h rename arm11/source/{ => hw}/i2c.c (99%) rename arm11/source/{ => hw}/i2c.h (99%) rename arm11/source/{ => hw}/mcu.c (100%) rename arm11/source/{ => hw}/mcu.h (100%) delete mode 100644 arm11/source/irq.s create mode 100755 arm11/source/sys.c diff --git a/arm11/link.ld b/arm11/link.ld index 88f4af8..838d20e 100644 --- a/arm11/link.ld +++ b/arm11/link.ld @@ -8,8 +8,8 @@ SECTIONS .text : ALIGN(4) { *(.text.boot) *(.text*); . = ALIGN(4); } .rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); } - .data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); } - .bss : ALIGN(4) { __bss_start = .; *(.bss*); __bss_end = .; } + .data : ALIGN(4) { *(.data*); . = ALIGN(8); } + .bss : ALIGN(4) { __bss_start = .; *(.bss* COMMON); __bss_end = .; } . = ALIGN(4); } diff --git a/arm11/source/arm/gic.c b/arm11/source/arm/gic.c new file mode 100644 index 0000000..018319b --- /dev/null +++ b/arm11/source/arm/gic.c @@ -0,0 +1,204 @@ +#include +#include + +#include "arm/gic.h" + +/* Generic Interrupt Controller Registers */ +#define REG_GIC(cpu, o, t) REG_ARM_PMR(0x200 + ((cpu) * 0x100) + (o), t) + +#define REG_GIC_CONTROL(c) (*REG_GIC(c, 0x00, u32)) +#define REG_GIC_PRIOMASK(c) (*REG_GIC(c, 0x04, u32)) +#define REG_GIC_POI(c) (*REG_GIC(c, 0x08, u32)) +#define REG_GIC_IRQACK(c) (*REG_GIC(c, 0x0C, u32)) +#define REG_GIC_IRQEND(c) (*REG_GIC(c, 0x10, u32)) +#define REG_GIC_LASTPRIO(c) (*REG_GIC(c, 0x14, u32)) +#define REG_GIC_PENDING(c) (*REG_GIC(c, 0x18, u32)) + +#define GIC_THIS_CPU_ALIAS (-1) +#define GIC_IRQ_SPURIOUS (1023) + +/* Interrupt Distributor Registers */ +#define REG_DIC(off, type) REG_ARM_PMR(0x1000 + (off), type) + +#define REG_DIC_CONTROL (*REG_DIC(0x00, u32)) +#define REG_DIC_TYPE (*REG_DIC(0x04, u32)) +#define REG_DIC_SETENABLE REG_DIC(0x100, u32) +#define REG_DIC_CLRENABLE REG_DIC(0x180, u32) +#define REG_DIC_SETPENDING REG_DIC(0x200, u32) +#define REG_DIC_CLRPENDING REG_DIC(0x280, u32) +#define REG_DIC_PRIORITY REG_DIC(0x400, u8) +#define REG_DIC_TARGETPROC REG_DIC(0x800, u8) +#define REG_DIC_CFGREG REG_DIC(0xC00, u32) +#define REG_DIC_SOFTINT (*REG_DIC(0xF00, u32)) + +/* Interrupt Handling */ +#define LOCAL_IRQS (32) +#define DIC_MAX_IRQ (LOCAL_IRQS + MAX_IRQ) + +#define IRQN_IS_LOCAL(n) ((n) < LOCAL_IRQS) +#define IRQN_IS_VALID(n) ((n) < DIC_MAX_IRQ) + +#define LOCAL_IRQ_OFF(c, n) (((c) * LOCAL_IRQS) + (n)) +#define GLOBAL_IRQ_OFF(n) (((MAX_CPU-1) * LOCAL_IRQS) + (n)) +#define IRQ_TABLE_OFF(c, n) \ + (IRQN_IS_LOCAL((n)) ? LOCAL_IRQ_OFF((c), (n)) : GLOBAL_IRQ_OFF((n))) + +static IRQ_Handler IRQ_Handlers[IRQ_TABLE_OFF(0, MAX_IRQ)]; + +static IRQ_Handler GIC_GetCB(u32 irqn) +{ + irqn &= ~(15 << 10); // clear source CPU bits + if (IRQN_IS_VALID(irqn)) { + return IRQ_Handlers[IRQ_TABLE_OFF(ARM_CoreID(), irqn)]; + } else { + // Possibly have a dummy handler function that + // somehow notifies of an unhandled interrupt? + return NULL; + } +} + +static void GIC_SetCB(u32 irqn, u32 cpu, IRQ_Handler handler) +{ + if (IRQN_IS_VALID(irqn)) { + IRQ_Handlers[IRQ_TABLE_OFF(cpu, irqn)] = handler; + } +} + +static void GIC_ClearCB(u32 irqn, u32 cpu) +{ + GIC_SetCB(irqn, cpu, NULL); +} + +void GIC_MainHandler(void) +{ + while(1) { + IRQ_Handler handler; + u32 irqn = REG_GIC_IRQACK(GIC_THIS_CPU_ALIAS); + if (irqn == GIC_IRQ_SPURIOUS) + break; + + handler = GIC_GetCB(irqn); + if (handler != NULL) + handler(irqn); + + REG_GIC_IRQEND(GIC_THIS_CPU_ALIAS) = irqn; + } +} + +void GIC_GlobalReset(void) +{ + int gicn, intn; + + // Number of local controllers + gicn = ((REG_DIC_TYPE >> 5) & 3) + 1; + + // Number of interrupt lines (up to 224 external + 32 fixed internal) + intn = ((REG_DIC_TYPE & 7) + 1) << 5; + + if (gicn > MAX_CPU) + gicn = MAX_CPU; + + // Clear the interrupt table + for (unsigned int i = 0; i < sizeof(IRQ_Handlers)/sizeof(*IRQ_Handlers); i++) + IRQ_Handlers[i] = NULL; + + // Disable all MP11 GICs + for (int i = 0; i < gicn; i++) + REG_GIC_CONTROL(i) = 0; + + // Disable the main DIC + REG_DIC_CONTROL = 0; + + // Clear all DIC interrupts + for (int i = 1; i < (intn / 32); i++) { + REG_DIC_CLRENABLE[i] = ~0; + REG_DIC_CLRPENDING[i] = ~0; + } + + // Reset all DIC priorities to lowest and clear target processor regs + for (int i = 32; i < intn; i++) { + REG_DIC_PRIORITY[i] = 0xF0; + REG_DIC_TARGETPROC[i] = 0; + } + + // Set all interrupts to rising edge triggered and 1-N model + for (int i = 2; i < (intn / 16); i++) + REG_DIC_CFGREG[i] = ~0; + + // Enable the main DIC + REG_DIC_CONTROL = 1; + + for (int i = 0; i < gicn; i++) { + // Compare all priority bits + REG_GIC_POI(i) = 3; + + // Don't mask any interrupt with low priority + REG_GIC_PRIOMASK(i) = 0xF0; + + // Enable the MP11 GIC + REG_GIC_CONTROL(i) = 1; + } +} + +void GIC_LocalReset(void) +{ + u32 irq_s; + + // Clear out local interrupt configuration bits + REG_DIC_CLRENABLE[0] = ~0; + REG_DIC_CLRPENDING[0] = ~0; + + for (int i = 0; i < 32; i++) { + REG_DIC_PRIORITY[i] = 0xF0; + REG_DIC_TARGETPROC[i] = 0; + } + + for (int i = 0; i < 2; i++) + REG_DIC_CFGREG[i] = ~0; + + // Wait for the spurious IRQ + do { + irq_s = REG_GIC_PENDING(GIC_THIS_CPU_ALIAS); + REG_GIC_IRQEND(GIC_THIS_CPU_ALIAS) = irq_s; + } while(irq_s != GIC_IRQ_SPURIOUS); +} + +int GIC_Enable(u32 irqn, u32 coremask, u32 prio, IRQ_Handler handler) +{ + if (!IRQN_IS_VALID(irqn)) + return -1; + + // in theory this should be replaced by a faster CLZ lookup + // in practice, meh, MAX_CPU will only be 2 anyway... + for (int i = 0; i < MAX_CPU; i++) { + if (coremask & BIT(i)) + GIC_SetCB(irqn, i, handler); + } + + REG_DIC_CLRPENDING[irqn >> 5] |= BIT(irqn & 0x1F); + REG_DIC_SETENABLE[irqn >> 5] |= BIT(irqn & 0x1F); + REG_DIC_PRIORITY[irqn] = prio << 4; + REG_DIC_TARGETPROC[irqn] = coremask; + return 0; +} + +int GIC_Disable(u32 irqn, u32 coremask) +{ + if (irqn >= MAX_IRQ) + return -1; + + for (int i = 0; i < MAX_CPU; i++) { + if (coremask & BIT(i)) + GIC_ClearCB(irqn, i); + } + + REG_DIC_CLRPENDING[irqn >> 5] |= BIT(irqn & 0x1F); + REG_DIC_CLRENABLE[irqn >> 5] |= BIT(irqn & 0x1F); + REG_DIC_TARGETPROC[irqn] = 0; + return 0; +} + +void GIC_TriggerSoftIRQ(u32 irqn, u32 mode, u32 coremask) +{ + REG_DIC_SOFTINT = (mode << 24) | (coremask << 16) | irqn; +} diff --git a/arm11/source/arm/gic.h b/arm11/source/arm/gic.h new file mode 100644 index 0000000..d1e2e7f --- /dev/null +++ b/arm11/source/arm/gic.h @@ -0,0 +1,26 @@ +#pragma once +#include + +typedef void (*IRQ_Handler)(u32 irqn); + +#define GIC_SOFTIRQ_SOURCE(n) (((n) >> 10) & 0xF) +#define GIC_SOFTIRQ_NUMBER(n) ((n) & 0x3FF) + +enum { + GIC_SOFTIRQ_NORMAL = 0, + GIC_SOFTIRQ_NOTSELF = 1, + GIC_SOFTIRQ_SELF = 2 +}; + +enum { + GIC_HIGHEST_PRIO = 0x0, + GIC_LOWEST_PRIO = 0xF, +}; + +void GIC_GlobalReset(void); +void GIC_LocalReset(void); + +int GIC_Enable(u32 irqn, u32 coremask, u32 prio, IRQ_Handler handler); +int GIC_Disable(u32 irqn, u32 coremask); + +void GIC_TriggerSoftIRQ(u32 irqn, u32 mode, u32 coremask); diff --git a/arm11/source/arm/mmu.c b/arm11/source/arm/mmu.c new file mode 100755 index 0000000..4635e98 --- /dev/null +++ b/arm11/source/arm/mmu.c @@ -0,0 +1,28 @@ +#include +#include + +#include "arm/mmu.h" + +static u32 __attribute__((aligned(16384))) MMU_TranslationTable[4096]; + +// Currently just does a super simple identity mapping +// with all sections set to uncacheable/unbufferable +// and no access limitations (RW and no NX bit set) +void MMU_PopulateTranslationTable(void) +{ + for (int i = 0; i < 4096; i++) { + MMU_TranslationTable[i] = (i << 20) | (3 << 10) | 2; + } +} + +void MMU_Init(void) +{ + u32 ttbr0 = (u32)(&MMU_TranslationTable) | 0x12; + ARM_MCR(p15, 0, ttbr0, c2, c0, 0); + ARM_MCR(p15, 0, 0, c2, c0, 1); + ARM_MCR(p15, 0, 0, c2, c0, 2); + + ARM_MCR(p15, 0, 0x55555555, c3, c0, 0); + + ARM_MCR(p15, 0, 0, c8, c7, 0); +} diff --git a/arm11/source/arm/mmu.h b/arm11/source/arm/mmu.h new file mode 100755 index 0000000..812a92b --- /dev/null +++ b/arm11/source/arm/mmu.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +void MMU_PopulateTranslationTable(void); +void MMU_Init(void); diff --git a/arm11/source/arm/scu.c b/arm11/source/arm/scu.c new file mode 100755 index 0000000..8d4f6dc --- /dev/null +++ b/arm11/source/arm/scu.c @@ -0,0 +1,14 @@ +#include +#include + +#define REG_SCU_CNT (*REG_ARM_PMR(0x00, u32)) +#define REG_SCU_CFG (*REG_ARM_PMR(0x04, u32)) +#define REG_SCU_CPU (*REG_ARM_PMR(0x08, u32)) +#define REG_SCU_INV (*REG_ARM_PMR(0x0C, u32)) + +void SCU_Init(void) +{ + REG_SCU_CNT = 0x1FFE; + REG_SCU_INV = 0xFFFF; + REG_SCU_CNT = 0x3FFF; +} diff --git a/arm11/source/arm/scu.h b/arm11/source/arm/scu.h new file mode 100755 index 0000000..0a9183d --- /dev/null +++ b/arm11/source/arm/scu.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +void SCU_Init(void); diff --git a/arm11/source/arm/vectors.s b/arm11/source/arm/vectors.s new file mode 100644 index 0000000..1ae1986 --- /dev/null +++ b/arm11/source/arm/vectors.s @@ -0,0 +1,26 @@ +#include + +.arm +.section .text +.align 2 + +@ temporarily use dumb vectors redirected from the bootrom, rather +@ than MMU-mapped pages + +.global irq_vector +.type irq_vector, %function +irq_vector: + sub lr, lr, #4 @ Fix return address + srsfd sp!, #SR_SVC_MODE @ Store IRQ mode LR and SPSR on the SVC stack + cps #SR_SVC_MODE @ Switch to SVC mode + push {r0-r4, r12, lr} @ Preserve registers + + and r4, sp, #7 @ Fix SP to be 8byte aligned + sub sp, sp, r4 + + bl GIC_MainHandler + + add sp, sp, r4 + + pop {r0-r4, r12, lr} + rfeia sp! @ Return from exception diff --git a/arm11/source/boot.s b/arm11/source/boot.s index cdbcf64..a0d43e7 100644 --- a/arm11/source/boot.s +++ b/arm11/source/boot.s @@ -3,26 +3,48 @@ #include +#define STACK_SZ (8192) + .global __boot __boot: cpsid aif, #SR_SVC_MODE + @ Writeback and invalidate all DCache + @ Invalidate all caches + @ Data Synchronization Barrier mov r0, #0 + mcr p15, 0, r0, c7, c10, 0 mcr p15, 0, r0, c7, c7, 0 - mcr p15, 0, r0, c7, c14, 0 mcr p15, 0, r0, c7, c10, 4 - ldr sp, =_stack_top - - @ Reset values + @ Reset control registers ldr r0, =0x00054078 ldr r1, =0x0000000F - ldr r2, =0x00000000 + ldr r2, =0x00F00000 mcr p15, 0, r0, c1, c0, 0 mcr p15, 0, r1, c1, c0, 1 mcr p15, 0, r2, c1, c0, 2 + @ Get CPU ID + mrc p15, 0, r12, c0, c0, 5 + ands r12, r12, #3 + + @ Setup stack according to CPU ID + ldr sp, =(_stack_base + STACK_SZ) + ldr r0, =STACK_SZ + mla sp, r0, r12, sp + + beq corezero_start + + cmp r12, #MAX_CPU + blo coresmp_start + +1: + wfi + b 1b + +corezero_start: ldr r0, =__bss_start ldr r1, =__bss_end mov r2, #0 @@ -31,10 +53,20 @@ __boot: strlt r2, [r0], #4 blt .Lclearbss - bl main + @ Set up IRQ vector + ldr r0, =0x1FFFFFA0 + ldr r1, =0xE51FF004 + ldr r2, =irq_vector + + stmia r0, {r1, r2} + +coresmp_start: + bl SYS_CoreInit + bl MPCoreMain + b __boot .section .bss.stack .align 3 - .space (8192 * 4) -_stack_top: +_stack_base: + .space (MAX_CPU * STACK_SZ) diff --git a/arm11/source/gic.c b/arm11/source/gic.c deleted file mode 100644 index 66e3c25..0000000 --- a/arm11/source/gic.c +++ /dev/null @@ -1,49 +0,0 @@ -#include -#include - -#define IRQVECTOR_BASE ((vu32*)0x1FFFFFA0) - -extern void (*main_irq_handler)(void); -irq_handler GIC_Handlers[128]; - -void GIC_Reset(void) -{ - u32 irq_s; - - REG_GIC_CONTROL = 0; - for (int i = 0; i < 128; i++) - GIC_Handlers[i] = NULL; - - 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; - - 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; -} - -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; -} diff --git a/arm11/source/gic.h b/arm11/source/gic.h deleted file mode 100644 index 5a573ea..0000000 --- a/arm11/source/gic.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once -#include - -typedef void (*irq_handler)(void); - -#define REG_GIC_BASE (0x17E00100) // MPCore PMR -#define REG_DIC_BASE (0x17E01000) - -#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 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); diff --git a/arm11/source/gpulcd.c b/arm11/source/gpulcd.c deleted file mode 100644 index 837b115..0000000 --- a/arm11/source/gpulcd.c +++ /dev/null @@ -1,184 +0,0 @@ -#include -#include -#include - -void LCD_SetBrightness(u32 screen, u8 brightness) -{ - vu32 *lcd_reg; - if (screen & 1) { - lcd_reg = LCD_CFG(0xA40); - } else { - lcd_reg = LCD_CFG(0x240); - } - *lcd_reg = brightness; - return; -} - -void LCD_Initialize(u8 brightness) -{ - *LCD_CFG(0x014) = 0x00000001; - *LCD_CFG(0x00C) &= 0xFFFEFFFE; - *LCD_CFG(0x240) = brightness; - *LCD_CFG(0xA40) = brightness; - *LCD_CFG(0x244) = 0x1023E; - *LCD_CFG(0xA44) = 0x1023E; - return; -} - -void LCD_Deinitialize(void) -{ - *LCD_CFG(0x244) = 0; - *LCD_CFG(0xA44) = 0; - *LCD_CFG(0x00C) = 0; - *LCD_CFG(0x014) = 0; - return; -} - -void GPU_PSCFill(u32 start, u32 end, u32 fv) -{ - u32 mp; - if (start > end) - return; - - start = GPU_ADDR(start); - end = GPU_ADDR(end); - mp = (start+end)/2; - - *GPU_PSC0(PSC_SADDR) = start; - *GPU_PSC0(PSC_EADDR) = mp; - *GPU_PSC0(PSC_FILL) = fv; - - *GPU_PSC1(PSC_SADDR) = mp; - *GPU_PSC1(PSC_EADDR) = end; - *GPU_PSC1(PSC_FILL) = fv; - - *GPU_PSC0(PSC_CNT) = PSC_START | PSC_32BIT; - *GPU_PSC1(PSC_CNT) = PSC_START | PSC_32BIT; - - while(!((*GPU_PSC0(PSC_CNT) & PSC_DONE) && (*GPU_PSC1(PSC_CNT) & PSC_DONE))); - return; -} - -void GPU_SetFramebuffers(const u32 *framebuffers) -{ - *GPU_PDC0(0x68) = framebuffers[0]; - *GPU_PDC0(0x6C) = framebuffers[1]; - *GPU_PDC0(0x94) = framebuffers[2]; - *GPU_PDC0(0x98) = framebuffers[3]; - *GPU_PDC1(0x68) = framebuffers[4]; - *GPU_PDC1(0x6C) = framebuffers[5]; - *GPU_PDC0(0x78) = 0; - *GPU_PDC1(0x78) = 0; - return; -} - -void GPU_SetFramebufferMode(u32 screen, u8 mode) -{ - u32 stride, cfg; - vu32 *fbcfg_reg, *fbstr_reg; - - mode &= 7; - screen &= 1; - cfg = PDC_FIXSTRIP | mode; - if (screen) { - fbcfg_reg = GPU_PDC1(0x70); - fbstr_reg = GPU_PDC1(0x90); - } else { - fbcfg_reg = GPU_PDC0(0x70); - fbstr_reg = GPU_PDC0(0x90); - cfg |= PDC_MAINSCREEN; - } - - switch(mode) { - case PDC_RGBA8: - stride = 960; - break; - case PDC_RGB24: - stride = 720; - break; - default: - stride = 480; - break; - } - - *fbcfg_reg = cfg; - *fbstr_reg = stride; - return; -} - -void GPU_Init(void) -{ - LCD_Initialize(0x20); - - if (*GPU_CNT != 0x1007F) { - *GPU_CNT = 0x1007F; - *GPU_PDC0(0x00) = 0x000001C2; - *GPU_PDC0(0x04) = 0x000000D1; - *GPU_PDC0(0x08) = 0x000001C1; - *GPU_PDC0(0x0C) = 0x000001C1; - *GPU_PDC0(0x10) = 0x00000000; - *GPU_PDC0(0x14) = 0x000000CF; - *GPU_PDC0(0x18) = 0x000000D1; - *GPU_PDC0(0x1C) = 0x01C501C1; - *GPU_PDC0(0x20) = 0x00010000; - *GPU_PDC0(0x24) = 0x0000019D; - *GPU_PDC0(0x28) = 0x00000002; - *GPU_PDC0(0x2C) = 0x00000192; - *GPU_PDC0(0x30) = 0x00000192; - *GPU_PDC0(0x34) = 0x00000192; - *GPU_PDC0(0x38) = 0x00000001; - *GPU_PDC0(0x3C) = 0x00000002; - *GPU_PDC0(0x40) = 0x01960192; - *GPU_PDC0(0x44) = 0x00000000; - *GPU_PDC0(0x48) = 0x00000000; - *GPU_PDC0(0x5C) = 0x00F00190; - *GPU_PDC0(0x60) = 0x01C100D1; - *GPU_PDC0(0x64) = 0x01920002; - *GPU_PDC0(0x68) = VRAM_START; - *GPU_PDC0(0x6C) = VRAM_START; - *GPU_PDC0(0x70) = 0x00080340; - *GPU_PDC0(0x74) = 0x00010501; - *GPU_PDC0(0x78) = 0x00000000; - *GPU_PDC0(0x90) = 0x000003C0; - *GPU_PDC0(0x94) = VRAM_START; - *GPU_PDC0(0x98) = VRAM_START; - *GPU_PDC0(0x9C) = 0x00000000; - - for (u32 i=0; i<256; i++) - *GPU_PDC0(0x84) = 0x10101 * i; - - *GPU_PDC1(0x00) = 0x000001C2; - *GPU_PDC1(0x04) = 0x000000D1; - *GPU_PDC1(0x08) = 0x000001C1; - *GPU_PDC1(0x0C) = 0x000001C1; - *GPU_PDC1(0x10) = 0x000000CD; - *GPU_PDC1(0x14) = 0x000000CF; - *GPU_PDC1(0x18) = 0x000000D1; - *GPU_PDC1(0x1C) = 0x01C501C1; - *GPU_PDC1(0x20) = 0x00010000; - *GPU_PDC1(0x24) = 0x0000019D; - *GPU_PDC1(0x28) = 0x00000052; - *GPU_PDC1(0x2C) = 0x00000192; - *GPU_PDC1(0x30) = 0x00000192; - *GPU_PDC1(0x34) = 0x0000004F; - *GPU_PDC1(0x38) = 0x00000050; - *GPU_PDC1(0x3C) = 0x00000052; - *GPU_PDC1(0x40) = 0x01980194; - *GPU_PDC1(0x44) = 0x00000000; - *GPU_PDC1(0x48) = 0x00000011; - *GPU_PDC1(0x5C) = 0x00F00140; - *GPU_PDC1(0x60) = 0x01C100d1; - *GPU_PDC1(0x64) = 0x01920052; - *GPU_PDC1(0x68) = VRAM_START; - *GPU_PDC1(0x6C) = VRAM_START; - *GPU_PDC1(0x70) = 0x00080300; - *GPU_PDC1(0x74) = 0x00010501; - *GPU_PDC1(0x78) = 0x00000000; - *GPU_PDC1(0x90) = 0x000003C0; - *GPU_PDC1(0x9C) = 0x00000000; - - for (u32 i=0; i<256; i++) - *GPU_PDC1(0x84) = 0x10101 * i; - } - return; -} diff --git a/arm11/source/gpulcd.h b/arm11/source/gpulcd.h deleted file mode 100644 index 6b933d0..0000000 --- a/arm11/source/gpulcd.h +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once -#include - -#define GPU_ADDR(x) ((x)>>3) -#define GPU_BOX(w,h) ((w) | (h)<<16) - -#define GPU_CNT ((vu32*)(0x10141200)) - - -#define LCD_CFG(x) ((vu32*)(0x10202000 + (x))) -void LCD_SetBrightness(u32 screen, u8 brightness); -void LCD_Deinitialize(void); - -#define GPU_PSC0(x) ((vu32*)(0x10400010 + (x))) -#define GPU_PSC1(x) ((vu32*)(0x10400020 + (x))) - -#define PSC_SADDR (0x00) -#define PSC_EADDR (0x04) -#define PSC_FILL (0x08) -#define PSC_CNT (0x0C) - -#define PSC_START (BIT(0)) -#define PSC_DONE (BIT(1)) -#define PSC_32BIT (2<<8) -#define PSC_24BIT (1<<8) -#define PSC_16BIT (0<<8) - -void GPU_PSCWait(void); -void GPU_PSCFill(u32 start, u32 end, u32 fv); - - -#define GPU_PDC0(x) ((vu32*)(0x10400400 + (x))) -#define GPU_PDC1(x) ((vu32*)(0x10400500 + (x))) - -#define PDC_RGBA8 (0<<0) -#define PDC_RGB24 (1<<0) -#define PDC_RGB565 (2<<0) -#define PDC_RGB5A1 (3<<0) -#define PDC_RGBA4 (4<<0) - -#define PDC_PARALLAX (BIT(5)) -#define PDC_MAINSCREEN (BIT(6)) -#define PDC_FIXSTRIP (BIT(7)) - -void GPU_SetFramebuffers(const u32 *framebuffers); -void GPU_SetFramebufferMode(u32 screen, u8 mode); -void GPU_Init(); diff --git a/arm11/source/hw/gpulcd.c b/arm11/source/hw/gpulcd.c new file mode 100644 index 0000000..b26e022 --- /dev/null +++ b/arm11/source/hw/gpulcd.c @@ -0,0 +1,203 @@ +#include +#include + +#include "hw/gpulcd.h" + +/* LCD Configuration Registers */ +#define REG_LCD(x) ((vu32*)(0x10202000 + (x))) +void LCD_SetBrightness(u8 brightness) +{ + *REG_LCD(0x240) = brightness; + *REG_LCD(0xA40) = brightness; +} + +void LCD_Initialize(u8 brightness) +{ + *REG_LCD(0x014) = 0x00000001; + *REG_LCD(0x00C) &= 0xFFFEFFFE; + *REG_LCD(0x240) = brightness; + *REG_LCD(0xA40) = brightness; + *REG_LCD(0x244) = 0x1023E; + *REG_LCD(0xA44) = 0x1023E; + return; +} + +void LCD_Deinitialize(void) +{ + *REG_LCD(0x244) = 0; + *REG_LCD(0xA44) = 0; + *REG_LCD(0x00C) = 0; + *REG_LCD(0x014) = 0; + return; +} + +/* GPU Control Registers */ +#define REG_GPU_CNT ((vu32*)(0x10141200)) + + +/* GPU DMA */ +#define REG_GPU_PSC(n, x) ((vu32*)(0x10400010 + ((n) * 0x10) + (x))) +#define GPU_PSC_START (0x00) +#define GPU_PSC_END (0x04) +#define GPU_PSC_FILLVAL (0x08) +#define GPU_PSC_CNT (0x0C) + +#define GPUDMA_ADDR(x) ((x) >> 3) +#define PSC_START (BIT(0)) +#define PSC_DONE (BIT(1)) +#define PSC_32BIT (2 << 8) +#define PSC_24BIT (1 << 8) +#define PSC_16BIT (0 << 8) + +void GPU_PSCFill(u32 start, u32 end, u32 fv) +{ + u32 mp; + if (start > end) + return; + + start = GPUDMA_ADDR(start); + end = GPUDMA_ADDR(end); + mp = (start + end) / 2; + + *REG_GPU_PSC(0, GPU_PSC_START) = start; + *REG_GPU_PSC(0, GPU_PSC_END) = mp; + *REG_GPU_PSC(0, GPU_PSC_FILLVAL) = fv; + *REG_GPU_PSC(0, GPU_PSC_CNT) = PSC_START | PSC_32BIT; + + *REG_GPU_PSC(1, GPU_PSC_START) = mp; + *REG_GPU_PSC(1, GPU_PSC_END) = end; + *REG_GPU_PSC(1, GPU_PSC_FILLVAL) = fv; + *REG_GPU_PSC(1, GPU_PSC_CNT) = PSC_START | PSC_32BIT; + + while(!((*REG_GPU_PSC(0, GPU_PSC_CNT) | *REG_GPU_PSC(1, GPU_PSC_CNT)) & PSC_DONE)); +} + +/* GPU Display Registers */ +#define GPU_PDC(n, x) ((vu32*)(0x10400400 + ((n) * 0x100) + x)) +#define PDC_PARALLAX (BIT(5)) +#define PDC_MAINSCREEN (BIT(6)) +#define PDC_FIXSTRIP (BIT(7)) + +void GPU_SetFramebuffers(const u32 *framebuffers) +{ + *GPU_PDC(0, 0x68) = framebuffers[0]; + *GPU_PDC(0, 0x6C) = framebuffers[1]; + *GPU_PDC(0, 0x94) = framebuffers[2]; + *GPU_PDC(0, 0x98) = framebuffers[3]; + *GPU_PDC(1, 0x68) = framebuffers[4]; + *GPU_PDC(1, 0x6C) = framebuffers[5]; + *GPU_PDC(0, 0x78) = 0; + *GPU_PDC(1, 0x78) = 0; + return; +} + +void GPU_SetFramebufferMode(u32 screen, u8 mode) +{ + u32 stride, cfg; + vu32 *fbcfg_reg, *fbstr_reg; + + mode &= 7; + screen &= 1; + cfg = PDC_FIXSTRIP | mode; + if (screen) { + fbcfg_reg = GPU_PDC(1, 0x70); + fbstr_reg = GPU_PDC(1, 0x90); + } else { + fbcfg_reg = GPU_PDC(0, 0x70); + fbstr_reg = GPU_PDC(0, 0x90); + cfg |= PDC_MAINSCREEN; + } + + stride = 240; + switch(mode) { + case PDC_RGBA8: + stride *= 4; + break; + case PDC_RGB24: + stride *= 3; + break; + default: + stride *= 2; + break; + } + + *fbcfg_reg = cfg; + *fbstr_reg = stride; + return; +} + +void GPU_Init(void) +{ + LCD_Initialize(0x20); + + if (*REG_GPU_CNT != 0x1007F) { + *REG_GPU_CNT = 0x1007F; + *GPU_PDC(0, 0x00) = 0x000001C2; + *GPU_PDC(0, 0x04) = 0x000000D1; + *GPU_PDC(0, 0x08) = 0x000001C1; + *GPU_PDC(0, 0x0C) = 0x000001C1; + *GPU_PDC(0, 0x10) = 0x00000000; + *GPU_PDC(0, 0x14) = 0x000000CF; + *GPU_PDC(0, 0x18) = 0x000000D1; + *GPU_PDC(0, 0x1C) = 0x01C501C1; + *GPU_PDC(0, 0x20) = 0x00010000; + *GPU_PDC(0, 0x24) = 0x0000019D; + *GPU_PDC(0, 0x28) = 0x00000002; + *GPU_PDC(0, 0x2C) = 0x00000192; + *GPU_PDC(0, 0x30) = 0x00000192; + *GPU_PDC(0, 0x34) = 0x00000192; + *GPU_PDC(0, 0x38) = 0x00000001; + *GPU_PDC(0, 0x3C) = 0x00000002; + *GPU_PDC(0, 0x40) = 0x01960192; + *GPU_PDC(0, 0x44) = 0x00000000; + *GPU_PDC(0, 0x48) = 0x00000000; + *GPU_PDC(0, 0x5C) = 0x00F00190; + *GPU_PDC(0, 0x60) = 0x01C100D1; + *GPU_PDC(0, 0x64) = 0x01920002; + *GPU_PDC(0, 0x68) = VRAM_START; + *GPU_PDC(0, 0x6C) = VRAM_START; + *GPU_PDC(0, 0x70) = 0x00080340; + *GPU_PDC(0, 0x74) = 0x00010501; + *GPU_PDC(0, 0x78) = 0x00000000; + *GPU_PDC(0, 0x90) = 0x000003C0; + *GPU_PDC(0, 0x94) = VRAM_START; + *GPU_PDC(0, 0x98) = VRAM_START; + *GPU_PDC(0, 0x9C) = 0x00000000; + + for (u32 i = 0; i < 256; i++) + *GPU_PDC(0, 0x84) = 0x10101 * i; + + *GPU_PDC(1, 0x00) = 0x000001C2; + *GPU_PDC(1, 0x04) = 0x000000D1; + *GPU_PDC(1, 0x08) = 0x000001C1; + *GPU_PDC(1, 0x0C) = 0x000001C1; + *GPU_PDC(1, 0x10) = 0x000000CD; + *GPU_PDC(1, 0x14) = 0x000000CF; + *GPU_PDC(1, 0x18) = 0x000000D1; + *GPU_PDC(1, 0x1C) = 0x01C501C1; + *GPU_PDC(1, 0x20) = 0x00010000; + *GPU_PDC(1, 0x24) = 0x0000019D; + *GPU_PDC(1, 0x28) = 0x00000052; + *GPU_PDC(1, 0x2C) = 0x00000192; + *GPU_PDC(1, 0x30) = 0x00000192; + *GPU_PDC(1, 0x34) = 0x0000004F; + *GPU_PDC(1, 0x38) = 0x00000050; + *GPU_PDC(1, 0x3C) = 0x00000052; + *GPU_PDC(1, 0x40) = 0x01980194; + *GPU_PDC(1, 0x44) = 0x00000000; + *GPU_PDC(1, 0x48) = 0x00000011; + *GPU_PDC(1, 0x5C) = 0x00F00140; + *GPU_PDC(1, 0x60) = 0x01C100d1; + *GPU_PDC(1, 0x64) = 0x01920052; + *GPU_PDC(1, 0x68) = VRAM_START; + *GPU_PDC(1, 0x6C) = VRAM_START; + *GPU_PDC(1, 0x70) = 0x00080300; + *GPU_PDC(1, 0x74) = 0x00010501; + *GPU_PDC(1, 0x78) = 0x00000000; + *GPU_PDC(1, 0x90) = 0x000003C0; + *GPU_PDC(1, 0x9C) = 0x00000000; + + for (u32 i = 0; i < 256; i++) + *GPU_PDC(1, 0x84) = 0x10101 * i; + } +} diff --git a/arm11/source/hw/gpulcd.h b/arm11/source/hw/gpulcd.h new file mode 100644 index 0000000..28e4957 --- /dev/null +++ b/arm11/source/hw/gpulcd.h @@ -0,0 +1,16 @@ +#pragma once +#include + +void LCD_SetBrightness(u8 brightness); +void LCD_Deinitialize(void); + +void GPU_PSCFill(u32 start, u32 end, u32 fv); + +#define PDC_RGBA8 (0<<0) +#define PDC_RGB24 (1<<0) +#define PDC_RGB565 (2<<0) +#define PDC_RGB5A1 (3<<0) +#define PDC_RGBA4 (4<<0) +void GPU_SetFramebufferMode(u32 screen, u8 mode); +void GPU_SetFramebuffers(const u32 *framebuffers); +void GPU_Init(); diff --git a/arm11/source/i2c.c b/arm11/source/hw/i2c.c similarity index 99% rename from arm11/source/i2c.c rename to arm11/source/hw/i2c.c index ac2147f..6800c31 100644 --- a/arm11/source/i2c.c +++ b/arm11/source/hw/i2c.c @@ -17,8 +17,9 @@ */ #include -#include "types.h" -#include "i2c.h" + +#include +#include "hw/i2c.h" #define I2C1_REGS_BASE (0x10161000) diff --git a/arm11/source/i2c.h b/arm11/source/hw/i2c.h similarity index 99% rename from arm11/source/i2c.h rename to arm11/source/hw/i2c.h index a164526..15f4dea 100644 --- a/arm11/source/i2c.h +++ b/arm11/source/hw/i2c.h @@ -19,7 +19,7 @@ */ #include -#include "types.h" +#include #define I2C_STOP (1u) diff --git a/arm11/source/mcu.c b/arm11/source/hw/mcu.c similarity index 100% rename from arm11/source/mcu.c rename to arm11/source/hw/mcu.c diff --git a/arm11/source/mcu.h b/arm11/source/hw/mcu.h similarity index 100% rename from arm11/source/mcu.h rename to arm11/source/hw/mcu.h diff --git a/arm11/source/irq.s b/arm11/source/irq.s deleted file mode 100644 index 9ddedae..0000000 --- a/arm11/source/irq.s +++ /dev/null @@ -1,46 +0,0 @@ -.section .text -.arm - -#include - -#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 - srsfd sp!, #SR_SVC_MODE @ Store IRQ mode LR and SPSR on the SVC stack - cps #SR_SVC_MODE @ Switch to SVC mode - push {r0-r3, r12, lr} @ Preserve registers - - 1: - ldr lr, =MPCORE_PMR - ldr r0, [lr, #0x10C] @ Get pending interrupt - - ldr r1, =IRQ_SPURIOUS - cmp r0, r1 - beq 3f @ Spurious interrupt, no interrupts pending - - 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 - diff --git a/arm11/source/main.c b/arm11/source/main.c index 351dcb7..aba9609 100644 --- a/arm11/source/main.c +++ b/arm11/source/main.c @@ -1,27 +1,25 @@ +#include +#include #include #include -#include -#include -#include -#include -#include - -#define CFG11_MPCORE_CLKCNT ((vu16*)(0x10141300)) -#define CFG11_SOCINFO ((vu16*)(0x10140FFC)) +#include "arm/gic.h" +#include "hw/gpulcd.h" +#include "hw/i2c.h" +#include "hw/mcu.h" #define LEGACY_BOOT_ENTRY ((vu32*)0x1FFFFFFC) #define LEGACY_BOOT_MAGIC (0xDEADDEAD) -void PXI_RX_Handler(void) +void PXI_RX_Handler(u32 __attribute__((unused)) irqn) { - u32 ret, msg, cmd, argc, args[PXI_FIFO_LEN]; + u32 ret, msg, cmd, argc, args[PXI_MAX_ARGS]; msg = PXI_Recv(); cmd = msg & 0xFFFF; argc = msg >> 16; - if (argc > PXI_FIFO_LEN) { + if (argc > PXI_MAX_ARGS) { PXI_Send(0xFFFFFFFF); return; } @@ -29,6 +27,20 @@ void PXI_RX_Handler(void) PXI_RecvArray(args, argc); switch (cmd) { + case PXI_LEGACY_MODE: + { + *LEGACY_BOOT_ENTRY = LEGACY_BOOT_MAGIC; + ret = 0; + break; + } + + case PXI_GET_SHMEM: + { + //ret = (u32)SHMEM_GetGlobalPointer(); + ret = 0xFFFFFFFF; + break; + } + case PXI_SCREENINIT: { GPU_Init(); @@ -45,8 +57,7 @@ void PXI_RX_Handler(void) case PXI_BRIGHTNESS: { - LCD_SetBrightness(0, args[0]); - LCD_SetBrightness(1, args[0]); + LCD_SetBrightness(args[0]); ret = args[0]; break; } @@ -63,13 +74,6 @@ void PXI_RX_Handler(void) break; } - case PXI_LEGACY_BOOT: - { - *LEGACY_BOOT_ENTRY = LEGACY_BOOT_MAGIC; - ret = 0; - break; - } - /* New CMD template: case CMD_ID: { @@ -89,38 +93,29 @@ void PXI_RX_Handler(void) return; } -void main(void) +void MPCoreMain(void) { u32 entry; - if ((*CFG11_SOCINFO & 2) && (!(*CFG11_MPCORE_CLKCNT & 1))) { - GIC_Reset(); - GIC_SetIRQ(88, NULL); - arm_enable_ints(); - *CFG11_MPCORE_CLKCNT = 0x8001; - do { - asm("wfi\n\t"); - } while(!(*CFG11_MPCORE_CLKCNT & 0x8000)); - arm_disable_ints(); - } - - GIC_Reset(); + GIC_Enable(IRQ_PXI_RX, BIT(0), GIC_HIGHEST_PRIO, PXI_RX_Handler); + *LEGACY_BOOT_ENTRY = 0; PXI_Reset(); I2C_init(); //MCU_init(); - GIC_SetIRQ(IRQ_PXI_RX, PXI_RX_Handler); - *LEGACY_BOOT_ENTRY = 0; - - arm_enable_ints(); + PXI_Barrier(ARM11_READY_BARRIER); + ARM_EnableInterrupts(); + // Process IRQs until the ARM9 tells us it's time to boot something else do { - arm_wfi(); + ARM_WFI(); } while(*LEGACY_BOOT_ENTRY != LEGACY_BOOT_MAGIC); - arm_disable_ints(); - GIC_Reset(); + // Perform any needed deinit stuff + ARM_DisableInterrupts(); + GIC_GlobalReset(); + GIC_LocalReset(); do { entry = *LEGACY_BOOT_ENTRY; diff --git a/arm11/source/sys.c b/arm11/source/sys.c new file mode 100755 index 0000000..23e0ccd --- /dev/null +++ b/arm11/source/sys.c @@ -0,0 +1,68 @@ +#include +#include + +#include "arm/gic.h" +#include "arm/scu.h" +#include "arm/mmu.h" + +#define CFG11_MPCORE_CLKCNT ((vu16*)(0x10141300)) +#define CFG11_SOCINFO ((vu16*)(0x10140FFC)) + +static bool SYS_IsNewConsole(void) +{ + return (*CFG11_SOCINFO & 2) != 0; +} + +static bool SYS_ClkMultEnabled(void) +{ + return (*CFG11_MPCORE_CLKCNT & 1) != 0; +} + +static void SYS_EnableClkMult(void) +{ + // magic bit twiddling to enable extra FCRAM + // only done on N3DS and when it hasn't been done yet + // state might get a bit messed up so it has to be done + // as early as possible in the initialization chain + if (SYS_IsNewConsole() && !SYS_ClkMultEnabled()) { + GIC_Enable(88, BIT(0), GIC_HIGHEST_PRIO, NULL); + ARM_EnableInterrupts(); + *CFG11_MPCORE_CLKCNT = 0x8001; + do { + ARM_WFI(); + } while(!(*CFG11_MPCORE_CLKCNT & 0x8000)); + ARM_DisableInterrupts(); + GIC_Disable(88, BIT(0)); + } +} + +static void SYS_CoreZeroInit(void) +{ + GIC_GlobalReset(); + SYS_EnableClkMult(); + + SCU_Init(); + + // Init MMU tables here + MMU_PopulateTranslationTable(); +} + +void SYS_CoreInit(void) +{ + if (!ARM_CoreID()) { + SYS_CoreZeroInit(); + } + + GIC_LocalReset(); + + MMU_Init(); + + // enable fancy ARM11 stuff + ARM_SetACR(ARM_GetACR() | + ACR_RETSTK | ACR_DBPRED | ACR_SBPRED | ACR_FOLDING | ACR_SMP); + + ARM_SetCR(ARM_GetCR() | + CR_MMU | CR_CACHES | CR_FLOWPRED | CR_HIGHVEC | CR_DSUBPAGE); + + ARM_DSB(); +} diff --git a/arm9/source/common/power.c b/arm9/source/common/power.c index effe828..af7345e 100644 --- a/arm9/source/common/power.c +++ b/arm9/source/common/power.c @@ -35,8 +35,8 @@ bool IsCharging() { void Reboot() { I2C_writeReg(I2C_DEV_MCU, 0x22, 1 << 0); // poweroff LCD to prevent MCU hangs - arm_wb_dc(); - arm_dsb(); + ARM_WbDC(); + ARM_DSB(); I2C_writeReg(I2C_DEV_MCU, 0x20, 1 << 2); while(true); } @@ -44,8 +44,8 @@ void Reboot() { void PowerOff() { I2C_writeReg(I2C_DEV_MCU, 0x22, 1 << 0); // poweroff LCD to prevent MCU hangs - arm_wb_dc(); - arm_dsb(); + ARM_WbDC(); + ARM_DSB(); I2C_writeReg(I2C_DEV_MCU, 0x20, 1 << 0); while(true); } diff --git a/arm9/source/godmode.c b/arm9/source/godmode.c index 48bffea..a0ab540 100644 --- a/arm9/source/godmode.c +++ b/arm9/source/godmode.c @@ -100,7 +100,7 @@ u32 BootFirmHandler(const char* bootpath, bool verbose, bool delete) { // boot the FIRM (if we got a proper fixpath) if (*fixpath) { if (delete) PathDelete(bootpath); - PXI_DoCMD(PXI_LEGACY_BOOT, NULL, 0); + PXI_DoCMD(PXI_LEGACY_MODE, NULL, 0); BootFirm((FirmHeader*) firm, fixpath); while(1); } diff --git a/arm9/source/main.c b/arm9/source/main.c index e9a5d1b..a9e8fc9 100644 --- a/arm9/source/main.c +++ b/arm9/source/main.c @@ -13,6 +13,10 @@ void main(int argc, char** argv, int entrypoint) PXI_Reset(); + // Don't even try to send any messages until the + // ARM11 says it's ready + PXI_Barrier(ARM11_READY_BARRIER); + PXI_DoCMD(PXI_SCREENINIT, NULL, 0); I2C_writeReg(I2C_DEV_MCU, 0x22, 0x2A); diff --git a/arm9/source/start.s b/arm9/source/start.s index 12a6f83..2b339de 100644 --- a/arm9/source/start.s +++ b/arm9/source/start.s @@ -33,7 +33,7 @@ _start: blx r0 @ Invalidate Instruction Cache @ Disable caches / DTCM / MPU - ldr r1, =(CR_MPU | CR_DCACHE | CR_ICACHE | CR_DTCM | CR_TCM_LOAD) + ldr r1, =(CR_MPU | CR_CACHES | CR_DTCM | CR_TCM_LOAD) ldr r2, =(CR_ITCM) mrc p15, 0, r0, c1, c0, 0 bic r0, r1 @@ -92,7 +92,7 @@ _start: @ Enable caches / DTCM / select low exception vectors ldr r1, =(CR_ALT_VECTORS | CR_V4TLD) - ldr r2, =(CR_MPU | CR_DCACHE | CR_ICACHE | CR_DTCM) + ldr r2, =(CR_MPU | CR_CACHES | CR_DTCM) mrc p15, 0, r0, c1, c0, 0 bic r0, r1 orr r0, r2 diff --git a/arm9/source/system/i2c.c b/arm9/source/system/i2c.c index eadb292..0a1844a 100755 --- a/arm9/source/system/i2c.c +++ b/arm9/source/system/i2c.c @@ -24,12 +24,12 @@ bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size) int ret; u32 args[] = {devId, regAddr, (u32)i2c_fcram_buf, size}; - arm_wb_dc_range(i2c_fcram_buf, size); - arm_dsb(); + ARM_WbDC_Range(i2c_fcram_buf, size); + ARM_DSB(); ret = PXI_DoCMD(PXI_I2C_READ, args, 4); - arm_inv_dc_range(i2c_fcram_buf, size); + ARM_InvDC_Range(i2c_fcram_buf, size); memcpy(out, i2c_fcram_buf, size); return ret; } @@ -43,8 +43,8 @@ bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const u8 *in, u32 size) u32 args[] = {devId, regAddr, (u32)i2c_fcram_buf, size}; memcpy(i2c_fcram_buf, in, size); - arm_wb_dc_range(i2c_fcram_buf, size); - arm_dsb(); + ARM_WbDC_Range(i2c_fcram_buf, size); + ARM_DSB(); ret = PXI_DoCMD(PXI_I2C_WRITE, args, 4); return ret; diff --git a/arm9/source/system/xrq_handler.s b/arm9/source/system/xrq_handler.s index 7872887..587aa6a 100644 --- a/arm9/source/system/xrq_handler.s +++ b/arm9/source/system/xrq_handler.s @@ -95,7 +95,7 @@ XRQ_MainHandler: mcr p15, 0, r0, c2, c0, 1 @ Inst cacheable 0, 2, 5 @ Enable mpu/caches - ldr r1, =(CR_MPU | CR_DCACHE | CR_ICACHE | CR_DTCM) + ldr r1, =(CR_MPU | CR_CACHES | CR_DTCM) mrc p15, 0, r0, c1, c0, 0 orr r0, r0, r1 mcr p15, 0, r0, c1, c0, 0 diff --git a/common/arm.h b/common/arm.h index fcdb279..f70b39f 100644 --- a/common/arm.h +++ b/common/arm.h @@ -29,10 +29,14 @@ #define CR_CACHE_RROBIN BIT(14) #define CR_DTCM_LOAD BIT(17) #define CR_ITCM_LOAD BIT(19) - #define CR_TCM_LOAD (CR_DTCM_LOAD | CR_ITCM_LOAD) + + #define CR_TCM_LOAD (CR_DTCM_LOAD | CR_ITCM_LOAD) #define ICACHE_SZ (4096) #define DCACHE_SZ (4096) + + #define MAX_IRQ (32) + #define MAX_CPU (1) #else // ARM11 #define CR_MMU BIT(0) #define CR_ALIGN BIT(1) @@ -53,8 +57,13 @@ #define ICACHE_SZ (16384) #define DCACHE_SZ (16384) + + #define MAX_IRQ (96) + #define MAX_CPU (2) #endif +#define CR_CACHES (CR_DCACHE | CR_ICACHE) + #ifndef __ASSEMBLER__ @@ -90,7 +99,7 @@ * so that all instructions following the ISB are fetched from cache or memory * after the ISB has been completed. */ - static inline void arm_isb(void) { + static inline void ARM_ISB(void) { ARM_MCR(p15, 0, 0, c7, c5, 4); } @@ -98,33 +107,33 @@ * A Data Memory Barrier (DMB) ensures that all explicit memory accesses before * the DMB instruction complete before any explicit memory accesses after the DMB instruction start. */ - static inline void arm_dmb(void) { + static inline void ARM_DMB(void) { ARM_MCR(p15, 0, 0, c7, c10, 5); } /* Wait For Interrupt */ - static inline void arm_wfi(void) { + static inline void ARM_WFI(void) { asm_v("wfi\n\t"); } /* Wait For Event */ - static inline void arm_wfe(void) { + static inline void ARM_WFE(void) { asm_v("wfe\n\t"); } /* Send Event */ - static inline void arm_sev(void) { + static inline void ARM_SEV(void) { asm_v("sev\n\t"); } /* Auxiliary Control Registers */ - static inline u32 arm_acr_get(void) { + static inline u32 ARM_GetACR(void) { u32 acr; ARM_MRC(p15, 0, acr, c1, c0, 1); return acr; } - static inline void arm_acr_set(u32 acr) { + static inline void ARM_SetACR(u32 acr) { ARM_MCR(p15, 0, acr, c1, c0, 1); } #endif @@ -134,24 +143,24 @@ * A Data Synchronization Barrier (DSB) completes when all * instructions before this instruction complete. */ -static inline void arm_dsb(void) { +static inline void ARM_DSB(void) { ARM_MCR(p15, 0, 0, c7, c10, 4); } /* Control Registers */ -static inline u32 arm_cr_get(void) { +static inline u32 ARM_GetCR(void) { u32 cr; ARM_MRC(p15, 0, cr, c1, c0, 0); return cr; } -static inline void arm_cr_set(u32 cr) { +static inline void ARM_SetCR(u32 cr) { ARM_MCR(p15, 0, cr, c1, c0, 0); } /* Thread ID Registers */ -static inline u32 arm_tid_get(void) { +static inline u32 ARM_GetTID(void) { u32 pid; #ifdef ARM9 ARM_MRC(p15, 0, pid, c13, c0, 1); @@ -161,7 +170,7 @@ static inline u32 arm_tid_get(void) { return pid; } -static inline void arm_tid_set(u32 pid) { +static inline void ARM_SetTID(u32 pid) { #ifdef ARM9 ARM_MCR(p15, 0, pid, c13, c0, 1); #else @@ -170,7 +179,7 @@ static inline void arm_tid_set(u32 pid) { } /* CPU ID */ -static inline u32 arm_cpuid(void) { +static inline u32 ARM_CoreID(void) { u32 id; #ifdef ARM9 id = 0; @@ -181,63 +190,71 @@ static inline u32 arm_cpuid(void) { } /* Status Register */ -static inline u32 arm_cpsr_get(void) { - u32 cpsr; - ARM_MRS(cpsr, "cpsr"); - return cpsr; +static inline u32 ARM_GetCPSR(void) { + u32 sr; + ARM_MRS(sr, cpsr); + return sr; } -static inline void arm_cpsr_c_set(u32 cpsr) { - ARM_MSR("cpsr_c", cpsr); +static inline void ARM_SetCPSR_c(u32 sr) { + ARM_MSR(cpsr_c, sr); } -static inline void arm_disable_ints(void) { +static inline void ARM_DisableInterrupts(void) { #ifdef ARM9 - arm_cpsr_c_set(arm_cpsr_get() | SR_NOINT); + ARM_SetCPSR_c(ARM_GetCPSR() | SR_NOINT); #else ARM_CPSID(if); #endif } -static inline void arm_enable_ints(void) { +static inline void ARM_EnableInterrupts(void) { #ifdef ARM9 - arm_cpsr_c_set(arm_cpsr_get() & ~SR_NOINT); + ARM_SetCPSR_c(ARM_GetCPSR() & ~SR_NOINT); #else ARM_CPSIE(if); #endif } -static inline u32 arm_enter_critical(void) { - u32 stat = arm_cpsr_get(); - arm_disable_ints(); +static inline u32 ARM_EnterCritical(void) { + u32 stat = ARM_GetCPSR(); + ARM_DisableInterrupts(); return stat & SR_NOINT; } -static inline void arm_leave_critical(u32 stat) { - arm_cpsr_c_set((arm_cpsr_get() & ~SR_NOINT) | stat); +static inline void ARM_LeaveCritical(u32 stat) { + ARM_SetCPSR_c((ARM_GetCPSR() & ~SR_NOINT) | stat); } /* Cache functions */ -static inline void arm_inv_ic(void) { +static inline void ARM_InvIC(void) { + #ifdef ARM9 ARM_MCR(p15, 0, 0, c7, c5, 0); + #else + ARM_MCR(p15, 0, 0, c7, c7, 0); + #endif } -static inline void arm_inv_ic_range(void *base, u32 len) { +static inline void ARM_InvIC_Range(void *base, u32 len) { u32 addr = (u32)base & ~0x1F; len >>= 5; do { + #ifdef ARM9 ARM_MCR(p15, 0, addr, c7, c5, 1); + #else + ARM_MCR(p15, 0, addr, c7, c7, 1); + #endif addr += 0x20; } while(len--); } -static inline void arm_inv_dc(void) { +static inline void ARM_InvDC(void) { ARM_MCR(p15, 0, 0, c7, c6, 0); } -static inline void arm_inv_dc_range(void *base, u32 len) { +static inline void ARM_InvDC_Range(void *base, u32 len) { u32 addr = (u32)base & ~0x1F; len >>= 5; @@ -247,7 +264,7 @@ static inline void arm_inv_dc_range(void *base, u32 len) { } while(len--); } -static inline void arm_wb_dc(void) { +static inline void ARM_WbDC(void) { #ifdef ARM9 u32 seg = 0, ind; do { @@ -263,7 +280,7 @@ static inline void arm_wb_dc(void) { #endif } -static inline void arm_wb_dc_range(void *base, u32 len) { +static inline void ARM_WbDC_Range(void *base, u32 len) { u32 addr = (u32)base & ~0x1F; len >>= 5; @@ -273,7 +290,7 @@ static inline void arm_wb_dc_range(void *base, u32 len) { } while(len--); } -static inline void arm_wb_inv_dc(void) { +static inline void ARM_WbInvDC(void) { #ifdef ARM9 u32 seg = 0, ind; do { @@ -289,7 +306,7 @@ static inline void arm_wb_inv_dc(void) { #endif } -static inline void arm_wb_inv_dc_range(void *base, u32 len) { +static inline void ARM_WbInvDC_Range(void *base, u32 len) { u32 addr = (u32)base & ~0x1F; len >>= 5; @@ -299,4 +316,8 @@ static inline void arm_wb_inv_dc_range(void *base, u32 len) { } while(len--); } +static inline void ARM_BKPT(void) { + __builtin_trap(); +} + #endif // __ASSEMBLER__ diff --git a/common/pxi.h b/common/pxi.h index 0aa0b7a..913be0f 100644 --- a/common/pxi.h +++ b/common/pxi.h @@ -15,14 +15,28 @@ #endif enum { - PXI_SCREENINIT = 0, + PXI_LEGACY_MODE = 0, + PXI_GET_SHMEM, + + PXI_SCREENINIT, PXI_BRIGHTNESS, PXI_I2C_READ, PXI_I2C_WRITE, - PXI_LEGACY_BOOT, }; -#define PXI_FIFO_LEN (16) +/* + * These should be pseudo-random numbers + * and shouldnt be similar to those + * used by any other software + */ +enum { + ARM11_READY_BARRIER = 19, +}; + +#define PXI_FIFO_LEN (16) +#define PXI_MAX_ARGS (32) + +#define PXI_INIT_MAGIC (0xDD) #define PXI_SYNC_RECV ((vu8*)(PXI_BASE + 0x00)) #define PXI_SYNC_SEND ((vu8*)(PXI_BASE + 0x01)) @@ -41,10 +55,6 @@ enum { #define PXI_CNT_ERROR_ACK (BIT(14)) #define PXI_CNT_ENABLE_FIFO (BIT(15)) -#define PXI_SYNC_TRIGGER_MPCORE (BIT(5)) -#define PXI_SYNC_TRIGGER_OLDARM (BIT(6)) -#define PXI_SYNC_ENABLE_IRQ (BIT(7)) - static inline void PXI_SetRemote(u8 msg) { *PXI_SYNC_SEND = msg; @@ -60,7 +70,7 @@ static inline void PXI_WaitRemote(u8 msg) while(PXI_GetRemote() != msg); } -static void PXI_Reset(void) +static inline void PXI_Reset(void) { *PXI_SYNC_IRQ = 0; *PXI_CNT = PXI_CNT_SEND_FIFO_FLUSH | PXI_CNT_ENABLE_FIFO; @@ -69,31 +79,39 @@ static void PXI_Reset(void) *PXI_CNT = 0; *PXI_CNT = PXI_CNT_RECV_FIFO_AVAIL_IRQ | PXI_CNT_ENABLE_FIFO; + + PXI_SetRemote(0xFF); } -static void PXI_Send(u32 w) +static inline void PXI_Barrier(u8 bar) +{ + PXI_SetRemote(bar); + PXI_WaitRemote(bar); +} + +static inline void PXI_Send(u32 w) { while(*PXI_CNT & PXI_CNT_SEND_FIFO_FULL); *PXI_SEND = w; } -static u32 PXI_Recv(void) +static inline u32 PXI_Recv(void) { while(*PXI_CNT & PXI_CNT_RECV_FIFO_EMPTY); return *PXI_RECV; } -static void PXI_SendArray(const u32 *w, u32 c) +static inline void PXI_SendArray(const u32 *w, u32 c) { while(c--) PXI_Send(*(w++)); } -static void PXI_RecvArray(u32 *w, u32 c) +static inline void PXI_RecvArray(u32 *w, u32 c) { while(c--) *(w++) = PXI_Recv(); } -static u32 PXI_DoCMD(u32 cmd, const u32 *args, u32 argc) +static inline u32 PXI_DoCMD(u32 cmd, const u32 *args, u32 argc) { PXI_Send((argc << 16) | cmd); PXI_SendArray(args, argc); diff --git a/common/types.h b/common/types.h index d36fc73..1839c9f 100644 --- a/common/types.h +++ b/common/types.h @@ -9,6 +9,7 @@ #define BIT(x) (1 << (x)) #ifndef __ASSEMBLER__ +#include #include #include