- unified CPU/cache header that works on C and asm code

- added legacy boot PXI command that allows power savings on ARM11
This commit is contained in:
Wolfvak 2019-04-09 09:33:52 -03:00 committed by d0k3
parent 987b820c4a
commit e70b8ab116
14 changed files with 459 additions and 344 deletions

View File

@ -1,9 +1,6 @@
#include <types.h> #include <types.h>
#include <cpu.h>
#include <gic.h> #include <gic.h>
#include <string.h>
#define IRQVECTOR_BASE ((vu32*)0x1FFFFFA0) #define IRQVECTOR_BASE ((vu32*)0x1FFFFFA0)
extern void (*main_irq_handler)(void); extern void (*main_irq_handler)(void);
@ -14,7 +11,8 @@ void GIC_Reset(void)
u32 irq_s; u32 irq_s;
REG_GIC_CONTROL = 0; 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; REG_DIC_CONTROL = 0;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {

View File

@ -11,8 +11,8 @@
.type main_irq_handler, %function .type main_irq_handler, %function
main_irq_handler: main_irq_handler:
sub lr, lr, #4 @ Fix return address sub lr, lr, #4 @ Fix return address
srsfd sp!, #0x13 @ Store IRQ mode LR and SPSR on the SVC stack srsfd sp!, #SR_SVC_MODE @ Store IRQ mode LR and SPSR on the SVC stack
cps #0x13 @ Switch to SVC mode cps #SR_SVC_MODE @ Switch to SVC mode
push {r0-r3, r12, lr} @ Preserve registers push {r0-r3, r12, lr} @ Preserve registers
1: 1:

View File

@ -1,4 +1,4 @@
#include <cpu.h> #include <arm.h>
#include <pxi.h> #include <pxi.h>
#include <gic.h> #include <gic.h>
#include <gpulcd.h> #include <gpulcd.h>
@ -10,15 +10,25 @@
#define CFG11_MPCORE_CLKCNT ((vu16*)(0x10141300)) #define CFG11_MPCORE_CLKCNT ((vu16*)(0x10141300))
#define CFG11_SOCINFO ((vu16*)(0x10140FFC)) #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) void PXI_RX_Handler(void)
{ {
u32 pxi_cmd, ret; u32 ret, msg, cmd, argc, args[PXI_FIFO_LEN];
u32 pxi_args[PXI_FIFO_LEN];
pxi_cmd = PXI_Recv(); msg = PXI_Recv();
switch (pxi_cmd) { cmd = msg & 0xFFFF;
argc = msg >> 16;
if (argc > PXI_FIFO_LEN) {
PXI_Send(0xFFFFFFFF);
return;
}
PXI_RecvArray(args, argc);
switch (cmd) {
case PXI_SCREENINIT: case PXI_SCREENINIT:
{ {
GPU_Init(); GPU_Init();
@ -35,26 +45,28 @@ void PXI_RX_Handler(void)
case PXI_BRIGHTNESS: case PXI_BRIGHTNESS:
{ {
PXI_RecvArray(pxi_args, 1); LCD_SetBrightness(0, args[0]);
LCD_SetBrightness(0, pxi_args[0]); LCD_SetBrightness(1, args[0]);
LCD_SetBrightness(1, pxi_args[0]); ret = args[0];
ret = pxi_args[0];
break; break;
} }
case PXI_I2C_READ: case PXI_I2C_READ:
{ {
PXI_RecvArray(pxi_args, 4); ret = I2C_readRegBuf(args[0], args[1], (u8*)args[2], args[3]);
ret = I2C_readRegBuf(pxi_args[0], pxi_args[1],
(u8*)pxi_args[2], pxi_args[3]);
break; break;
} }
case PXI_I2C_WRITE: case PXI_I2C_WRITE:
{ {
PXI_RecvArray(pxi_args, 4); ret = I2C_writeRegBuf(args[0], args[1], (u8*)args[2], args[3]);
ret = I2C_writeRegBuf(pxi_args[0], pxi_args[1], break;
(const u8*)pxi_args[2], pxi_args[3]); }
case PXI_LEGACY_BOOT:
{
*LEGACY_BOOT_ENTRY = LEGACY_BOOT_MAGIC;
ret = 0;
break; break;
} }
@ -62,7 +74,6 @@ void PXI_RX_Handler(void)
case CMD_ID: case CMD_ID:
{ {
<var declarations/assignments> <var declarations/assignments>
<receive args from PXI FIFO>
<execute the command> <execute the command>
<set the return value> <set the return value>
break; break;
@ -85,12 +96,12 @@ void main(void)
if ((*CFG11_SOCINFO & 2) && (!(*CFG11_MPCORE_CLKCNT & 1))) { if ((*CFG11_SOCINFO & 2) && (!(*CFG11_MPCORE_CLKCNT & 1))) {
GIC_Reset(); GIC_Reset();
GIC_SetIRQ(88, NULL); GIC_SetIRQ(88, NULL);
CPU_EnableIRQ(); arm_enable_ints();
*CFG11_MPCORE_CLKCNT = 0x8001; *CFG11_MPCORE_CLKCNT = 0x8001;
do { do {
asm("wfi\n\t"); asm("wfi\n\t");
} while(!(*CFG11_MPCORE_CLKCNT & 0x8000)); } while(!(*CFG11_MPCORE_CLKCNT & 0x8000));
CPU_DisableIRQ(); arm_disable_ints();
} }
GIC_Reset(); GIC_Reset();
@ -100,14 +111,20 @@ void main(void)
//MCU_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; do {
while((entry=*entrypoint) == 0); arm_wfi();
} while(*LEGACY_BOOT_ENTRY != LEGACY_BOOT_MAGIC);
CPU_DisableIRQ(); arm_disable_ints();
GIC_Reset(); GIC_Reset();
do {
entry = *LEGACY_BOOT_ENTRY;
} while(entry == LEGACY_BOOT_MAGIC);
((void (*)())(entry))(); ((void (*)())(entry))();
} }

View File

@ -1,6 +1,6 @@
#include "arm.h"
#include "power.h" #include "power.h"
#include "i2c.h" #include "i2c.h"
#include "cache.h"
#include "pxi.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}; 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() { void Reboot() {
I2C_writeReg(I2C_DEV_MCU, 0x22, 1 << 0); // poweroff LCD to prevent MCU hangs I2C_writeReg(I2C_DEV_MCU, 0x22, 1 << 0); // poweroff LCD to prevent MCU hangs
cpu_writeback_dc(); arm_wb_dc();
cpu_membarrier(); arm_dsb();
I2C_writeReg(I2C_DEV_MCU, 0x20, 1 << 2); I2C_writeReg(I2C_DEV_MCU, 0x20, 1 << 2);
while(true); while(true);
} }
@ -44,8 +44,8 @@ void Reboot() {
void PowerOff() void PowerOff()
{ {
I2C_writeReg(I2C_DEV_MCU, 0x22, 1 << 0); // poweroff LCD to prevent MCU hangs I2C_writeReg(I2C_DEV_MCU, 0x22, 1 << 0); // poweroff LCD to prevent MCU hangs
cpu_writeback_dc(); arm_wb_dc();
cpu_membarrier(); arm_dsb();
I2C_writeReg(I2C_DEV_MCU, 0x20, 1 << 0); I2C_writeReg(I2C_DEV_MCU, 0x20, 1 << 0);
while(true); while(true);
} }

View File

@ -19,6 +19,7 @@
#include "power.h" #include "power.h"
#include "vram0.h" #include "vram0.h"
#include "i2c.h" #include "i2c.h"
#include "pxi.h"
#ifndef N_PANES #ifndef N_PANES
#define N_PANES 3 #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) // boot the FIRM (if we got a proper fixpath)
if (*fixpath) { if (*fixpath) {
if (delete) PathDelete(bootpath); if (delete) PathDelete(bootpath);
PXI_DoCMD(PXI_LEGACY_BOOT, NULL, 0);
BootFirm((FirmHeader*) firm, fixpath); BootFirm((FirmHeader*) firm, fixpath);
while(1); while(1);
} }

View File

@ -10,9 +10,7 @@
.global _start .global _start
_start: _start:
@ Disable interrupts @ Disable interrupts
mrs r4, cpsr msr cpsr_c, #(SR_SVC_MODE | SR_NOINT)
orr r4, r4, #(SR_IRQ | SR_FIQ)
msr cpsr_c, r4
@ Preserve boot registers @ Preserve boot registers
mov r8, r0 mov r8, r0
@ -35,9 +33,8 @@ _start:
blx r0 @ Invalidate Instruction Cache blx r0 @ Invalidate Instruction Cache
@ Disable caches / DTCM / MPU @ Disable caches / DTCM / MPU
ldr r1, =(CR_ENABLE_MPU | CR_ENABLE_DCACHE | CR_ENABLE_ICACHE | \ ldr r1, =(CR_MPU | CR_DCACHE | CR_ICACHE | CR_DTCM | CR_TCM_LOAD)
CR_ENABLE_DTCM) ldr r2, =(CR_ITCM)
ldr r2, =(CR_ENABLE_ITCM)
mrc p15, 0, r0, c1, c0, 0 mrc p15, 0, r0, c1, c0, 0
bic r0, r1 bic r0, r1
orr r0, r2 orr r0, r2
@ -94,16 +91,15 @@ _start:
blo .LXRQ_Install blo .LXRQ_Install
@ Enable caches / DTCM / select low exception vectors @ Enable caches / DTCM / select low exception vectors
ldr r1, =(CR_ALT_VECTORS | CR_DISABLE_TBIT) ldr r1, =(CR_ALT_VECTORS | CR_V4TLD)
ldr r2, =(CR_ENABLE_MPU | CR_ENABLE_DCACHE | CR_ENABLE_ICACHE | \ ldr r2, =(CR_MPU | CR_DCACHE | CR_ICACHE | CR_DTCM)
CR_ENABLE_DTCM | CR_CACHE_RROBIN)
mrc p15, 0, r0, c1, c0, 0 mrc p15, 0, r0, c1, c0, 0
bic r0, r1 bic r0, r1
orr r0, r2 orr r0, r2
mcr p15, 0, r0, c1, c0, 0 mcr p15, 0, r0, c1, c0, 0
@ Switch to system mode, disable interrupts, setup application stack @ 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 ldr sp, =__STACK_TOP
@ Check entrypoints @ Check entrypoints
@ -156,9 +152,8 @@ _start:
.Lboot_main: .Lboot_main:
ldr r3, =main
mov lr, #0 mov lr, #0
bx r3 ldr pc, =main
__mpu_regions: __mpu_regions:

View File

@ -64,12 +64,12 @@ BootFirm_stub:
@ CPSR: @ CPSR:
@ ARM, Supervisor, IRQ/FIQs disabled @ ARM, Supervisor, IRQ/FIQs disabled
@ Flags are undefined @ Flags are undefined
msr cpsr_c, #(SR_SVC_MODE | SR_IRQ | SR_FIQ) msr cpsr_c, #(SR_SVC_MODE | SR_NOINT)
@ CP15: @ CP15:
@ MPU and Caches are off @ MPU and Caches are off
@ TCMs are on (location/configuration is undefined) @ TCMs are on (location/configuration is undefined)
@ Alternative exception vectors are enabled (0xFFFF0000) @ High exception vectors are enabled (0xFFFF0000)
ldr r3, =WBINV_DC ldr r3, =WBINV_DC
ldr r4, =INV_IC ldr r4, =INV_IC
ldr r5, =INITCP15 ldr r5, =INITCP15
@ -79,7 +79,7 @@ BootFirm_stub:
@ Registers: @ Registers:
@ R0 = 0x1 or 0x2 @ R0 = 0x1 or 0x2
@ R1 = 0x23FFFE10 @ R1 = 0x27FFFE00
@ R2 = 0x0003BEEF @ R2 = 0x0003BEEF
@ R3-R14 are undefined @ R3-R14 are undefined

View File

@ -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--);
}

View File

@ -1,6 +1,6 @@
#include "common.h" #include "common.h"
#include "arm.h"
#include "cache.h"
#include "i2c.h" #include "i2c.h"
#include "pxi.h" #include "pxi.h"
@ -24,14 +24,13 @@ bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size)
int ret; int ret;
u32 args[] = {devId, regAddr, (u32)i2c_fcram_buf, size}; u32 args[] = {devId, regAddr, (u32)i2c_fcram_buf, size};
cpu_writeback_dc_range(i2c_fcram_buf, size); arm_wb_dc_range(i2c_fcram_buf, size);
cpu_membarrier(); arm_dsb();
ret = PXI_DoCMD(PXI_I2C_READ, args, 4); 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); memcpy(out, i2c_fcram_buf, size);
return ret; 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}; u32 args[] = {devId, regAddr, (u32)i2c_fcram_buf, size};
memcpy(i2c_fcram_buf, in, size); memcpy(i2c_fcram_buf, in, size);
cpu_writeback_dc_range(i2c_fcram_buf, size); arm_wb_dc_range(i2c_fcram_buf, size);
cpu_membarrier(); arm_dsb();
ret = PXI_DoCMD(PXI_I2C_WRITE, args, 4); ret = PXI_DoCMD(PXI_I2C_WRITE, args, 4);
return ret; return ret;

