mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 13:42:47 +00:00
- 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:
parent
987b820c4a
commit
e70b8ab116
@ -1,9 +1,6 @@
|
||||
#include <types.h>
|
||||
#include <cpu.h>
|
||||
#include <gic.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#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++) {
|
||||
|
@ -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:
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <cpu.h>
|
||||
#include <arm.h>
|
||||
#include <pxi.h>
|
||||
#include <gic.h>
|
||||
#include <gpulcd.h>
|
||||
@ -7,107 +7,124 @@
|
||||
|
||||
#include <i2c.h>
|
||||
|
||||
#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:
|
||||
{
|
||||
<var declarations/assignments>
|
||||
<receive args from PXI FIFO>
|
||||
<execute the command>
|
||||
<set the return value>
|
||||
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:
|
||||
{
|
||||
<var declarations/assignments>
|
||||
<execute the command>
|
||||
<set the return value>
|
||||
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))();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
@ -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:
|
||||
|
@ -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
|
||||
|
||||
|
@ -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--);
|
||||
}
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
320
common/arm.h
320
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__
|
||||
|
68
common/cpu.h
68
common/cpu.h
@ -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;
|
||||
}
|
52
common/pxi.h
52
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();
|
||||
}
|
||||
|
@ -6,10 +6,13 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define BIT(x) (1 << (x))
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#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
|
||||
|
Loading…
x
Reference in New Issue
Block a user