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:
Wolfvak 2019-04-11 18:16:20 -03:00 committed by d0k3
parent e70b8ab116
commit 2f86686388
31 changed files with 784 additions and 469 deletions

View File

@ -8,8 +8,8 @@ SECTIONS
.text : ALIGN(4) { *(.text.boot) *(.text*); . = ALIGN(4); } .text : ALIGN(4) { *(.text.boot) *(.text*); . = ALIGN(4); }
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); } .rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
.data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); } .data : ALIGN(4) { *(.data*); . = ALIGN(8); }
.bss : ALIGN(4) { __bss_start = .; *(.bss*); __bss_end = .; } .bss : ALIGN(4) { __bss_start = .; *(.bss* COMMON); __bss_end = .; }
. = ALIGN(4); . = ALIGN(4);
} }

204
arm11/source/arm/gic.c Normal file
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,5 @@
#pragma once
#include <types.h>
void SCU_Init(void);

View 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

View File

@ -3,26 +3,48 @@
#include <arm.h> #include <arm.h>
#define STACK_SZ (8192)
.global __boot .global __boot
__boot: __boot:
cpsid aif, #SR_SVC_MODE cpsid aif, #SR_SVC_MODE
@ Writeback and invalidate all DCache
@ Invalidate all caches
@ Data Synchronization Barrier
mov r0, #0 mov r0, #0
mcr p15, 0, r0, c7, c10, 0
mcr p15, 0, r0, c7, c7, 0 mcr p15, 0, r0, c7, c7, 0
mcr p15, 0, r0, c7, c14, 0
mcr p15, 0, r0, c7, c10, 4 mcr p15, 0, r0, c7, c10, 4
ldr sp, =_stack_top @ Reset control registers
@ Reset values
ldr r0, =0x00054078 ldr r0, =0x00054078
ldr r1, =0x0000000F ldr r1, =0x0000000F
ldr r2, =0x00000000 ldr r2, =0x00F00000
mcr p15, 0, r0, c1, c0, 0 mcr p15, 0, r0, c1, c0, 0
mcr p15, 0, r1, c1, c0, 1 mcr p15, 0, r1, c1, c0, 1
mcr p15, 0, r2, c1, c0, 2 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 r0, =__bss_start
ldr r1, =__bss_end ldr r1, =__bss_end
mov r2, #0 mov r2, #0
@ -31,10 +53,20 @@ __boot:
strlt r2, [r0], #4 strlt r2, [r0], #4
blt .Lclearbss 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 b __boot
.section .bss.stack .section .bss.stack
.align 3 .align 3
.space (8192 * 4) _stack_base:
_stack_top: .space (MAX_CPU * STACK_SZ)

View File

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

View File

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

View File

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

View File

@ -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
View 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
View 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();

View File

@ -17,8 +17,9 @@
*/ */
#include <stdbool.h> #include <stdbool.h>
#include "types.h"
#include "i2c.h" #include <types.h>
#include "hw/i2c.h"
#define I2C1_REGS_BASE (0x10161000) #define I2C1_REGS_BASE (0x10161000)

View File

@ -19,7 +19,7 @@
*/ */
#include <stdbool.h> #include <stdbool.h>
#include "types.h" #include <types.h>
#define I2C_STOP (1u) #define I2C_STOP (1u)

View File

@ -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

View File