View File

@ -31,7 +31,7 @@ XRQ_Vectors:
b . @ FIQs are unused (except for debug?) b . @ FIQs are unused (except for debug?)
XRQ_Reset: XRQ_Reset:
msr cpsr_c, #(SR_ABT_MODE | SR_IRQ | SR_FIQ) msr cpsr_c, #(SR_ABT_MODE | SR_NOINT)
XRQ_FATAL 0 XRQ_FATAL 0
XRQ_Undefined: XRQ_Undefined:
@ -63,7 +63,7 @@ XRQ_MainHandler:
@ Retrieve banked registers @ Retrieve banked registers
ands r0, r9, #(SR_PMODE_MASK & (0x0F)) ands r0, r9, #(SR_PMODE_MASK & (0x0F))
orreq r0, #(SR_SYS_MODE) 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 msr cpsr_c, r0 @ Switch to previous mode
mov r0, sp mov r0, sp
@ -95,7 +95,7 @@ XRQ_MainHandler:
mcr p15, 0, r0, c2, c0, 1 @ Inst cacheable 0, 2, 5 mcr p15, 0, r0, c2, c0, 1 @ Inst cacheable 0, 2, 5
@ Enable mpu/caches @ 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 mrc p15, 0, r0, c1, c0, 0
orr r0, r0, r1 orr r0, r0, r1
mcr p15, 0, r0, c1, c0, 0 mcr p15, 0, r0, c1, c0, 0
@ -105,11 +105,11 @@ XRQ_MainHandler:
mov r0, r11 mov r0, r11
blx r2 blx r2
msr cpsr, #(SR_SVC_MODE | SR_IRQ | SR_FIQ) msr cpsr, #(SR_SVC_MODE | SR_NOINT)
mov r0, #0 mov r0, #0
.LXRQ_WFI: 1:
mcr p15, 0, r0, c7, c0, 4 mcr p15, 0, r0, c7, c0, 4
b .LXRQ_WFI b 1b
.pool .pool

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include "types.h"
/* Status Register flags */ /* Status Register flags */
#define SR_USR_MODE (0x10) #define SR_USR_MODE (0x10)
#define SR_FIQ_MODE (0x11) #define SR_FIQ_MODE (0x11)
@ -10,21 +12,291 @@
#define SR_SYS_MODE (0x1F) #define SR_SYS_MODE (0x1F)
#define SR_PMODE_MASK (0x1F) #define SR_PMODE_MASK (0x1F)
#define SR_THUMB (1<<5) #define SR_THUMB BIT(5)
#define SR_FIQ (1<<6) #define SR_NOFIQ BIT(6)
#define SR_IRQ (1<<7) #define SR_NOIRQ BIT(7)
#define SR_NOINT (SR_FIQ | SR_IRQ) #define SR_NOINT (SR_NOFIQ | SR_NOIRQ)
#ifdef ARM9 #ifdef ARM9
#define CR_ENABLE_MPU (1<<0) #define CR_MPU BIT(0)
#define CR_ENABLE_BIGEND (1<<7) #define CR_DCACHE BIT(2)
#define CR_ENABLE_DCACHE (1<<2) #define CR_ICACHE BIT(12)
#define CR_ENABLE_ICACHE (1<<12) #define CR_DTCM BIT(16)
#define CR_ENABLE_DTCM (1<<16) #define CR_ITCM BIT(18)
#define CR_ENABLE_ITCM (1<<18) #define CR_V4TLD BIT(15)
#define CR_ALT_VECTORS (1<<13)
#define CR_CACHE_RROBIN (1<<14) #define CR_ALT_VECTORS BIT(13)
#define CR_DISABLE_TBIT (1<<15) #define CR_CACHE_RROBIN BIT(14)
#define CR_DTCM_LMODE (1<<17) #define CR_DTCM_LOAD BIT(17)
#define CR_ITCM_LMODE (1<<19) #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 #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__

