diff --git a/exosphere/bpmpfw/Makefile b/exosphere/bpmpfw/Makefile index 55b1d4f01..87df99b5e 100644 --- a/exosphere/bpmpfw/Makefile +++ b/exosphere/bpmpfw/Makefile @@ -12,24 +12,23 @@ dir_source := src dir_build := build dir_out := out -ASFLAGS := +ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork + +ASFLAGS := -g $(ARCH) CFLAGS = \ - -Iinclude \ - -Iinclude/compat \ - -march=armv8-a \ - -mlittle-endian \ - -fno-stack-protector \ - -fno-common \ - -fno-builtin \ - -fno-inline \ - -ffreestanding \ - -std=gnu99 \ + $(ARCH) \ + -g \ + -O2 \ + -ffunction-sections \ + -fdata-sections \ + -fomit-frame-pointer \ + -fno-inline \ + -std=gnu11 \ -Werror \ - -Wall \ - -Wno-error=unused-variable - -LDFLAGS := -nostartfiles -Wl,--nmagic + -Wall + +LDFLAGS = -g $(ARCH) -nostartfiles -nostdlib -Wl,--nmagic,--gc-sections objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ @@ -59,4 +58,4 @@ $(dir_build)/%.o: $(dir_source)/%.c $(dir_build)/%.o: $(dir_source)/%.s @mkdir -p "$(@D)" - $(COMPILE.s) $(OUTPUT_OPTION) $< + $(COMPILE.c) -x assembler-with-cpp $(OUTPUT_OPTION) $< diff --git a/exosphere/bpmpfw/src/emc.c b/exosphere/bpmpfw/src/emc.c index 3bb220c0a..d1893fe93 100644 --- a/exosphere/bpmpfw/src/emc.c +++ b/exosphere/bpmpfw/src/emc.c @@ -5,7 +5,7 @@ #include "pmc.h" #include "timer.h" -void emc_trigger_timing_update(void) { +static void emc_trigger_timing_update(void) { EMC_TIMING_CONTROL_0 = 1; while (EMC_EMC_STATUS_0 & 0x800000) { /* Wait until TIMING_UPDATE_STALLED is unset. */ @@ -18,16 +18,16 @@ void emc_put_dram_in_self_refresh_mode(void) { if (!(EMC_FBIO_CFG7_0 & 4)) { reboot(); } - + /* Clear config. */ EMC_CFG_0 = 0; emc_trigger_timing_update(); timer_wait(5); - + /* Set calibration intervals. */ EMC_ZCAL_INTERVAL_0 = 0; EMC_AUTO_CAL_CONFIG_0 = 0x600; /* AUTO_CAL_MEASURE_STALL | AUTO_CAL_UPDATE_STALL */ - + /* If EMC0 mirror is set, clear digital DLL. */ if (EMC0_CFG_DIG_DLL_0 & 1) { EMC_CFG_DIG_DLL_0 &= 0xFFFFFFFE; @@ -37,22 +37,22 @@ void emc_put_dram_in_self_refresh_mode(void) { } else { emc_trigger_timing_update(); } - + /* Stall all transactions to DRAM. */ EMC_REQ_CTRL_0 = 3; /* STALL_ALL_WRITES | STALL_ALL_READS. */ while (!(EMC0_EMC_STATUS_0 & 4)) { /* Wait for NO_OUTSTANDING_TRANSACTIONS for EMC0. */ } while (!(EMC1_EMC_STATUS_0 & 4)) { /* Wait for NO_OUTSTANDING_TRANSACTIONS for EMC1. */ } - + /* Enable Self-Refresh Mode. */ EMC_SELF_REF_0 |= 1; - - + + /* Wait until we see the right devices in self refresh mode. */ uint32_t num_populated_devices = 1; if (EMC_ADR_CFG_0) { num_populated_devices = 3; } - + while (((EMC0_EMC_STATUS_0 >> 8) & 3) != num_populated_devices) { /* Wait for EMC0 DRAM_IN_SELF_REFRESH to be correct. */ } while (((EMC1_EMC_STATUS_0 >> 8) & 3) != num_populated_devices) { /* Wait for EMC1 DRAM_IN_SELF_REFRESH to be correct. */ } -} \ No newline at end of file +} diff --git a/exosphere/bpmpfw/src/i2c.c b/exosphere/bpmpfw/src/i2c.c index 75dc76b31..93495c95c 100644 --- a/exosphere/bpmpfw/src/i2c.c +++ b/exosphere/bpmpfw/src/i2c.c @@ -5,7 +5,7 @@ void i2c_load_config(void) { /* Set MSTR_CONFIG_LOAD, TIMEOUT_CONFIG_LOAD, undocumented bit. */ I2C_I2C_CONFIG_LOAD_0 = 0x25; - + /* Wait a bit for master config to be loaded. */ for (unsigned int i = 0; i < 20; i++) { timer_wait(1); @@ -20,10 +20,10 @@ void i2c_init(void) { /* Setup divisor, and clear the bus. */ I2C_I2C_CLK_DIVISOR_REGISTER_0 = 0x50001; I2C_I2C_BUS_CLEAR_CONFIG_0 = 0x90003; - + /* Load hardware configuration. */ i2c_load_config(); - + /* Wait a while until BUS_CLEAR_DONE is set. */ for (unsigned int i = 0; i < 10; i++) { timer_wait(20000); @@ -31,10 +31,10 @@ void i2c_init(void) { break; } } - + /* Read the BUS_CLEAR_STATUS. Result doesn't matter. */ - uint32_t unused_clear_status = I2C_I2C_BUS_CLEAR_STATUS_0; - + I2C_I2C_BUS_CLEAR_STATUS_0; + /* Read and set the Interrupt Status. */ uint32_t int_status = I2C_INTERRUPT_STATUS_REGISTER_0; I2C_INTERRUPT_STATUS_REGISTER_0 = int_status; @@ -45,26 +45,26 @@ int i2c_write(unsigned int device, uint32_t val, unsigned int num_bytes) { if (num_bytes > 4) { return 0; } - + /* Set device for 7-bit mode. */ I2C_I2C_CMD_ADDR0_0 = device << 1; - + /* Load in data to write. */ I2C_I2C_CMD_DATA1_0 = val; - + /* Set config with LENGTH = num_bytes, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */ I2C_I2C_CNFG_0 = ((num_bytes << 1) - 2) | 0x2800; - + i2c_load_config(); - + /* Config |= SEND; */ I2C_I2C_CNFG_0 |= 0x200; - - + + while (I2C_I2C_STATUS_0 & 0x100) { /* Wait until not busy. */ } - + /* Return CMD1_STAT == SL1_XFER_SUCCESSFUL. */ return (I2C_I2C_STATUS_0 & 7) == 0; } @@ -80,4 +80,4 @@ int i2c_send_byte_command(unsigned int device, unsigned char reg, unsigned char int i2c_send_reset_cmd(void) { /* Write 00 to Device 27 Reg 00. */ return i2c_send_byte_command(27, 0, 0); -} \ No newline at end of file +} diff --git a/exosphere/bpmpfw/src/lp0.c b/exosphere/bpmpfw/src/lp0.c index adaad0fff..7a3c0a91d 100644 --- a/exosphere/bpmpfw/src/lp0.c +++ b/exosphere/bpmpfw/src/lp0.c @@ -1,4 +1,5 @@ #include +#include #include "lp0.h" #include "i2c.h" @@ -18,13 +19,13 @@ void reboot(void) { /* Write MAIN_RST */ APBDEV_PMC_CNTRL_0 = 0x10; - while (1) { + while (true) { /* Wait for reboot. */ } } -void set_pmc_dpd_io_pads(void) { +static void set_pmc_dpd_io_pads(void) { /* Read val from EMC_PMC scratch, configure accordingly. */ uint32_t emc_pmc_val = EMC_PMC_SCRATCH3_0; APBDEV_PMC_DDR_CNTRL_0 = emc_pmc_val & 0x7FFFF; @@ -43,22 +44,22 @@ void set_pmc_dpd_io_pads(void) { void lp0_entry_main(void) { /* Disable the BPMP Cache. */ CACHE_CTRL |= 0xC00; - + /* Wait until the CPU Rail is turned off. */ while (APBDEV_PMC_PWRGATE_STATUS_0 & 1) { /* Wait for TrustZone to finish. */ } - + /* Clamp the CPU Rail. */ APBDEV_PMC_SET_SW_CLAMP_0 |= 0x1; while (!(APBDEV_PMC_CLAMP_STATUS_0 & 1)) { /* Wait for CPU Rail to be clamped. */ } - + /* Waste some time. */ spinlock_wait(10); - + /* Reset device 27 over I2C, then wait a while. */ i2c_init(); i2c_send_reset_cmd(); timer_wait(700); - + /* Clear Interrupt Enable for BPMP in all ICTLRs. */ PRI_ICTLR_COP_IER_CLR_0 = 0xFFFFFFFF; SEC_ICTLR_COP_IER_CLR_0 = 0xFFFFFFFF; @@ -66,7 +67,7 @@ void lp0_entry_main(void) { QUAD_ICTLR_COP_IER_CLR_0 = 0xFFFFFFFF; PENTA_ICTLR_COP_IER_CLR_0 = 0xFFFFFFFF; HEXA_ICTLR_COP_IER_CLR_0 = 0xFFFFFFFF; - + /* Write EMC's DRAM op into PMC scratch. */ if ((EMC_FBIO_CFG5_0 & 3) != 1) { /* If DRAM_TYPE != LPDDR4, something's gone wrong. Reboot. */ @@ -77,29 +78,29 @@ void lp0_entry_main(void) { uint32_t mrw3_op = ((EMC_MRW3_0 & 0xC0) << 8) | (EMC_MRW3_0 & 0xC0); APBDEV_PMC_SCRATCH12_0 = (APBDEV_PMC_SCRATCH12_0 & 0xFFFF3F3F) | mrw3_op; APBDEV_PMC_SCRATCH13_0 = (APBDEV_PMC_SCRATCH13_0 & 0xFFFF3F3F) | mrw3_op; - + /* Ready DRAM for deep sleep. */ emc_put_dram_in_self_refresh_mode(); - + /* Setup LPDDR MRW based on device config. */ EMC_MRW_0 = 0x88110000; if (EMC_ADR_CFG_0 & 1) { EMC_MRW_0 = 0x48110000; } - + /* Put IO pads in Deep Power Down. */ set_pmc_dpd_io_pads(); - + /* Enable pad sampling during deep sleep. */ APBDEV_PMC_DPD_SAMPLE_0 |= 1; - + /* Waste some more time. */ spinlock_wait(0x128); - + /* Enter deep sleep. */ APBDEV_PMC_DPD_ENABLE_0 |= 1; - - while (1) { /* Wait until we're asleep. */ } + + while (true) { /* Wait until we're asleep. */ } } diff --git a/exosphere/bpmpfw/src/start.s b/exosphere/bpmpfw/src/start.s index afad59f54..c6a0ac794 100644 --- a/exosphere/bpmpfw/src/start.s +++ b/exosphere/bpmpfw/src/start.s @@ -10,19 +10,15 @@ _start: .type crt0, %function crt0: @ setup to call lp0_entry_main - msr cpsr_f, #0xC0 - msr cpsr_cf, #0xD3 + msr cpsr_cxsf, #0xD3 ldr sp, =__stack_top__ ldr lr, =reboot - bl lp0_entry_main - infloop: - b infloop - - + b lp0_entry_main + + .global spinlock_wait .type spinlock_wait, %function spinlock_wait: - sub r0, r0, #1 - cmp r0, #0 + subs r0, r0, #1 bgt spinlock_wait - bx lr \ No newline at end of file + bx lr