@ -1,27 +1,25 @@
#include <types.h>
#include <vram.h>
#include <arm.h> #include <arm.h>
#include <pxi.h> #include <pxi.h>
#include <gic.h>
#include <gpulcd.h>
#include <vram.h>
#include <types.h>
#include <i2c.h> #include "arm/gic.h"
#include "hw/gpulcd.h"
#define CFG11_MPCORE_CLKCNT ((vu16*)(0x10141300)) #include "hw/i2c.h"
#define CFG11_SOCINFO ((vu16*)(0x10140FFC)) #include "hw/mcu.h"
#define LEGACY_BOOT_ENTRY ((vu32*)0x1FFFFFFC) #define LEGACY_BOOT_ENTRY ((vu32*)0x1FFFFFFC)
#define LEGACY_BOOT_MAGIC (0xDEADDEAD) #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(); msg = PXI_Recv();
cmd = msg & 0xFFFF; cmd = msg & 0xFFFF;
argc = msg >> 16; argc = msg >> 16;
if (argc > PXI_FIFO_LEN) { if (argc > PXI_MAX_ARGS) {
PXI_Send(0xFFFFFFFF); PXI_Send(0xFFFFFFFF);
return; return;
} }
@ -29,6 +27,20 @@ void PXI_RX_Handler(void)
PXI_RecvArray(args, argc); PXI_RecvArray(args, argc);
switch (cmd) { 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: case PXI_SCREENINIT:
{ {
GPU_Init(); GPU_Init();
@ -45,8 +57,7 @@ void PXI_RX_Handler(void)
case PXI_BRIGHTNESS: case PXI_BRIGHTNESS:
{ {
LCD_SetBrightness(0, args[0]); LCD_SetBrightness(args[0]);
LCD_SetBrightness(1, args[0]);
ret = args[0]; ret = args[0];
break; break;
} }
@ -63,13 +74,6 @@ void PXI_RX_Handler(void)
break; break;
} }
case PXI_LEGACY_BOOT:
{
*LEGACY_BOOT_ENTRY = LEGACY_BOOT_MAGIC;
ret = 0;
break;
}
/* New CMD template: /* New CMD template:
case CMD_ID: case CMD_ID:
{ {
@ -89,38 +93,29 @@ void PXI_RX_Handler(void)
return; return;
} }
void main(void) void MPCoreMain(void)
{ {
u32 entry; u32 entry;
if ((*CFG11_SOCINFO & 2) && (!(*CFG11_MPCORE_CLKCNT & 1))) { GIC_Enable(IRQ_PXI_RX, BIT(0), GIC_HIGHEST_PRIO, PXI_RX_Handler);
GIC_Reset(); *LEGACY_BOOT_ENTRY = 0;
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();
PXI_Reset(); PXI_Reset();
I2C_init(); I2C_init();
//MCU_init(); //MCU_init();
GIC_SetIRQ(IRQ_PXI_RX, PXI_RX_Handler); PXI_Barrier(ARM11_READY_BARRIER);
*LEGACY_BOOT_ENTRY = 0; ARM_EnableInterrupts();
arm_enable_ints();
// Process IRQs until the ARM9 tells us it's time to boot something else
do { do {
arm_wfi(); ARM_WFI();
} while(*LEGACY_BOOT_ENTRY != LEGACY_BOOT_MAGIC); } while(*LEGACY_BOOT_ENTRY != LEGACY_BOOT_MAGIC);
arm_disable_ints(); // Perform any needed deinit stuff
GIC_Reset(); ARM_DisableInterrupts();
GIC_GlobalReset();
GIC_LocalReset();
do { do {
entry = *LEGACY_BOOT_ENTRY; entry = *LEGACY_BOOT_ENTRY;

68
arm11/source/sys.c Executable file
View 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();
}

View File

@ -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
arm_wb_dc(); ARM_WbDC();
arm_dsb(); 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
arm_wb_dc(); ARM_WbDC();
arm_dsb(); ARM_DSB();
I2C_writeReg(I2C_DEV_MCU, 0x20, 1 << 0); I2C_writeReg(I2C_DEV_MCU, 0x20, 1 << 0);
while(true); while(true);
} }

View File

@ -100,7 +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); PXI_DoCMD(PXI_LEGACY_MODE, NULL, 0);
BootFirm((FirmHeader*) firm, fixpath); BootFirm((FirmHeader*) firm, fixpath);
while(1); while(1);
} }

View File

@ -13,6 +13,10 @@ void main(int argc, char** argv, int entrypoint)
PXI_Reset(); 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); PXI_DoCMD(PXI_SCREENINIT, NULL, 0);
I2C_writeReg(I2C_DEV_MCU, 0x22, 0x2A); I2C_writeReg(I2C_DEV_MCU, 0x22, 0x2A);

View File

@ -33,7 +33,7 @@ _start:
blx r0 @ Invalidate Instruction Cache blx r0 @ Invalidate Instruction Cache
@ Disable caches / DTCM / MPU @ 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) ldr r2, =(CR_ITCM)
mrc p15, 0, r0, c1, c0, 0 mrc p15, 0, r0, c1, c0, 0
bic r0, r1 bic r0, r1
@ -92,7 +92,7 @@ _start:
@ Enable caches / DTCM / select low exception vectors @ Enable caches / DTCM / select low exception vectors
ldr r1, =(CR_ALT_VECTORS | CR_V4TLD) 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 mrc p15, 0, r0, c1, c0, 0
bic r0, r1 bic r0, r1
orr r0, r2 orr r0, r2

View File

@ -24,12 +24,12 @@ 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};
arm_wb_dc_range(i2c_fcram_buf, size); ARM_WbDC_Range(i2c_fcram_buf, size);
arm_dsb(); ARM_DSB();
ret = PXI_DoCMD(PXI_I2C_READ, args, 4); 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); memcpy(out, i2c_fcram_buf, size);
return ret; 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}; u32 args[] = {devId, regAddr, (u32)i2c_fcram_buf, size};
memcpy(i2c_fcram_buf, in, size); memcpy(i2c_fcram_buf, in, size);
arm_wb_dc_range(i2c_fcram_buf, size); ARM_WbDC_Range(i2c_fcram_buf, size);
arm_dsb(); ARM_DSB();
ret = PXI_DoCMD(PXI_I2C_WRITE, args, 4); ret = PXI_DoCMD(PXI_I2C_WRITE, args, 4);
return ret; return ret;

View File

@ -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_MPU | CR_DCACHE | CR_ICACHE | CR_DTCM) ldr r1, =(CR_MPU | CR_CACHES | 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

View File

@ -29,10 +29,14 @@
#define CR_CACHE_RROBIN BIT(14) #define CR_CACHE_RROBIN BIT(14)
#define CR_DTCM_LOAD BIT(17) #define CR_DTCM_LOAD BIT(17)
#define CR_ITCM_LOAD BIT(19) #define CR_ITCM_LOAD BIT(19)
#define CR_TCM_LOAD (CR_DTCM_LOAD | CR_ITCM_LOAD)
#define CR_TCM_LOAD (CR_DTCM_LOAD | CR_ITCM_LOAD)
#define ICACHE_SZ (4096) #define ICACHE_SZ (4096)
#define DCACHE_SZ (4096) #define DCACHE_SZ (4096)
#define MAX_IRQ (32)
#define MAX_CPU (1)
#else // ARM11 #else // ARM11
#define CR_MMU BIT(0) #define CR_MMU BIT(0)
#define CR_ALIGN BIT(1) #define CR_ALIGN BIT(1)
@ -53,8 +57,13 @@
#define ICACHE_SZ (16384) #define ICACHE_SZ (16384)
#define DCACHE_SZ (16384) #define DCACHE_SZ (16384)
#define MAX_IRQ (96)
#define MAX_CPU (2)
#endif #endif
#define CR_CACHES (CR_DCACHE | CR_ICACHE)
#ifndef __ASSEMBLER__ #ifndef __ASSEMBLER__
@ -90,7 +99,7 @@
* so that all instructions following the ISB are fetched from cache or memory * so that all instructions following the ISB are fetched from cache or memory
* after the ISB has been completed. * 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); ARM_MCR(p15, 0, 0, c7, c5, 4);
} }
@ -98,33 +107,33 @@
* A Data Memory Barrier (DMB) ensures that all explicit memory accesses before * 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. * 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); ARM_MCR(p15, 0, 0, c7, c10, 5);
} }
/* Wait For Interrupt */ /* Wait For Interrupt */
static inline void arm_wfi(void) { static inline void ARM_WFI(void) {
asm_v("wfi\n\t"); asm_v("wfi\n\t");
} }
/* Wait For Event */ /* Wait For Event */
static inline void arm_wfe(void) { static inline void ARM_WFE(void) {
asm_v("wfe\n\t"); asm_v("wfe\n\t");
} }
/* Send Event */ /* Send Event */
static inline void arm_sev(void) { static inline void ARM_SEV(void) {
asm_v("sev\n\t"); asm_v("sev\n\t");
} }
/* Auxiliary Control Registers */ /* Auxiliary Control Registers */
static inline u32 arm_acr_get(void) { static inline u32 ARM_GetACR(void) {
u32 acr; u32 acr;
ARM_MRC(p15, 0, acr, c1, c0, 1); ARM_MRC(p15, 0, acr, c1, c0, 1);
return acr; 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); ARM_MCR(p15, 0, acr, c1, c0, 1);
} }
#endif #endif
@ -134,24 +143,24 @@
* A Data Synchronization Barrier (DSB) completes when all * A Data Synchronization Barrier (DSB) completes when all
* instructions before this instruction complete. * 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); ARM_MCR(p15, 0, 0, c7, c10, 4);
} }
/* Control Registers */ /* Control Registers */
static inline u32 arm_cr_get(void) { static inline u32 ARM_GetCR(void) {
u32 cr; u32 cr;
ARM_MRC(p15, 0, cr, c1, c0, 0); ARM_MRC(p15, 0, cr, c1, c0, 0);
return cr; 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); ARM_MCR(p15, 0, cr, c1, c0, 0);
} }
/* Thread ID Registers */ /* Thread ID Registers */
static inline u32 arm_tid_get(void) { static inline u32 ARM_GetTID(void) {
u32 pid; u32 pid;
#ifdef ARM9 #ifdef ARM9
ARM_MRC(p15, 0, pid, c13, c0, 1); ARM_MRC(p15, 0, pid, c13, c0, 1);
@ -161,7 +170,7 @@ static inline u32 arm_tid_get(void) {
return pid; return pid;
} }
static inline void arm_tid_set(u32 pid) { static inline void ARM_SetTID(u32 pid) {
#ifdef ARM9 #ifdef ARM9
ARM_MCR(p15, 0, pid, c13, c0, 1); ARM_MCR(p15, 0, pid, c13, c0, 1);
#else #else
@ -170,7 +179,7 @@ static inline void arm_tid_set(u32 pid) {
} }
/* CPU ID */ /* CPU ID */
static inline u32 arm_cpuid(void) { static inline u32 ARM_CoreID(void) {
u32 id; u32 id;
#ifdef ARM9 #ifdef ARM9
id = 0; id = 0;
@ -181,63 +190,71 @@ static inline u32 arm_cpuid(void) {
} }
/* Status Register */ /* Status Register */
static inline u32 arm_cpsr_get(void) { static inline u32 ARM_GetCPSR(void) {
u32 cpsr; u32 sr;
ARM_MRS(cpsr, "cpsr"); ARM_MRS(sr, cpsr);
return cpsr; return sr;
} }
static inline void arm_cpsr_c_set(u32 cpsr) { static inline void ARM_SetCPSR_c(u32 sr) {
ARM_MSR("cpsr_c", cpsr); ARM_MSR(cpsr_c, sr);
} }
static inline void arm_disable_ints(void) { static inline void ARM_DisableInterrupts(void) {
#ifdef ARM9 #ifdef ARM9
arm_cpsr_c_set(arm_cpsr_get() | SR_NOINT); ARM_SetCPSR_c(ARM_GetCPSR() | SR_NOINT);
#else #else
ARM_CPSID(if); ARM_CPSID(if);
#endif #endif
} }
static inline void arm_enable_ints(void) { static inline void ARM_EnableInterrupts(void) {
#ifdef ARM9 #ifdef ARM9
arm_cpsr_c_set(arm_cpsr_get() & ~SR_NOINT); ARM_SetCPSR_c(ARM_GetCPSR() & ~SR_NOINT);
#else #else
ARM_CPSIE(if); ARM_CPSIE(if);
#endif #endif
} }
static inline u32 arm_enter_critical(void) { static inline u32 ARM_EnterCritical(void) {
u32 stat = arm_cpsr_get(); u32 stat = ARM_GetCPSR();
arm_disable_ints(); ARM_DisableInterrupts();
return stat & SR_NOINT; return stat & SR_NOINT;
} }
static inline void arm_leave_critical(u32 stat) { static inline void ARM_LeaveCritical(u32 stat) {
arm_cpsr_c_set((arm_cpsr_get() & ~SR_NOINT) | stat); ARM_SetCPSR_c((ARM_GetCPSR() & ~SR_NOINT) | stat);
} }
/* Cache functions */ /* 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); 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; u32 addr = (u32)base & ~0x1F;
len >>= 5; len >>= 5;
do { do {
#ifdef ARM9
ARM_MCR(p15, 0, addr, c7, c5, 1); ARM_MCR(p15, 0, addr, c7, c5, 1);
#else
ARM_MCR(p15, 0, addr, c7, c7, 1);
#endif
addr += 0x20; addr += 0x20;
} while(len--); } while(len--);
} }
static inline void arm_inv_dc(void) { static inline void ARM_InvDC(void) {
ARM_MCR(p15, 0, 0, c7, c6, 0); 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; u32 addr = (u32)base & ~0x1F;
len >>= 5; len >>= 5;
@ -247,7 +264,7 @@ static inline void arm_inv_dc_range(void *base, u32 len) {
} while(len--); } while(len--);
} }
static inline void arm_wb_dc(void) { static inline void ARM_WbDC(void) {
#ifdef ARM9 #ifdef ARM9
u32 seg = 0, ind; u32 seg = 0, ind;
do { do {
@ -263,7 +280,7 @@ static inline void arm_wb_dc(void) {
#endif #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; u32 addr = (u32)base & ~0x1F;
len >>= 5; len >>= 5;
@ -273,7 +290,7 @@ static inline void arm_wb_dc_range(void *base, u32 len) {
} while(len--); } while(len--);
} }
static inline void arm_wb_inv_dc(void) { static inline void ARM_WbInvDC(void) {
#ifdef ARM9 #ifdef ARM9
u32 seg = 0, ind; u32 seg = 0, ind;
do { do {
@ -289,7 +306,7 @@ static inline void arm_wb_inv_dc(void) {
#endif #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; u32 addr = (u32)base & ~0x1F;
len >>= 5; len >>= 5;
@ -299,4 +316,8 @@ static inline void arm_wb_inv_dc_range(void *base, u32 len) {
} while(len--); } while(len--);
} }
static inline void ARM_BKPT(void) {
__builtin_trap();
}
#endif // __ASSEMBLER__ #endif // __ASSEMBLER__

View File

@ -15,14 +15,28 @@
#endif #endif
enum { enum {
PXI_SCREENINIT = 0, PXI_LEGACY_MODE = 0,
PXI_GET_SHMEM,
PXI_SCREENINIT,
PXI_BRIGHTNESS, PXI_BRIGHTNESS,
PXI_I2C_READ, PXI_I2C_READ,
PXI_I2C_WRITE, PXI_I2C_WRITE,
PXI_LEGACY_BOOT,
}; };
#define PXI_FIFO_LEN (16) /*
* These should be pseudo-random numbers
* and shouldnt be similar to those
* used by any other software
*/
enum {
ARM11_READY_BARRIER = 19,
};
#define PXI_FIFO_LEN (16)
#define PXI_MAX_ARGS (32)
#define PXI_INIT_MAGIC (0xDD)
#define PXI_SYNC_RECV ((vu8*)(PXI_BASE + 0x00)) #define PXI_SYNC_RECV ((vu8*)(PXI_BASE + 0x00))
#define PXI_SYNC_SEND ((vu8*)(PXI_BASE + 0x01)) #define PXI_SYNC_SEND ((vu8*)(PXI_BASE + 0x01))
@ -41,10 +55,6 @@ enum {
#define PXI_CNT_ERROR_ACK (BIT(14)) #define PXI_CNT_ERROR_ACK (BIT(14))
#define PXI_CNT_ENABLE_FIFO (BIT(15)) #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) static inline void PXI_SetRemote(u8 msg)
{ {
*PXI_SYNC_SEND = msg; *PXI_SYNC_SEND = msg;
@ -60,7 +70,7 @@ static inline void PXI_WaitRemote(u8 msg)
while(PXI_GetRemote() != msg); while(PXI_GetRemote() != msg);
} }
static void PXI_Reset(void) static inline void PXI_Reset(void)
{ {
*PXI_SYNC_IRQ = 0; *PXI_SYNC_IRQ = 0;
*PXI_CNT = PXI_CNT_SEND_FIFO_FLUSH | PXI_CNT_ENABLE_FIFO; *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 = 0;
*PXI_CNT = PXI_CNT_RECV_FIFO_AVAIL_IRQ | PXI_CNT_ENABLE_FIFO; *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); while(*PXI_CNT & PXI_CNT_SEND_FIFO_FULL);
*PXI_SEND = w; *PXI_SEND = w;
} }
static u32 PXI_Recv(void) static inline u32 PXI_Recv(void)
{ {
while(*PXI_CNT & PXI_CNT_RECV_FIFO_EMPTY); while(*PXI_CNT & PXI_CNT_RECV_FIFO_EMPTY);
return *PXI_RECV; 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++)); 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(); 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_Send((argc << 16) | cmd);
PXI_SendArray(args, argc); PXI_SendArray(args, argc);

View File

@ -9,6 +9,7 @@
#define BIT(x) (1 << (x)) #define BIT(x) (1 << (x))
#ifndef __ASSEMBLER__ #ifndef __ASSEMBLER__
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>