From e70b8ab1165a1bb0f93c94e5f0457ca097aef852 Mon Sep 17 00:00:00 2001 From: Wolfvak Date: Tue, 9 Apr 2019 09:33:52 -0300 Subject: [PATCH] - unified CPU/cache header that works on C and asm code - added legacy boot PXI command that allows power savings on ARM11 --- arm11/source/gic.c | 6 +- arm11/source/irq.s | 4 +- arm11/source/main.c | 177 +++++++++-------- arm9/source/common/power.c | 10 +- arm9/source/godmode.c | 2 + arm9/source/start.s | 21 +- arm9/source/system/bootfirm.s | 8 +- arm9/source/system/cache.h | 102 ---------- arm9/source/system/i2c.c | 13 +- arm9/source/system/xrq_handler.s | 14 +- common/arm.h | 320 ++++++++++++++++++++++++++++--- common/cpu.h | 68 ------- common/pxi.h | 52 +++-- common/types.h | 6 +- 14 files changed, 459 insertions(+), 344 deletions(-) delete mode 100644 arm9/source/system/cache.h delete mode 100644 common/cpu.h diff --git a/arm11/source/gic.c b/arm11/source/gic.c index 034fbcc..66e3c25 100644 --- a/arm11/source/gic.c +++ b/arm11/source/gic.c @@ -1,9 +1,6 @@ #include -#include #include -#include - #define IRQVECTOR_BASE ((vu32*)0x1FFFFFA0) extern void (*main_irq_handler)(void); @@ -14,7 +11,8 @@ void GIC_Reset(void) u32 irq_s; REG_GIC_CONTROL = 0; - memset(GIC_Handlers, 0, sizeof(GIC_Handlers)); + for (int i = 0; i < 128; i++) + GIC_Handlers[i] = NULL; REG_DIC_CONTROL = 0; for (int i = 0; i < 4; i++) { diff --git a/arm11/source/irq.s b/arm11/source/irq.s index c3c02d0..9ddedae 100644 --- a/arm11/source/irq.s +++ b/arm11/source/irq.s @@ -11,8 +11,8 @@ .type main_irq_handler, %function main_irq_handler: sub lr, lr, #4 @ Fix return address - srsfd sp!, #0x13 @ Store IRQ mode LR and SPSR on the SVC stack - cps #0x13 @ Switch to SVC mode + 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: diff --git a/arm11/source/main.c b/arm11/source/main.c index 2565e52..351dcb7 100644 --- a/arm11/source/main.c +++ b/arm11/source/main.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -7,107 +7,124 @@ #include -#define CFG11_MPCORE_CLKCNT ((vu16*)(0x10141300)) -#define CFG11_SOCINFO ((vu16*)(0x10140FFC)) +#define CFG11_MPCORE_CLKCNT ((vu16*)(0x10141300)) +#define CFG11_SOCINFO ((vu16*)(0x10140FFC)) -vu32 *entrypoint = (vu32*)0x1FFFFFFC; +#define LEGACY_BOOT_ENTRY ((vu32*)0x1FFFFFFC) +#define LEGACY_BOOT_MAGIC (0xDEADDEAD) void PXI_RX_Handler(void) { - u32 pxi_cmd, ret; - u32 pxi_args[PXI_FIFO_LEN]; + u32 ret, msg, cmd, argc, args[PXI_FIFO_LEN]; - pxi_cmd = PXI_Recv(); - switch (pxi_cmd) { - case PXI_SCREENINIT: - { - GPU_Init(); - GPU_PSCFill(VRAM_START, VRAM_END, 0); - GPU_SetFramebuffers((u32[]){VRAM_TOP_LA, VRAM_TOP_LB, - VRAM_TOP_RA, VRAM_TOP_RB, - VRAM_BOT_A, VRAM_BOT_B}); + msg = PXI_Recv(); + cmd = msg & 0xFFFF; + argc = msg >> 16; - GPU_SetFramebufferMode(0, PDC_RGB24); - GPU_SetFramebufferMode(1, PDC_RGB24); - ret = 0; - break; - } + if (argc > PXI_FIFO_LEN) { + PXI_Send(0xFFFFFFFF); + return; + } - case PXI_BRIGHTNESS: - { - PXI_RecvArray(pxi_args, 1); - LCD_SetBrightness(0, pxi_args[0]); - LCD_SetBrightness(1, pxi_args[0]); - ret = pxi_args[0]; - break; - } + PXI_RecvArray(args, argc); - case PXI_I2C_READ: - { - PXI_RecvArray(pxi_args, 4); - ret = I2C_readRegBuf(pxi_args[0], pxi_args[1], - (u8*)pxi_args[2], pxi_args[3]); - break; - } + switch (cmd) { + case PXI_SCREENINIT: + { + GPU_Init(); + GPU_PSCFill(VRAM_START, VRAM_END, 0); + GPU_SetFramebuffers((u32[]){VRAM_TOP_LA, VRAM_TOP_LB, + VRAM_TOP_RA, VRAM_TOP_RB, + VRAM_BOT_A, VRAM_BOT_B}); - case PXI_I2C_WRITE: - { - PXI_RecvArray(pxi_args, 4); - ret = I2C_writeRegBuf(pxi_args[0], pxi_args[1], - (const u8*)pxi_args[2], pxi_args[3]); - break; - } + GPU_SetFramebufferMode(0, PDC_RGB24); + GPU_SetFramebufferMode(1, PDC_RGB24); + ret = 0; + break; + } - /* New CMD template: - case CMD_ID: - { - - - - - break; - } - */ + case PXI_BRIGHTNESS: + { + LCD_SetBrightness(0, args[0]); + LCD_SetBrightness(1, args[0]); + ret = args[0]; + break; + } - default: - ret = 0xFFFFFFFF; - break; - } + case PXI_I2C_READ: + { + ret = I2C_readRegBuf(args[0], args[1], (u8*)args[2], args[3]); + break; + } - PXI_Send(ret); - return; + case PXI_I2C_WRITE: + { + ret = I2C_writeRegBuf(args[0], args[1], (u8*)args[2], args[3]); + break; + } + + case PXI_LEGACY_BOOT: + { + *LEGACY_BOOT_ENTRY = LEGACY_BOOT_MAGIC; + ret = 0; + break; + } + + /* New CMD template: + case CMD_ID: + { + + + + break; + } + */ + + default: + ret = 0xFFFFFFFF; + break; + } + + PXI_Send(ret); + return; } void main(void) { - u32 entry; + u32 entry; - 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(); - } + 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_Reset(); - PXI_Reset(); - I2C_init(); - //MCU_init(); + PXI_Reset(); + I2C_init(); + //MCU_init(); - GIC_SetIRQ(IRQ_PXI_RX, PXI_RX_Handler); + GIC_SetIRQ(IRQ_PXI_RX, PXI_RX_Handler); + *LEGACY_BOOT_ENTRY = 0; - CPU_EnableIRQ(); + arm_enable_ints(); - *entrypoint = 0; - while((entry=*entrypoint) == 0); + do { + arm_wfi(); + } while(*LEGACY_BOOT_ENTRY != LEGACY_BOOT_MAGIC); - CPU_DisableIRQ(); - GIC_Reset(); + arm_disable_ints(); + GIC_Reset(); - ((void (*)())(entry))(); + do { + entry = *LEGACY_BOOT_ENTRY; + } while(entry == LEGACY_BOOT_MAGIC); + + ((void (*)())(entry))(); } diff --git a/arm9/source/common/power.c b/arm9/source/common/power.c index a376f29..effe828 100644 --- a/arm9/source/common/power.c +++ b/arm9/source/common/power.c @@ -1,6 +1,6 @@ +#include "arm.h" #include "power.h" #include "i2c.h" -#include "cache.h" #include "pxi.h" static const u8 br_settings[] = {0x10, 0x17, 0x1E, 0x25, 0x2C, 0x34, 0x3C, 0x44, 0x4D, 0x56, 0x60, 0x6B, 0x79, 0x8C, 0xA7, 0xD2}; @@ -35,8 +35,8 @@ bool IsCharging() { void Reboot() { I2C_writeReg(I2C_DEV_MCU, 0x22, 1 << 0); // poweroff LCD to prevent MCU hangs - cpu_writeback_dc(); - cpu_membarrier(); + arm_wb_dc(); + 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 - cpu_writeback_dc(); - cpu_membarrier(); + arm_wb_dc(); + 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 f4f8481..48bffea 100644 --- a/arm9/source/godmode.c +++ b/arm9/source/godmode.c @@ -19,6 +19,7 @@ #include "power.h" #include "vram0.h" #include "i2c.h" +#include "pxi.h" #ifndef N_PANES #define N_PANES 3 @@ -99,6 +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); BootFirm((FirmHeader*) firm, fixpath); while(1); } diff --git a/arm9/source/start.s b/arm9/source/start.s index 10014d1..12a6f83 100644 --- a/arm9/source/start.s +++ b/arm9/source/start.s @@ -10,9 +10,7 @@ .global _start _start: @ Disable interrupts - mrs r4, cpsr - orr r4, r4, #(SR_IRQ | SR_FIQ) - msr cpsr_c, r4 + msr cpsr_c, #(SR_SVC_MODE | SR_NOINT) @ Preserve boot registers mov r8, r0 @@ -35,9 +33,8 @@ _start: blx r0 @ Invalidate Instruction Cache @ Disable caches / DTCM / MPU - ldr r1, =(CR_ENABLE_MPU | CR_ENABLE_DCACHE | CR_ENABLE_ICACHE | \ - CR_ENABLE_DTCM) - ldr r2, =(CR_ENABLE_ITCM) + ldr r1, =(CR_MPU | CR_DCACHE | CR_ICACHE | CR_DTCM | CR_TCM_LOAD) + ldr r2, =(CR_ITCM) mrc p15, 0, r0, c1, c0, 0 bic r0, r1 orr r0, r2 @@ -73,7 +70,7 @@ _start: @ mov r0, #0x10000000 @ mov r1, #0x340 @ strh r1, [r0, #0x20] - + @ Setup heap ldr r0, =fake_heap_start ldr r1, =__HEAP_ADDR @@ -94,16 +91,15 @@ _start: blo .LXRQ_Install @ Enable caches / DTCM / select low exception vectors - ldr r1, =(CR_ALT_VECTORS | CR_DISABLE_TBIT) - ldr r2, =(CR_ENABLE_MPU | CR_ENABLE_DCACHE | CR_ENABLE_ICACHE | \ - CR_ENABLE_DTCM | CR_CACHE_RROBIN) + ldr r1, =(CR_ALT_VECTORS | CR_V4TLD) + ldr r2, =(CR_MPU | CR_DCACHE | CR_ICACHE | CR_DTCM) mrc p15, 0, r0, c1, c0, 0 bic r0, r1 orr r0, r2 mcr p15, 0, r0, c1, c0, 0 @ Switch to system mode, disable interrupts, setup application stack - msr cpsr_c, #(SR_SYS_MODE | SR_IRQ | SR_FIQ) + msr cpsr_c, #(SR_SYS_MODE | SR_NOINT) ldr sp, =__STACK_TOP @ Check entrypoints @@ -156,9 +152,8 @@ _start: .Lboot_main: - ldr r3, =main mov lr, #0 - bx r3 + ldr pc, =main __mpu_regions: diff --git a/arm9/source/system/bootfirm.s b/arm9/source/system/bootfirm.s index 95d8150..dfcdb6a 100644 --- a/arm9/source/system/bootfirm.s +++ b/arm9/source/system/bootfirm.s @@ -60,16 +60,16 @@ BootFirm_stub: addne r11, #0x30 @ Advance to the next section bne .LBootFirm_stub_copysect - @ Boot state + @ Boot state @ CPSR: @ ARM, Supervisor, IRQ/FIQs disabled @ Flags are undefined - msr cpsr_c, #(SR_SVC_MODE | SR_IRQ | SR_FIQ) + msr cpsr_c, #(SR_SVC_MODE | SR_NOINT) @ CP15: @ MPU and Caches are off @ TCMs are on (location/configuration is undefined) - @ Alternative exception vectors are enabled (0xFFFF0000) + @ High exception vectors are enabled (0xFFFF0000) ldr r3, =WBINV_DC ldr r4, =INV_IC ldr r5, =INITCP15 @@ -79,7 +79,7 @@ BootFirm_stub: @ Registers: @ R0 = 0x1 or 0x2 - @ R1 = 0x23FFFE10 + @ R1 = 0x27FFFE00 @ R2 = 0x0003BEEF @ R3-R14 are undefined diff --git a/arm9/source/system/cache.h b/arm9/source/system/cache.h deleted file mode 100644 index 9978e94..0000000 --- a/arm9/source/system/cache.h +++ /dev/null @@ -1,102 +0,0 @@ -#pragma once - -#include "types.h" - -static inline void -cpu_membarrier(void) { - __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 4\n\t" - :: "r"(0) : "memory"); -} - -static inline void -cpu_invalidate_ic(void) { - __asm__ __volatile__("mcr p15, 0, %0, c7, c5, 0\n\t" - :: "r"(0) : "memory"); -} - -static inline void -cpu_invalidate_ic_range(void *base, u32 len) { - u32 addr = (u32)base & ~0x1F; - len >>= 5; - - do { - __asm__ __volatile__("mcr p15, 0, %0, c7, c5, 1\n\t" - :: "r"(addr) : "memory"); - - addr += 0x20; - } while(len--); -} - -static inline void -cpu_invalidate_dc(void) { - __asm__ __volatile__("mcr p15, 0, %0, c7, c6, 0\n\t" - :: "r"(0) : "memory"); -} - -static inline void -cpu_invalidate_dc_range(void *base, u32 len) { - u32 addr = (u32)base & ~0x1F; - len >>= 5; - - do { - __asm__ __volatile__("mcr p15, 0, %0, c7, c6, 1" - :: "r"(addr) : "memory"); - addr += 0x20; - } while(len--); -} - -static inline void -cpu_writeback_dc(void) { - u32 seg = 0, ind; - do { - ind = 0; - do { - __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 2\n\t" - :: "r"(seg | ind) : "memory"); - - ind += 0x20; - } while(ind < 0x400); - seg += 0x40000000; - } while(seg != 0); -} - -static inline -void cpu_writeback_dc_range(void *base, u32 len) { - u32 addr = (u32)base & ~0x1F; - len >>= 5; - - do { - __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 1" - :: "r"(addr) : "memory"); - - addr += 0x20; - } while(len--); -} - -static inline -void cpu_writeback_invalidate_dc(void) { - u32 seg = 0, ind; - do { - ind = 0; - do { - __asm__ __volatile__("mcr p15, 0, %0, c7, c14, 2\n\t" - :: "r"(seg | ind) : "memory"); - - ind += 0x20; - } while(ind < 0x400); - seg += 0x40000000; - } while(seg != 0); -} - -static inline -void cpu_writeback_invalidate_dc_range(void *base, u32 len) { - u32 addr = (u32)base & ~0x1F; - len >>= 5; - - do { - __asm__ __volatile__("mcr p15, 0, %0, c7, c14, 1" - :: "r"(addr) : "memory"); - - addr += 0x20; - } while(len--); -} diff --git a/arm9/source/system/i2c.c b/arm9/source/system/i2c.c index d7668e5..eadb292 100755 --- a/arm9/source/system/i2c.c +++ b/arm9/source/system/i2c.c @@ -1,6 +1,6 @@ #include "common.h" +#include "arm.h" -#include "cache.h" #include "i2c.h" #include "pxi.h" @@ -24,14 +24,13 @@ bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size) int ret; u32 args[] = {devId, regAddr, (u32)i2c_fcram_buf, size}; - cpu_writeback_dc_range(i2c_fcram_buf, size); - cpu_membarrier(); + arm_wb_dc_range(i2c_fcram_buf, size); + arm_dsb(); ret = PXI_DoCMD(PXI_I2C_READ, args, 4); - cpu_invalidate_dc_range(i2c_fcram_buf, size); + arm_inv_dc_range(i2c_fcram_buf, size); memcpy(out, i2c_fcram_buf, size); - return ret; } @@ -44,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); - cpu_writeback_dc_range(i2c_fcram_buf, size); - cpu_membarrier(); + arm_wb_dc_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 db20b4f..7872887 100644 --- a/arm9/source/system/xrq_handler.s +++ b/arm9/source/system/xrq_handler.s @@ -31,7 +31,7 @@ XRQ_Vectors: b . @ FIQs are unused (except for debug?) XRQ_Reset: - msr cpsr_c, #(SR_ABT_MODE | SR_IRQ | SR_FIQ) + msr cpsr_c, #(SR_ABT_MODE | SR_NOINT) XRQ_FATAL 0 XRQ_Undefined: @@ -63,7 +63,7 @@ XRQ_MainHandler: @ Retrieve banked registers ands r0, r9, #(SR_PMODE_MASK & (0x0F)) orreq r0, #(SR_SYS_MODE) - orr r0, #(0x10 | SR_IRQ | SR_FIQ) + orr r0, #(0x10 | SR_NOINT) msr cpsr_c, r0 @ Switch to previous mode mov r0, sp @@ -71,7 +71,7 @@ XRQ_MainHandler: msr cpsr_c, r10 @ Return to abort add r2, sp, #(13*4) - stmia r2, {r0,r1,r8,r9} + stmia r2, {r0, r1, r8, r9} @ Give read/write access to all the memory regions ldr r0, =0x33333333 @@ -95,7 +95,7 @@ XRQ_MainHandler: mcr p15, 0, r0, c2, c0, 1 @ Inst cacheable 0, 2, 5 @ Enable mpu/caches - ldr r1, =(CR_ENABLE_MPU | CR_ENABLE_DCACHE | CR_ENABLE_ICACHE | CR_ENABLE_DTCM) + ldr r1, =(CR_MPU | CR_DCACHE | CR_ICACHE | CR_DTCM) mrc p15, 0, r0, c1, c0, 0 orr r0, r0, r1 mcr p15, 0, r0, c1, c0, 0 @@ -105,11 +105,11 @@ XRQ_MainHandler: mov r0, r11 blx r2 - msr cpsr, #(SR_SVC_MODE | SR_IRQ | SR_FIQ) + msr cpsr, #(SR_SVC_MODE | SR_NOINT) mov r0, #0 - .LXRQ_WFI: + 1: mcr p15, 0, r0, c7, c0, 4 - b .LXRQ_WFI + b 1b .pool diff --git a/common/arm.h b/common/arm.h index 65122ac..fcdb279 100644 --- a/common/arm.h +++ b/common/arm.h @@ -1,30 +1,302 @@ #pragma once -/* Status Register flags */ -#define SR_USR_MODE (0x10) -#define SR_FIQ_MODE (0x11) -#define SR_IRQ_MODE (0x12) -#define SR_SVC_MODE (0x13) -#define SR_ABT_MODE (0x17) -#define SR_UND_MODE (0x1B) -#define SR_SYS_MODE (0x1F) -#define SR_PMODE_MASK (0x1F) +#include "types.h" -#define SR_THUMB (1<<5) -#define SR_FIQ (1<<6) -#define SR_IRQ (1<<7) -#define SR_NOINT (SR_FIQ | SR_IRQ) +/* Status Register flags */ +#define SR_USR_MODE (0x10) +#define SR_FIQ_MODE (0x11) +#define SR_IRQ_MODE (0x12) +#define SR_SVC_MODE (0x13) +#define SR_ABT_MODE (0x17) +#define SR_UND_MODE (0x1B) +#define SR_SYS_MODE (0x1F) +#define SR_PMODE_MASK (0x1F) + +#define SR_THUMB BIT(5) +#define SR_NOFIQ BIT(6) +#define SR_NOIRQ BIT(7) +#define SR_NOINT (SR_NOFIQ | SR_NOIRQ) #ifdef ARM9 -#define CR_ENABLE_MPU (1<<0) -#define CR_ENABLE_BIGEND (1<<7) -#define CR_ENABLE_DCACHE (1<<2) -#define CR_ENABLE_ICACHE (1<<12) -#define CR_ENABLE_DTCM (1<<16) -#define CR_ENABLE_ITCM (1<<18) -#define CR_ALT_VECTORS (1<<13) -#define CR_CACHE_RROBIN (1<<14) -#define CR_DISABLE_TBIT (1<<15) -#define CR_DTCM_LMODE (1<<17) -#define CR_ITCM_LMODE (1<<19) + #define CR_MPU BIT(0) + #define CR_DCACHE BIT(2) + #define CR_ICACHE BIT(12) + #define CR_DTCM BIT(16) + #define CR_ITCM BIT(18) + #define CR_V4TLD BIT(15) + + #define CR_ALT_VECTORS BIT(13) + #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 ICACHE_SZ (4096) + #define DCACHE_SZ (4096) +#else // ARM11 + #define CR_MMU BIT(0) + #define CR_ALIGN BIT(1) + #define CR_DCACHE BIT(2) + #define CR_ICACHE BIT(12) + #define CR_FLOWPRED BIT(11) + #define CR_HIGHVEC BIT(13) + #define CR_V4TLD BIT(15) + #define CR_UNALIGN BIT(22) + #define CR_DSUBPAGE BIT(23) + + #define ACR_RETSTK BIT(0) + #define ACR_DBPRED BIT(1) + #define ACR_SBPRED BIT(2) + #define ACR_FOLDING BIT(3) + #define ACR_EXCL BIT(4) + #define ACR_SMP BIT(5) + + #define ICACHE_SZ (16384) + #define DCACHE_SZ (16384) #endif + + +#ifndef __ASSEMBLER__ + +/* ARM Private Memory Region */ +#ifdef ARM11 + #define REG_ARM_PMR(off, type) ((volatile type*)(0x17E00000 + (off))) +#endif + + +#define ARM_MCR(cp, op1, reg, crn, crm, op2) asm_v( \ + "MCR " #cp ", " #op1 ", %[R], " #crn ", " #crm ", " #op2 "\n\t" \ + :: [R] "r"(reg)) + +#define ARM_MRC(cp, op1, reg, crn, crm, op2) asm_v( \ + "MRC " #cp ", " #op1 ", %[R], " #crn ", " #crm ", " #op2 "\n\t" \ + : [R] "=r"(reg)) + +#define ARM_MSR(cp, reg) asm_v( \ + "MSR " #cp ", %[R]\n\t" \ + :: [R] "r"(reg)) + +#define ARM_MRS(reg, cp) asm_v( \ + "MRS %[R], " #cp "\n\t" \ + : [R] "=r"(reg)) + +#ifdef ARM11 + #define ARM_CPS(m) asm_v("CPS " #m) + #define ARM_CPSID(m) asm_v("CPSID " #m) + #define ARM_CPSIE(m) asm_v("CPSIE " #m) + + /* + * An Instruction Synchronization Barrier (ISB) flushes the pipeline in the processor + * 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) { + ARM_MCR(p15, 0, 0, c7, c5, 4); + } + + /* + * 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) { + ARM_MCR(p15, 0, 0, c7, c10, 5); + } + + /* Wait For Interrupt */ + static inline void arm_wfi(void) { + asm_v("wfi\n\t"); + } + + /* Wait For Event */ + static inline void arm_wfe(void) { + asm_v("wfe\n\t"); + } + + /* Send Event */ + static inline void arm_sev(void) { + asm_v("sev\n\t"); + } + + /* Auxiliary Control Registers */ + static inline u32 arm_acr_get(void) { + u32 acr; + ARM_MRC(p15, 0, acr, c1, c0, 1); + return acr; + } + + static inline void arm_acr_set(u32 acr) { + ARM_MCR(p15, 0, acr, c1, c0, 1); + } +#endif + + +/* + * A Data Synchronization Barrier (DSB) completes when all + * instructions before this instruction complete. + */ +static inline void arm_dsb(void) { + ARM_MCR(p15, 0, 0, c7, c10, 4); +} + + +/* Control Registers */ +static inline u32 arm_cr_get(void) { + u32 cr; + ARM_MRC(p15, 0, cr, c1, c0, 0); + return cr; +} + +static inline void arm_cr_set(u32 cr) { + ARM_MCR(p15, 0, cr, c1, c0, 0); +} + +/* Thread ID Registers */ +static inline u32 arm_tid_get(void) { + u32 pid; + #ifdef ARM9 + ARM_MRC(p15, 0, pid, c13, c0, 1); + #else + ARM_MRC(p15, 0, pid, c13, c0, 4); + #endif + return pid; +} + +static inline void arm_tid_set(u32 pid) { + #ifdef ARM9 + ARM_MCR(p15, 0, pid, c13, c0, 1); + #else + ARM_MCR(p15, 0, pid, c13, c0, 4); + #endif +} + +/* CPU ID */ +static inline u32 arm_cpuid(void) { + u32 id; + #ifdef ARM9 + id = 0; + #else + ARM_MRC(p15, 0, id, c0, c0, 5); + #endif + return id & 3; +} + +/* Status Register */ +static inline u32 arm_cpsr_get(void) { + u32 cpsr; + ARM_MRS(cpsr, "cpsr"); + return cpsr; +} + +static inline void arm_cpsr_c_set(u32 cpsr) { + ARM_MSR("cpsr_c", cpsr); +} + +static inline void arm_disable_ints(void) { + #ifdef ARM9 + arm_cpsr_c_set(arm_cpsr_get() | SR_NOINT); + #else + ARM_CPSID(if); + #endif +} + +static inline void arm_enable_ints(void) { + #ifdef ARM9 + arm_cpsr_c_set(arm_cpsr_get() & ~SR_NOINT); + #else + ARM_CPSIE(if); + #endif +} + +static inline u32 arm_enter_critical(void) { + u32 stat = arm_cpsr_get(); + arm_disable_ints(); + return stat & SR_NOINT; +} + +static inline void arm_leave_critical(u32 stat) { + arm_cpsr_c_set((arm_cpsr_get() & ~SR_NOINT) | stat); +} + + +/* Cache functions */ +static inline void arm_inv_ic(void) { + ARM_MCR(p15, 0, 0, c7, c5, 0); +} + +static inline void arm_inv_ic_range(void *base, u32 len) { + u32 addr = (u32)base & ~0x1F; + len >>= 5; + + do { + ARM_MCR(p15, 0, addr, c7, c5, 1); + addr += 0x20; + } while(len--); +} + +static inline void arm_inv_dc(void) { + ARM_MCR(p15, 0, 0, c7, c6, 0); +} + +static inline void arm_inv_dc_range(void *base, u32 len) { + u32 addr = (u32)base & ~0x1F; + len >>= 5; + + do { + ARM_MCR(p15, 0, addr, c7, c6, 1); + addr += 0x20; + } while(len--); +} + +static inline void arm_wb_dc(void) { + #ifdef ARM9 + u32 seg = 0, ind; + do { + ind = 0; + do { + ARM_MCR(p15, 0, seg | ind, c7, c10, 2); + ind += 0x20; + } while(ind < 0x400); + seg += 0x40000000; + } while(seg != 0); + #else + ARM_MCR(p15, 0, 0, c7, c10, 0); + #endif +} + +static inline void arm_wb_dc_range(void *base, u32 len) { + u32 addr = (u32)base & ~0x1F; + len >>= 5; + + do { + ARM_MCR(p15, 0, addr, c7, c10, 1); + addr += 0x20; + } while(len--); +} + +static inline void arm_wb_inv_dc(void) { + #ifdef ARM9 + u32 seg = 0, ind; + do { + ind = 0; + do { + ARM_MCR(p15, 0, seg | ind, c7, c14, 2); + ind += 0x20; + } while(ind < 0x400); + seg += 0x40000000; + } while(seg != 0); + #else + ARM_MCR(p15, 0, 0, c7, c14, 0); + #endif +} + +static inline void arm_wb_inv_dc_range(void *base, u32 len) { + u32 addr = (u32)base & ~0x1F; + len >>= 5; + + do { + ARM_MCR(p15, 0, addr, c7, c14, 1); + addr += 0x20; + } while(len--); +} + +#endif // __ASSEMBLER__ diff --git a/common/cpu.h b/common/cpu.h deleted file mode 100644 index a8f73b4..0000000 --- a/common/cpu.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - Written by Wolfvak, specially sublicensed under the GPLv2 - Read LICENSE for more details -*/ - -#pragma once -#include - -#define asm __asm volatile - -static inline u32 CPU_ReadCPSR(void) -{ - u32 cpsr; - asm("mrs %0, cpsr\n\t":"=r"(cpsr)); - return cpsr; -} - -static inline void CPU_WriteCPSR_c(u32 cpsr) -{ - asm("msr cpsr_c, %0\n\t"::"r"(cpsr)); - return; -} - -static inline u32 CPU_ReadCR(void) -{ - u32 cr; - asm("mrc p15, 0, %0, c1, c0, 0\n\t":"=r"(cr)); - return cr; -} - -static inline void CPU_WriteCR(u32 cr) -{ - asm("mcr p15, 0, %0, c1, c0, 0\n\t"::"r"(cr)); - return; -} - -static inline void CPU_DisableIRQ(void) -{ - #ifdef ARM9 - CPU_WriteCPSR_c(CPU_ReadCPSR() | (SR_IRQ | SR_FIQ)); - #else - asm("cpsid if\n\t"); - #endif - return; -} - -static inline void CPU_EnableIRQ(void) -{ - #ifdef ARM9 - CPU_WriteCPSR_c(CPU_ReadCPSR() & ~(SR_IRQ | SR_FIQ)); - #else - asm("cpsie if\n\t"); - #endif - return; -} - -static inline void CPU_EnterCritical(u32 *ss) -{ - *ss = CPU_ReadCPSR(); - CPU_DisableIRQ(); - return; -} - -static inline void CPU_LeaveCritical(u32 *ss) -{ - CPU_WriteCPSR_c(*ss); - return; -} diff --git a/common/pxi.h b/common/pxi.h index 17cb81a..0aa0b7a 100644 --- a/common/pxi.h +++ b/common/pxi.h @@ -8,20 +8,18 @@ #ifdef ARM9 #define PXI_BASE (0x10008000) -#define PXI_INIT_SYNC_SET (33) -#define PXI_INIT_SYNC_WAIT (66) +#define IRQ_PXI_RX (14) #else #define PXI_BASE (0x10163000) -#define IRQ_PXI_RX (83) -#define PXI_INIT_SYNC_SET (66) -#define PXI_INIT_SYNC_WAIT (33) +#define IRQ_PXI_RX (83) #endif enum { - PXI_SCREENINIT = 0, - PXI_BRIGHTNESS, - PXI_I2C_READ, - PXI_I2C_WRITE, + PXI_SCREENINIT = 0, + PXI_BRIGHTNESS, + PXI_I2C_READ, + PXI_I2C_WRITE, + PXI_LEGACY_BOOT, }; #define PXI_FIFO_LEN (16) @@ -49,55 +47,55 @@ enum { static inline void PXI_SetRemote(u8 msg) { - *PXI_SYNC_SEND = msg; + *PXI_SYNC_SEND = msg; } static inline u8 PXI_GetRemote(void) { - return *PXI_SYNC_RECV; + return *PXI_SYNC_RECV; } static inline void PXI_WaitRemote(u8 msg) { - while(PXI_GetRemote() != msg); + while(PXI_GetRemote() != msg); } static void PXI_Reset(void) { - *PXI_SYNC_IRQ = 0; - *PXI_CNT = PXI_CNT_SEND_FIFO_FLUSH | PXI_CNT_ENABLE_FIFO; - for (int i = 0; i < PXI_FIFO_LEN; i++) - *PXI_RECV; + *PXI_SYNC_IRQ = 0; + *PXI_CNT = PXI_CNT_SEND_FIFO_FLUSH | PXI_CNT_ENABLE_FIFO; + for (int i = 0; i < PXI_FIFO_LEN; i++) + *PXI_RECV; - *PXI_CNT = 0; - *PXI_CNT = PXI_CNT_RECV_FIFO_AVAIL_IRQ | PXI_CNT_ENABLE_FIFO; + *PXI_CNT = 0; + *PXI_CNT = PXI_CNT_RECV_FIFO_AVAIL_IRQ | PXI_CNT_ENABLE_FIFO; } static void PXI_Send(u32 w) { - while(*PXI_CNT & PXI_CNT_SEND_FIFO_FULL); - *PXI_SEND = w; + while(*PXI_CNT & PXI_CNT_SEND_FIFO_FULL); + *PXI_SEND = w; } static u32 PXI_Recv(void) { - while(*PXI_CNT & PXI_CNT_RECV_FIFO_EMPTY); - return *PXI_RECV; + while(*PXI_CNT & PXI_CNT_RECV_FIFO_EMPTY); + return *PXI_RECV; } static void PXI_SendArray(const u32 *w, u32 c) { - while(c--) PXI_Send(*(w++)); + while(c--) PXI_Send(*(w++)); } static void PXI_RecvArray(u32 *w, u32 c) { - while(c--) *(w++) = PXI_Recv(); + while(c--) *(w++) = PXI_Recv(); } static u32 PXI_DoCMD(u32 cmd, const u32 *args, u32 argc) { - PXI_Send(cmd); - PXI_SendArray(args, argc); - return PXI_Recv(); + PXI_Send((argc << 16) | cmd); + PXI_SendArray(args, argc); + return PXI_Recv(); } diff --git a/common/types.h b/common/types.h index 03cf23a..d36fc73 100644 --- a/common/types.h +++ b/common/types.h @@ -6,10 +6,13 @@ #endif #endif +#define BIT(x) (1 << (x)) + +#ifndef __ASSEMBLER__ #include #include -#define BIT(x) (1<<(x)) +#define asm_v asm __volatile__ typedef uint8_t u8; typedef uint16_t u16; @@ -30,3 +33,4 @@ typedef volatile s8 vs8; typedef volatile s16 vs16; typedef volatile s32 vs32; typedef volatile s64 vs64; +#endif