Exo: bpmpfw -> sc7fw, lp0 -> sc7

This commit is contained in:
Michael Scire
2018-12-17 11:30:59 -08:00
parent b72a68f622
commit dca51291aa
17 changed files with 23 additions and 23 deletions

154
exosphere/sc7fw/Makefile Normal file
View File

@@ -0,0 +1,154 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/base_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := src
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
CFLAGS := \
-g \
-O2 \
-ffunction-sections \
-fdata-sections \
-fomit-frame-pointer \
-fno-inline \
-std=gnu11 \
-Werror \
-Wall \
$(ARCH) $(DEFINES)
CFLAGS += $(INCLUDE) -D__BPMP__
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS :=
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS :=
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf
#---------------------------------------------------------------------------------
else
.PHONY: all
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
all : $(OUTPUT).bin
$(OUTPUT).bin : $(OUTPUT).elf
$(OBJCOPY) -S -O binary $< $@
@echo built ... $(notdir $@)
$(OUTPUT).elf : $(OFILES)
%.elf: $(OFILES)
@echo linking $(notdir $@)
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
@$(NM) -CSn $@ > $(notdir $*.lst)
$(OFILES_SRC) : $(HFILES_BIN)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

21
exosphere/sc7fw/linker.ld Normal file
View File

@@ -0,0 +1,21 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x40003000;
__start__ = ABSOLUTE(.);
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
.bss : ALIGN(8) { __bss_start__ = .; *(.bss* COMMON); . = ALIGN(8); __bss_end__ = .; }
. = ALIGN(4);
__end__ = ABSOLUTE(.);
__stack_top__ = 0x40005000;
__stack_bottom__ = 0x40004000;
}

View File

@@ -0,0 +1,7 @@
%rename link old_link
*link:
%(old_link) -T %:getenv(TOPDIR /linker.ld) --nmagic --gc-sections
*startfile:
crti%O%s crtbegin%O%s

73
exosphere/sc7fw/src/emc.c Normal file
View File

@@ -0,0 +1,73 @@
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "utils.h"
#include "sc7.h"
#include "emc.h"
#include "pmc.h"
#include "timer.h"
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. */
}
}
/* Puts DRAM into self refresh mode. */
void emc_put_dram_in_self_refresh_mode(void) {
/* Verify CH1_ENABLE [PMC]. */
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;
emc_trigger_timing_update();
while (EMC0_CFG_DIG_DLL_0 & 1) { /* Wait for EMC0 to clear. */ }
while (EMC1_CFG_DIG_DLL_0 & 1) { /* Wait for EMC1 to clear. */ }
} 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. */ }
}

67
exosphere/sc7fw/src/emc.h Normal file
View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EXOSPHERE_BPMPFW_EMC_H
#define EXOSPHERE_BPMPFW_EMC_H
#include "utils.h"
#define EMC_BASE (0x7001B000)
#define EMC0_BASE (0x7001E000)
#define EMC1_BASE (0x7001F000)
#define MAKE_EMC_REG(ofs) (MAKE_REG32(EMC_BASE + ofs))
#define MAKE_EMC0_REG(ofs) (MAKE_REG32(EMC0_BASE + ofs))
#define MAKE_EMC1_REG(ofs) (MAKE_REG32(EMC1_BASE + ofs))
#define EMC_CFG_0 MAKE_EMC_REG(0x00C)
#define EMC_ADR_CFG_0 MAKE_EMC_REG(0x10)
#define EMC_TIMING_CONTROL_0 MAKE_EMC_REG(0x028)
#define EMC_SELF_REF_0 MAKE_EMC_REG(0x0E0)
#define EMC_MRW_0 MAKE_EMC_REG(0x0E8)
#define EMC_FBIO_CFG5_0 MAKE_EMC_REG(0x104)
#define EMC_MRW3_0 MAKE_EMC_REG(0x138)
#define EMC_AUTO_CAL_CONFIG_0 MAKE_EMC_REG(0x2A4)
#define EMC_REQ_CTRL_0 MAKE_EMC_REG(0x2B0)
#define EMC_EMC_STATUS_0 MAKE_EMC_REG(0x2B4)
#define EMC0_EMC_STATUS_0 MAKE_EMC0_REG(0x2B4)
#define EMC1_EMC_STATUS_0 MAKE_EMC1_REG(0x2B4)
#define EMC_CFG_DIG_DLL_0 MAKE_EMC_REG(0x2BC)
#define EMC0_CFG_DIG_DLL_0 MAKE_EMC0_REG(0x2BC)
#define EMC1_CFG_DIG_DLL_0 MAKE_EMC1_REG(0x2BC)
#define EMC_ZCAL_INTERVAL_0 MAKE_EMC_REG(0x2E0)
#define EMC_PMC_SCRATCH3_0 MAKE_EMC_REG(0x448)
#define EMC_FBIO_CFG7_0 MAKE_EMC_REG(0x584)
void emc_put_dram_in_self_refresh_mode(void);
#endif