View File

@ -1,68 +0,0 @@
/*
Written by Wolfvak, specially sublicensed under the GPLv2
Read LICENSE for more details
*/
#pragma once
#include <types.h>
#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;
}

View File

@ -8,13 +8,10 @@
#ifdef ARM9 #ifdef ARM9
#define PXI_BASE (0x10008000) #define PXI_BASE (0x10008000)
#define PXI_INIT_SYNC_SET (33) #define IRQ_PXI_RX (14)
#define PXI_INIT_SYNC_WAIT (66)
#else #else
#define PXI_BASE (0x10163000) #define PXI_BASE (0x10163000)
#define IRQ_PXI_RX (83) #define IRQ_PXI_RX (83)
#define PXI_INIT_SYNC_SET (66)
#define PXI_INIT_SYNC_WAIT (33)
#endif #endif
enum { enum {
@ -22,6 +19,7 @@ enum {
PXI_BRIGHTNESS, PXI_BRIGHTNESS,
PXI_I2C_READ, PXI_I2C_READ,
PXI_I2C_WRITE, PXI_I2C_WRITE,
PXI_LEGACY_BOOT,
}; };
#define PXI_FIFO_LEN (16) #define PXI_FIFO_LEN (16)
@ -97,7 +95,7 @@ static void PXI_RecvArray(u32 *w, u32 c)
static u32 PXI_DoCMD(u32 cmd, const u32 *args, u32 argc) static u32 PXI_DoCMD(u32 cmd, const u32 *args, u32 argc)
{ {
PXI_Send(cmd); PXI_Send((argc << 16) | cmd);
PXI_SendArray(args, argc); PXI_SendArray(args, argc);
return PXI_Recv(); return PXI_Recv();
} }

View File

@ -6,10 +6,13 @@
#endif #endif
#endif #endif
#define BIT(x) (1 << (x))
#ifndef __ASSEMBLER__
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#define BIT(x) (1<<(x)) #define asm_v asm __volatile__
typedef uint8_t u8; typedef uint8_t u8;
typedef uint16_t u16; typedef uint16_t u16;
@ -30,3 +33,4 @@ typedef volatile s8 vs8;
typedef volatile s16 vs16; typedef volatile s16 vs16;
typedef volatile s32 vs32; typedef volatile s32 vs32;
typedef volatile s64 vs64; typedef volatile s64 vs64;
#endif