forked from Mirror/GodMode9
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
This commit is contained in:
parent
e70b8ab116
commit
2f86686388
@ -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);
|
||||
}
|
||||
|
204
arm11/source/arm/gic.c
Normal file
204
arm11/source/arm/gic.c
Normal file
@ -0,0 +1,204 @@
|
||||
#include <types.h>
|
||||
#include <arm.h>
|
||||
|
||||
#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;
|
||||
}
|
26
arm11/source/arm/gic.h
Normal file
26
arm11/source/arm/gic.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
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);
|
28
arm11/source/arm/mmu.c
Executable file
28
arm11/source/arm/mmu.c
Executable file
@ -0,0 +1,28 @@
|
||||
#include <types.h>
|
||||
#include <arm.h>
|
||||
|
||||
#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);
|
||||
}
|
6
arm11/source/arm/mmu.h
Executable file
6
arm11/source/arm/mmu.h
Executable file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <types.h>
|
||||
|
||||
void MMU_PopulateTranslationTable(void);
|
||||
void MMU_Init(void);
|
14
arm11/source/arm/scu.c
Executable file
14
arm11/source/arm/scu.c
Executable file
@ -0,0 +1,14 @@
|
||||
#include <types.h>
|
||||
#include <arm.h>
|
||||
|
||||
#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;
|
||||
}
|
5
arm11/source/arm/scu.h
Executable file
5
arm11/source/arm/scu.h
Executable file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <types.h>
|
||||
|
||||
void SCU_Init(void);
|
26
arm11/source/arm/vectors.s
Normal file
26
arm11/source/arm/vectors.s
Normal file
@ -0,0 +1,26 @@
|
||||
#include <arm.h>
|
||||
|
||||
.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
|
@ -3,26 +3,48 @@
|
||||
|
||||
#include <arm.h>
|
||||
|
||||
#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)
|
||||
|
@ -1,49 +0,0 @@
|
||||
#include <types.h>
|
||||
#include <gic.h>
|
||||
|
||||
#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;
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
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);
|
@ -1,184 +0,0 @@
|
||||
#include <vram.h>
|
||||
#include <gpulcd.h>
|
||||
#include <types.h>
|
||||
|
||||
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;
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
#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();
|
203
arm11/source/hw/gpulcd.c
Normal file
203
arm11/source/hw/gpulcd.c
Normal file
@ -0,0 +1,203 @@
|
||||
#include <types.h>
|
||||
#include <vram.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
16
arm11/source/hw/gpulcd.h
Normal file
16
arm11/source/hw/gpulcd.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
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();
|
@ -17,8 +17,9 @@
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "types.h"
|
||||
#include "i2c.h"
|
||||
|
||||
#include <types.h>
|
||||
#include "hw/i2c.h"
|
||||
|
||||
|
||||
#define I2C1_REGS_BASE (0x10161000)
|
@ -19,7 +19,7 @@
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "types.h"
|
||||
#include <types.h>
|
||||
|
||||
|
||||
#define I2C_STOP (1u)
|
@ -1,46 +0,0 @@
|
||||
.section .text
|
||||
.arm
|
||||
|
||||
#include <arm.h>
|
||||
|
||||
#define MPCORE_PMR (0x17E00000)
|
||||
#define IRQ_SPURIOUS (1023)
|
||||
#define IRQ_COUNT (128)
|
||||
|
||||
.global main_irq_handler
|
||||
.type main_irq_handler, %function
|
||||
main_irq_handler:
|
||||
sub lr, lr, #4 @ Fix return address
|
||||
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
|
||||
|
@ -1,27 +1,25 @@
|
||||
#include <types.h>
|
||||
#include <vram.h>
|
||||
#include <arm.h>
|
||||
#include <pxi.h>
|
||||
#include <gic.h>
|
||||
#include <gpulcd.h>
|
||||
#include <vram.h>
|
||||
#include <types.h>
|
||||
|
||||
#include <i2c.h>
|
||||
|
||||
#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;
|
||||
|
68
arm11/source/sys.c
Executable file
68
arm11/source/sys.c
Executable file
@ -0,0 +1,68 @@
|
||||
#include <types.h>
|
||||
#include <arm.h>
|
||||
|
||||
#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();
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
93
common/arm.h
93
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 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__
|
||||
|
42
common/pxi.h
42
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,
|
||||
};
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
@ -9,6 +9,7 @@
|
||||
#define BIT(x) (1 << (x))
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user