104
exosphere/sc7fw/src/i2c.c Normal file
View File

@@ -0,0 +1,104 @@
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "i2c.h"
#include "timer.h"
/* Prototypes for internal commands. */
void i2c_load_config(void);
int i2c_write(unsigned int device, uint32_t val, unsigned int num_bytes);
int i2c_send_byte_command(unsigned int device, unsigned char reg, unsigned char b);
/* Load hardware config for I2C4. */
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);
if (!(I2C_I2C_CONFIG_LOAD_0 & 1)) {
break;
}
}
}
/* Initialize I2C4. */
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);
if (I2C_INTERRUPT_STATUS_REGISTER_0 & 0x800) {
break;
}
}
/* Read the BUS_CLEAR_STATUS. Result doesn't matter. */
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;
}
/* Writes a value to an i2c device. */
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 & 0xF) == 0;
}
/* Writes a byte val to reg for given device. */
int i2c_send_byte_command(unsigned int device, unsigned char reg, unsigned char b) {
uint32_t val = (reg) | (b << 8);
/* Write 1 byte (reg) + 1 byte (value) */
return i2c_write(device, val, 2);
}
/* Actually reset device 27. This might turn off the screen? */
int i2c_send_reset_cmd(void) {
/* Write 00 to Device 27 Reg 00. */
return i2c_send_byte_command(27, 0, 0);
}

50
exosphere/sc7fw/src/i2c.h Normal file
View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EXOSPHERE_BPMPFW_I2C_H
#define EXOSPHERE_BPMPFW_I2C_H
#include "utils.h"
/* I2C_BASE = I2C4. */
#define I2C_BASE (0x7000D000)
#define MAKE_I2C_REG(ofs) (MAKE_REG32(I2C_BASE + ofs))
#define I2C_I2C_CNFG_0 MAKE_I2C_REG(0x000)
#define I2C_I2C_CMD_ADDR0_0 MAKE_I2C_REG(0x004)
#define I2C_I2C_CMD_DATA1_0 MAKE_I2C_REG(0x00C)
#define I2C_I2C_STATUS_0 MAKE_I2C_REG(0x01C)
#define I2C_INTERRUPT_STATUS_REGISTER_0 MAKE_I2C_REG(0x068)
#define I2C_I2C_CLK_DIVISOR_REGISTER_0 MAKE_I2C_REG(0x06C)
#define I2C_I2C_BUS_CLEAR_CONFIG_0 MAKE_I2C_REG(0x084)
#define I2C_I2C_BUS_CLEAR_STATUS_0 MAKE_I2C_REG(0x088)
#define I2C_I2C_CONFIG_LOAD_0 MAKE_I2C_REG(0x08C)
void i2c_init(void);
int i2c_send_reset_cmd(void);
#endif

53
exosphere/sc7fw/src/pmc.h Normal file
View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EXOSPHERE_BPMPFW_PMC_H
#define EXOSPHERE_BPMPFW_PMC_H
#include "utils.h"
#define PMC_BASE (0x7000E400)
#define MAKE_PMC_REG(ofs) (MAKE_REG32(PMC_BASE + ofs))
#define APBDEV_PMC_CNTRL_0 MAKE_PMC_REG(0x000)
#define APBDEV_PMC_DPD_SAMPLE_0 MAKE_PMC_REG(0x020)
#define APBDEV_PMC_DPD_ENABLE_0 MAKE_PMC_REG(0x024)
#define APBDEV_PMC_CLAMP_STATUS_0 MAKE_PMC_REG(0x02C)
#define APBDEV_PMC_PWRGATE_STATUS_0 MAKE_PMC_REG(0x038)
#define APBDEV_PMC_SCRATCH12_0 MAKE_PMC_REG(0x080)
#define APBDEV_PMC_SCRATCH13_0 MAKE_PMC_REG(0x084)
#define APBDEV_PMC_SCRATCH18_0 MAKE_PMC_REG(0x098)
#define APBDEV_PMC_WEAK_BIAS_0 MAKE_PMC_REG(0x2C8)
#define APBDEV_PMC_IO_DPD3_REQ_0 MAKE_PMC_REG(0x45C)
#define APBDEV_PMC_IO_DPD3_STATUS_0 MAKE_PMC_REG(0x460)
#define APBDEV_PMC_IO_DPD4_REQ_0 MAKE_PMC_REG(0x464)
#define APBDEV_PMC_IO_DPD4_STATUS_0 MAKE_PMC_REG(0x468)
#define APBDEV_PMC_SET_SW_CLAMP_0 MAKE_PMC_REG(0x47C)
#define APBDEV_PMC_DDR_CNTRL_0 MAKE_PMC_REG(0x4E4)
#endif

120
exosphere/sc7fw/src/sc7.c Normal file
View File

@@ -0,0 +1,120 @@
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "utils.h"
#include "sc7.h"
#include "i2c.h"
#include "pmc.h"
#include "emc.h"
#include "timer.h"
#define CACHE_CTRL MAKE_REG32(0x50040000)
#define PRI_ICTLR_COP_IER_CLR_0 MAKE_REG32(0x60004038)
#define SEC_ICTLR_COP_IER_CLR_0 MAKE_REG32(0x60004138)
#define TRI_ICTLR_COP_IER_CLR_0 MAKE_REG32(0x60004238)
#define QUAD_ICTLR_COP_IER_CLR_0 MAKE_REG32(0x60004338)
#define PENTA_ICTLR_COP_IER_CLR_0 MAKE_REG32(0x60004438)
#define HEXA_ICTLR_COP_IER_CLR_0 MAKE_REG32(0x60004538)
void reboot(void) {
/* Write MAIN_RST */
APBDEV_PMC_CNTRL_0 = 0x10;
while (true) {
/* Wait for reboot. */
}
}
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;
if (emc_pmc_val & 0x40000000) {
APBDEV_PMC_WEAK_BIAS_0 = 0x7FFF0000;
}
/* Request to put pads in Deep Power Down. */
APBDEV_PMC_IO_DPD3_REQ_0 = 0x8FFFFFFF;
while (APBDEV_PMC_IO_DPD3_STATUS_0 != 0xFFFFFFF) { /* Wait a while. */ }
spinlock_wait(32);
APBDEV_PMC_IO_DPD4_REQ_0 = 0x8FFFFFFF;
while (APBDEV_PMC_IO_DPD4_STATUS_0 != 0xFFF1FFF) { /* Wait a while. */ }
spinlock_wait(32);
}
void sc7_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;
TRI_ICTLR_COP_IER_CLR_0 = 0xFFFFFFFF;
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. */
reboot();
}
/* Write MRW3_OP into scratch. */
APBDEV_PMC_SCRATCH18_0 = (APBDEV_PMC_SCRATCH18_0 & 0xFFFFFF3F) | (EMC_MRW3_0 & 0xC0);
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 (true) { /* Wait until we're asleep. */ }
}

26
exosphere/sc7fw/src/sc7.h Normal file
View File

@@ -0,0 +1,26 @@
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EXOSPHERE_BPMPFW_SC7_H
#define EXOSPHERE_BPMPFW_SC7_H
#include "utils.h"
void sc7_entry_main(void);
void reboot(void);
#endif

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
.section .text.start
.align 4
.global _start
_start:
b crt0
.global _reboot
b reboot
.global crt0
.type crt0, %function
crt0:
@ setup to call sc7_entry_main
msr cpsr_cxsf, #0xD3
ldr sp, =__stack_top__
ldr lr, =reboot
b sc7_entry_main
.global spinlock_wait
.type spinlock_wait, %function
spinlock_wait:
subs r0, r0, #1
bgt spinlock_wait
bx lr

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EXOSPHERE_BPMPFW_TIMER_H
#define EXOSPHERE_BPMPFW_TIMER_H
#include "utils.h"
#define TIMERUS_CNTR_1US_0 MAKE_REG32(0x60005010)
static inline void timer_wait(uint32_t microseconds) {
uint32_t old_time = TIMERUS_CNTR_1US_0;
while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) {
/* Spin-lock. */
}
}
void spinlock_wait(uint32_t count);
#endif

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EXOSPHERE_BPMPFW_UTILS_H
#define EXOSPHERE_BPMPFW_UTILS_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#define BIT(n) (1u << (n))
#define BITL(n) (1ull << (n))
#define MASK(n) (BIT(n) - 1)
#define MASKL(n) (BITL(n) - 1)
#define MASK2(a,b) (MASK(a) & ~MASK(b))
#define MASK2L(a,b) (MASKL(a) & ~MASKL(b))
#define MAKE_REG32(a) (*(volatile uint32_t *)(a))
#define ALIGN(m) __attribute__((aligned(m)))
#define PACKED __attribute__((packed))
#define ALINLINE __attribute__((always_inline))
#endif