mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
exo2: implement warmboot firmware
This commit is contained in:
parent
ff87ff2592
commit
293c213bf2
43 changed files with 1996 additions and 103 deletions
122
exosphere2/warmboot/Makefile
Normal file
122
exosphere2/warmboot/Makefile
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# Define the atmosphere board and cpu
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export ATMOSPHERE_BOARD := nx-hac-001
|
||||||
|
export ATMOSPHERE_CPU := arm7tdmi
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# pull in common atmosphere configuration
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../../libraries/config/templates/exosphere.mk
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# 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 DEPSDIR := $(CURDIR)/$(BUILD)
|
||||||
|
|
||||||
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||||
|
|
||||||
|
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
|
||||||
|
$(notdir $(wildcard $(dir)/*.c))))
|
||||||
|
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).c)))
|
||||||
|
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).c)))
|
||||||
|
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).c)))
|
||||||
|
|
||||||
|
CPPFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.cpp)) $(notdir $(wildcard $(dir)/*.board.*.cpp)) $(notdir $(wildcard $(dir)/*.os.*.cpp)), \
|
||||||
|
$(notdir $(wildcard $(dir)/*.cpp))))
|
||||||
|
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).cpp)))
|
||||||
|
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).cpp)))
|
||||||
|
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).cpp)))
|
||||||
|
|
||||||
|
SFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.s)) $(notdir $(wildcard $(dir)/*.board.*.s)) $(notdir $(wildcard $(dir)/*.os.*.s)), \
|
||||||
|
$(notdir $(wildcard $(dir)/*.s))))
|
||||||
|
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).s)))
|
||||||
|
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).s)))
|
||||||
|
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).s)))
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# 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 .,_,$(subst -,_,$(BINFILES))))
|
||||||
|
|
||||||
|
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
|
-I.
|
||||||
|
|
||||||
|
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib -L$(dir)/$(ATMOSPHERE_LIBRARY_DIR))
|
||||||
|
|
||||||
|
.PHONY: $(BUILD) clean all
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
all: $(BUILD) check_libexo
|
||||||
|
|
||||||
|
$(BUILD): check_libexo
|
||||||
|
@[ -d $@ ] || mkdir -p $@
|
||||||
|
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||||
|
|
||||||
|
check_libexo:
|
||||||
|
@$(MAKE) --no-print-directory -C ../../libraries/libexosphere arm
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
clean:
|
||||||
|
@echo clean ...
|
||||||
|
@rm -fr $(BUILD) $(OUTPUT).bin $(OUTPUT).elf *.lz4
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
.PHONY: all
|
||||||
|
|
||||||
|
DEPENDS := $(OFILES:.o=.d)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# main targets
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
all : $(OUTPUT).bin
|
||||||
|
|
||||||
|
$(OUTPUT).bin : $(OUTPUT).elf
|
||||||
|
$(OBJCOPY) -S -O binary --set-section-flags .bss=alloc,load,contents $< $@
|
||||||
|
@echo built ... $(notdir $@)
|
||||||
|
|
||||||
|
$(OUTPUT).elf : $(OFILES) ../../../libraries/libexosphere/$(ATMOSPHERE_LIBRARY_DIR)/libexosphere.a
|
||||||
|
|
||||||
|
%.elf:
|
||||||
|
@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.h: %.bin
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(bin2o)
|
||||||
|
|
||||||
|
-include $(DEPENDS)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------------
|
99
exosphere2/warmboot/source/warmboot_bootrom_workaround.cpp
Normal file
99
exosphere2/warmboot/source/warmboot_bootrom_workaround.cpp
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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 <exosphere.hpp>
|
||||||
|
#include "warmboot_clkrst.hpp"
|
||||||
|
|
||||||
|
namespace ams::warmboot {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr inline const uintptr_t CLKRST = secmon::MemoryRegionPhysicalDeviceClkRst.GetAddress();
|
||||||
|
constexpr inline const uintptr_t EMC = EMC_ADDRESS(0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplyMbistWorkaround() {
|
||||||
|
/* Clear all LVL2 clock gate overrides to zero. */
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA, 0);
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB, 0);
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRC, 0);
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD, 0);
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRE, 0);
|
||||||
|
|
||||||
|
/* Clear clock enable for all but a select few devices. */
|
||||||
|
auto devices_to_clear_l = reg::Read(CLKRST + CLK_RST_CONTROLLER_CLK_OUT_ENB_L);
|
||||||
|
reg::ClearBits(static_cast<volatile u32 &>(devices_to_clear_l), CLK_RST_REG_BITS_MASK(CLK_ENB_L_CLK_ENB_RTC ),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_L_CLK_ENB_TMR ),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_L_CLK_ENB_GPIO ),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_L_CLK_ENB_CACHE2));
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_ENB_L_CLR, devices_to_clear_l);
|
||||||
|
|
||||||
|
auto devices_to_clear_h = reg::Read(CLKRST + CLK_RST_CONTROLLER_CLK_OUT_ENB_H);
|
||||||
|
reg::ClearBits(static_cast<volatile u32 &>(devices_to_clear_h), CLK_RST_REG_BITS_MASK(CLK_ENB_H_CLK_ENB_MEM ),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_H_CLK_ENB_PMC ),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_H_CLK_ENB_FUSE),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_H_CLK_ENB_EMC ));
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_ENB_H_CLR, devices_to_clear_h);
|
||||||
|
|
||||||
|
auto devices_to_clear_u = reg::Read(CLKRST + CLK_RST_CONTROLLER_CLK_OUT_ENB_U);
|
||||||
|
reg::ClearBits(static_cast<volatile u32 &>(devices_to_clear_u), CLK_RST_REG_BITS_MASK(CLK_ENB_U_CLK_ENB_CSITE),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_U_CLK_ENB_IRAMA),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_U_CLK_ENB_IRAMB),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_U_CLK_ENB_IRAMC),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_U_CLK_ENB_IRAMD),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_U_CLK_ENB_CRAM2));
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_ENB_U_CLR, devices_to_clear_u);
|
||||||
|
|
||||||
|
auto devices_to_clear_v = reg::Read(CLKRST + CLK_RST_CONTROLLER_CLK_OUT_ENB_V);
|
||||||
|
reg::ClearBits(static_cast<volatile u32 &>(devices_to_clear_v), CLK_RST_REG_BITS_MASK(CLK_ENB_V_CLK_ENB_MSELECT ),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_V_CLK_ENB_SPDIF_DOUBLER),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_V_CLK_ENB_TZRAM ),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_V_CLK_ENB_SE ));
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_ENB_V_CLR, devices_to_clear_v);
|
||||||
|
|
||||||
|
auto devices_to_clear_w = reg::Read(CLKRST + CLK_RST_CONTROLLER_CLK_OUT_ENB_W);
|
||||||
|
reg::ClearBits(static_cast<volatile u32 &>(devices_to_clear_w), CLK_RST_REG_BITS_MASK(CLK_ENB_W_CLK_ENB_PCIERX0),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_W_CLK_ENB_PCIERX1),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_W_CLK_ENB_PCIERX2),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_W_CLK_ENB_PCIERX3),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_W_CLK_ENB_PCIERX4),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_W_CLK_ENB_PCIERX5),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_W_CLK_ENB_ENTROPY));
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_ENB_W_CLR, devices_to_clear_w);
|
||||||
|
|
||||||
|
auto devices_to_clear_x = reg::Read(CLKRST + CLK_RST_CONTROLLER_CLK_OUT_ENB_X);
|
||||||
|
reg::ClearBits(static_cast<volatile u32 &>(devices_to_clear_x), CLK_RST_REG_BITS_MASK(CLK_ENB_X_CLK_ENB_MC_CAPA ),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_X_CLK_ENB_MC_CBPA ),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_X_CLK_ENB_MC_CPU ),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_X_CLK_ENB_MC_BBC ),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_X_CLK_ENB_EMC_DLL ),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_X_CLK_ENB_GPU ),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_X_CLK_ENB_DBGAPB ),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_X_CLK_ENB_PLLG_REF));
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_ENB_X_CLR, devices_to_clear_x);
|
||||||
|
|
||||||
|
auto devices_to_clear_y = reg::Read(CLKRST + CLK_RST_CONTROLLER_CLK_OUT_ENB_Y);
|
||||||
|
reg::ClearBits(static_cast<volatile u32 &>(devices_to_clear_y), CLK_RST_REG_BITS_MASK(CLK_ENB_Y_CLK_ENB_MC_CCPA),
|
||||||
|
CLK_RST_REG_BITS_MASK(CLK_ENB_Y_CLK_ENB_MC_CDPA));
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_ENB_Y_CLR, devices_to_clear_y);
|
||||||
|
|
||||||
|
/* If CH1 is enabled, enable clock to MC1. */
|
||||||
|
if (reg::HasValue(EMC + EMC_FBIO_CFG7, EMC_REG_BITS_ENUM(FBIO_CFG7_CH1_ENABLE, ENABLE))) {
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_ENB_W_SET, CLK_RST_REG_BITS_ENUM(CLK_ENB_W_CLK_ENB_MC1, ENABLE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
23
exosphere2/warmboot/source/warmboot_bootrom_workaround.hpp
Normal file
23
exosphere2/warmboot/source/warmboot_bootrom_workaround.hpp
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <exosphere.hpp>
|
||||||
|
|
||||||
|
namespace ams::warmboot {
|
||||||
|
|
||||||
|
void ApplyMbistWorkaround();
|
||||||
|
|
||||||
|
}
|
46
exosphere2/warmboot/source/warmboot_clkrst.cpp
Normal file
46
exosphere2/warmboot/source/warmboot_clkrst.cpp
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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 <exosphere.hpp>
|
||||||
|
#include "warmboot_clkrst.hpp"
|
||||||
|
|
||||||
|
namespace ams::warmboot {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr inline const uintptr_t CLKRST = secmon::MemoryRegionPhysicalDeviceClkRst.GetAddress();
|
||||||
|
constexpr inline const uintptr_t PMC = secmon::MemoryRegionPhysicalDevicePmc.GetAddress();
|
||||||
|
constexpr inline const uintptr_t TIMER = secmon::MemoryRegionPhysicalDeviceTimer.GetAddress();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigureOscillators() {
|
||||||
|
/* Enable the crystal oscillator, and copy the drive strength from pmc. */
|
||||||
|
const auto xofs = reg::GetValue(PMC + APBDEV_PMC_OSC_EDPD_OVER, PMC_REG_BITS_MASK(OSC_EDPD_OVER_XOFS));
|
||||||
|
|
||||||
|
reg::ReadWrite(CLKRST + CLK_RST_CONTROLLER_OSC_CTRL, CLK_RST_REG_BITS_ENUM (OSC_CTRL_XOE, ENABLE),
|
||||||
|
CLK_RST_REG_BITS_VALUE(OSC_CTRL_XOFS, xofs));
|
||||||
|
|
||||||
|
/* Configure CLK_M_DIVISOR to 2. */
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_SPARE_REG0, CLK_RST_REG_BITS_ENUM(SPARE_REG0_CLK_M_DIVISOR, CLK_M_DIVISOR2));
|
||||||
|
reg::Read(CLKRST + CLK_RST_CONTROLLER_SPARE_REG0);
|
||||||
|
|
||||||
|
/* Restore TIMERUS config to 19.2 MHz. */
|
||||||
|
reg::Write(TIMER + TIMERUS_USEC_CFG, TIMER_REG_BITS_VALUE(USEC_CFG_USEC_DIVIDEND, 5 - 1),
|
||||||
|
TIMER_REG_BITS_VALUE(USEC_CFG_USEC_DIVISOR, 96 - 1));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
23
exosphere2/warmboot/source/warmboot_clkrst.hpp
Normal file
23
exosphere2/warmboot/source/warmboot_clkrst.hpp
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <exosphere.hpp>
|
||||||
|
|
||||||
|
namespace ams::warmboot {
|
||||||
|
|
||||||
|
void ConfigureOscillators();
|
||||||
|
|
||||||
|
}
|
219
exosphere2/warmboot/source/warmboot_cpu_cluster.cpp
Normal file
219
exosphere2/warmboot/source/warmboot_cpu_cluster.cpp
Normal file
|
@ -0,0 +1,219 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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 <exosphere.hpp>
|
||||||
|
#include "warmboot_clkrst.hpp"
|
||||||
|
#include "warmboot_util.hpp"
|
||||||
|
|
||||||
|
namespace ams::warmboot {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr inline const uintptr_t APB_MISC = secmon::MemoryRegionPhysicalDeviceApbMisc.GetAddress();
|
||||||
|
constexpr inline const uintptr_t CLKRST = secmon::MemoryRegionPhysicalDeviceClkRst.GetAddress();
|
||||||
|
constexpr inline const uintptr_t FLOW_CTLR = secmon::MemoryRegionPhysicalDeviceFlowController.GetAddress();
|
||||||
|
constexpr inline const uintptr_t GPIO = secmon::MemoryRegionPhysicalDeviceGpio.GetAddress();
|
||||||
|
constexpr inline const uintptr_t MSELECT = MSELECT(0);
|
||||||
|
constexpr inline const uintptr_t PMC = secmon::MemoryRegionPhysicalDevicePmc.GetAddress();
|
||||||
|
constexpr inline const uintptr_t SYSTEM = secmon::MemoryRegionPhysicalDeviceSystem.GetAddress();
|
||||||
|
|
||||||
|
ALWAYS_INLINE void EnableClusterPartition(const reg::BitsValue value, APBDEV_PMC_PWRGATE_TOGGLE_PARTID part_id) {
|
||||||
|
/* Toggle the partitions if necessary. */
|
||||||
|
if (!reg::HasValue(PMC + APBDEV_PMC_PWRGATE_STATUS, value)) {
|
||||||
|
reg::Write(PMC + APBDEV_PMC_PWRGATE_TOGGLE, PMC_REG_BITS_ENUM (PWRGATE_TOGGLE_START, ENABLE),
|
||||||
|
PMC_REG_BITS_VALUE(PWRGATE_TOGGLE_PARTID, part_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for the toggle to complete. */
|
||||||
|
while (!reg::HasValue(PMC + APBDEV_PMC_PWRGATE_STATUS, value)) { /* ... */ }
|
||||||
|
|
||||||
|
/* Remove clamping. */
|
||||||
|
reg::Write(PMC + APBDEV_PMC_REMOVE_CLAMPING_CMD, value);
|
||||||
|
|
||||||
|
/* Wait for clamping to be removed. */
|
||||||
|
while (reg::HasValue(PMC + APBDEV_PMC_CLAMP_STATUS, value)) { /* ... */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitializeCpuCluster() {
|
||||||
|
/* Set CoreSight reset. */
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_RST_DEV_U_SET, CLK_RST_REG_BITS_ENUM(RST_DEV_U_SET_SET_CSITE_RST, ENABLE));
|
||||||
|
|
||||||
|
/* Restore PROD setting to CPU_SOFTRST_CTRL2 by clearing CAR2PMC_CPU_ACK_WIDTH. */
|
||||||
|
reg::ReadWrite(CLKRST + CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2, CLK_RST_REG_BITS_VALUE(CPU_SOFTRST_CTRL2_CAR2PMC_CPU_ACK_WIDTH, 0));
|
||||||
|
|
||||||
|
/* Restore the CPU reset vector from PMC scratch. */
|
||||||
|
reg::Write(SYSTEM + SB_AA64_RESET_LOW, reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH34) | 1);
|
||||||
|
reg::Write(SYSTEM + SB_AA64_RESET_HIGH, reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH35));
|
||||||
|
|
||||||
|
/* Configure SUPER_CCLKG_DIVIDER. */
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_SUPER_CCLKG_DIVIDER, CLK_RST_REG_BITS_ENUM (SUPER_CCLKG_DIVIDER_SUPER_CDIV_ENB, ENABLE),
|
||||||
|
CLK_RST_REG_BITS_ENUM (SUPER_CCLK_DIVIDER_SUPER_CDIV_DIS_FROM_COP_FIQ, NO_IMPACT),
|
||||||
|
CLK_RST_REG_BITS_ENUM (SUPER_CCLK_DIVIDER_SUPER_CDIV_DIS_FROM_CPU_FIQ, NO_IMPACT),
|
||||||
|
CLK_RST_REG_BITS_ENUM (SUPER_CCLK_DIVIDER_SUPER_CDIV_DIS_FROM_COP_IRQ, NO_IMPACT),
|
||||||
|
CLK_RST_REG_BITS_ENUM (SUPER_CCLK_DIVIDER_SUPER_CDIV_DIS_FROM_CPU_IRQ, NO_IMPACT),
|
||||||
|
CLK_RST_REG_BITS_VALUE(SUPER_CCLK_DIVIDER_SUPER_CDIV_DIVIDEND, 0),
|
||||||
|
CLK_RST_REG_BITS_VALUE(SUPER_CCLK_DIVIDER_SUPER_CDIV_DIVISOR, 0));
|
||||||
|
|
||||||
|
/* Configure SUPER_CCLKLP_DIVIDER. */
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_SUPER_CCLKLP_DIVIDER, CLK_RST_REG_BITS_ENUM (SUPER_CCLKLP_DIVIDER_SUPER_CDIV_ENB, ENABLE),
|
||||||
|
CLK_RST_REG_BITS_ENUM (SUPER_CCLK_DIVIDER_SUPER_CDIV_DIS_FROM_COP_FIQ, NO_IMPACT),
|
||||||
|
CLK_RST_REG_BITS_ENUM (SUPER_CCLK_DIVIDER_SUPER_CDIV_DIS_FROM_CPU_FIQ, NO_IMPACT),
|
||||||
|
CLK_RST_REG_BITS_ENUM (SUPER_CCLK_DIVIDER_SUPER_CDIV_DIS_FROM_COP_IRQ, NO_IMPACT),
|
||||||
|
CLK_RST_REG_BITS_ENUM (SUPER_CCLK_DIVIDER_SUPER_CDIV_DIS_FROM_CPU_IRQ, NO_IMPACT),
|
||||||
|
CLK_RST_REG_BITS_VALUE(SUPER_CCLK_DIVIDER_SUPER_CDIV_DIVIDEND, 0),
|
||||||
|
CLK_RST_REG_BITS_VALUE(SUPER_CCLK_DIVIDER_SUPER_CDIV_DIVISOR, 0));
|
||||||
|
|
||||||
|
/* Enable CoreSight clock. */
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_ENB_U_SET, CLK_RST_REG_BITS_ENUM(CLK_ENB_U_SET_SET_CLK_ENB_CSITE, ENABLE));
|
||||||
|
|
||||||
|
/* Clear CoreSight reset. */
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_RST_DEV_U_CLR, CLK_RST_REG_BITS_ENUM(RST_DEV_U_CLR_CLR_CSITE_RST, ENABLE));
|
||||||
|
|
||||||
|
/* Select MSELECT clock source as PLLP_OUT0 with divider of 4. */
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT, CLK_RST_REG_BITS_ENUM (CLK_SOURCE_MSELECT_MSELECT_CLK_SRC, PLLP_OUT0),
|
||||||
|
CLK_RST_REG_BITS_VALUE(CLK_SOURCE_MSELECT_MSELECT_CLK_DIVISOR, 6));
|
||||||
|
|
||||||
|
/* Enable clock to MSELECT. */
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_ENB_V_SET, CLK_RST_REG_BITS_ENUM(CLK_ENB_V_SET_SET_CLK_ENB_MSELECT, ENABLE));
|
||||||
|
|
||||||
|
/* Wait two microseconds, then take MSELECT out of reset. */
|
||||||
|
util::WaitMicroSeconds(2);
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_RST_DEV_V_CLR, CLK_RST_REG_BITS_ENUM(RST_DEV_V_CLR_CLR_MSELECT_RST, ENABLE));
|
||||||
|
|
||||||
|
/* Workaround bug by disabling MSELECT error mechanism and enabling WRAP type conversion. */
|
||||||
|
reg::ReadWrite(MSELECT + MSELECT_CONFIG, MSELECT_REG_BITS_ENUM(CONFIG_ERR_RESP_EN_SLAVE1, DISABLE),
|
||||||
|
MSELECT_REG_BITS_ENUM(CONFIG_ERR_RESP_EN_SLAVE2, DISABLE),
|
||||||
|
MSELECT_REG_BITS_ENUM(CONFIG_WRAP_TO_INCR_SLAVE0, ENABLE),
|
||||||
|
MSELECT_REG_BITS_ENUM(CONFIG_WRAP_TO_INCR_SLAVE1, ENABLE),
|
||||||
|
MSELECT_REG_BITS_ENUM(CONFIG_WRAP_TO_INCR_SLAVE2, ENABLE));
|
||||||
|
|
||||||
|
/* Disable PLLX. */
|
||||||
|
reg::ReadWrite(CLKRST + CLK_RST_CONTROLLER_PLLX_BASE, CLK_RST_REG_BITS_ENUM(PLLX_BASE_PLLX_ENABLE, DISABLE));
|
||||||
|
|
||||||
|
/* Clear bit 0 of PMC Scratch 190. */
|
||||||
|
reg::ReadWrite(PMC + APBDEV_PMC_SCRATCH190, REG_BITS_VALUE(0, 1, 0));
|
||||||
|
|
||||||
|
/* Clear PMC_DPD_SAMPLE, and wait 10 us for clear to take effect. */
|
||||||
|
reg::Write(PMC + APBDEV_PMC_DPD_SAMPLE, 0);
|
||||||
|
util::WaitMicroSeconds(10);
|
||||||
|
|
||||||
|
/* Configure UART2_RTS low (GPIO controller 2 G). */
|
||||||
|
reg::ReadWrite(GPIO + 0x108, REG_BITS_VALUE(2, 1, 1)); /* GPIO_CNF */
|
||||||
|
reg::ReadWrite(GPIO + 0x118, REG_BITS_VALUE(2, 1, 1)); /* GPIO_OE */
|
||||||
|
reg::ReadWrite(GPIO + 0x128, REG_BITS_VALUE(2, 1, 0)); /* GPIO_OUT */
|
||||||
|
|
||||||
|
/* Tristate CLDVFS PWN. */
|
||||||
|
reg::Write(APB_MISC + PINMUX_AUX_DVFS_PWM, PINMUX_REG_BITS_ENUM(AUX_TRISTATE, TRISTATE),
|
||||||
|
PINMUX_REG_BITS_ENUM(AUX_DVFS_PWM_PM, CLDVFS));
|
||||||
|
reg::Read(APB_MISC + PINMUX_AUX_DVFS_PWM);
|
||||||
|
|
||||||
|
/* Restore PWR_I2C E_INPUT. */
|
||||||
|
reg::Write(APB_MISC + PINMUX_AUX_PWR_I2C_SCL, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE));
|
||||||
|
reg::Write(APB_MISC + PINMUX_AUX_PWR_I2C_SDA, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE));
|
||||||
|
|
||||||
|
/* Enable CLDVFS clock. */
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_ENB_W_SET, CLK_RST_REG_BITS_ENUM(CLK_ENB_W_SET_SET_CLK_ENB_DVFS, ENABLE));
|
||||||
|
|
||||||
|
/* Set CLDVFS clock source/divider. */
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_REF, CLK_RST_REG_BITS_ENUM (CLK_SOURCE_DVFS_REF_DVFS_REF_CLK_SRC, PLLP_OUT0),
|
||||||
|
CLK_RST_REG_BITS_VALUE(CLK_SOURCE_DVFS_REF_DVFS_REF_DIVISOR, 14));
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_SOC, CLK_RST_REG_BITS_ENUM (CLK_SOURCE_DVFS_SOC_DVFS_SOC_CLK_SRC, PLLP_OUT0),
|
||||||
|
CLK_RST_REG_BITS_VALUE(CLK_SOURCE_DVFS_SOC_DVFS_SOC_DIVISOR, 14));
|
||||||
|
|
||||||
|
/* Enable PWR_I2C controller (I2C5). */
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_ENB_H_SET, CLK_RST_REG_BITS_ENUM(CLK_ENB_H_SET_SET_CLK_ENB_I2C5, ENABLE));
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_RST_DEV_H_SET, CLK_RST_REG_BITS_ENUM(RST_DEV_H_SET_SET_I2C5_RST, ENABLE));
|
||||||
|
util::WaitMicroSeconds(5);
|
||||||
|
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_SOURCE_I2C5, CLK_RST_REG_BITS_ENUM (CLK_SOURCE_I2C5_I2C5_CLK_SRC, PLLP_OUT0),
|
||||||
|
CLK_RST_REG_BITS_VALUE(CLK_SOURCE_I2C5_I2C5_CLK_DIVISOR, 4));
|
||||||
|
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_RST_DEV_H_CLR, CLK_RST_REG_BITS_ENUM(RST_DEV_H_CLR_CLR_I2C5_RST, ENABLE));
|
||||||
|
|
||||||
|
/* Set the EN bit in pmic regulator. */
|
||||||
|
pmic::SetEnBit(fuse::GetRegulator());
|
||||||
|
|
||||||
|
/* Wait 2ms. */
|
||||||
|
util::WaitMicroSeconds(2'000);
|
||||||
|
|
||||||
|
/* Enable power to the CRAIL partition. */
|
||||||
|
EnableClusterPartition(PMC_REG_BITS_ENUM(PWRGATE_STATUS_CRAIL, ON), APBDEV_PMC_PWRGATE_TOGGLE_PARTID_CRAIL);
|
||||||
|
|
||||||
|
/* Remove software clamp to CRAIL. */
|
||||||
|
reg::Write(PMC + APBDEV_PMC_SET_SW_CLAMP, 0);
|
||||||
|
reg::Write(PMC + APBDEV_PMC_REMOVE_CLAMPING_CMD, PMC_REG_BITS_ENUM(REMOVE_CLAMPING_COMMAND_CRAIL, ENABLE));
|
||||||
|
while (reg::HasValue(PMC + APBDEV_PMC_CLAMP_STATUS, PMC_REG_BITS_ENUM(CLAMP_STATUS_CRAIL, ENABLE))) { /* ... */ }
|
||||||
|
|
||||||
|
/* Spinloop 8 times, to add a little delay. */
|
||||||
|
SpinLoop(8);
|
||||||
|
|
||||||
|
/* Disable PWR_I2C controller (I2C5). */
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_RST_DEV_H_SET, CLK_RST_REG_BITS_ENUM(RST_DEV_H_SET_SET_I2C5_RST, ENABLE));
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_ENB_H_CLR, CLK_RST_REG_BITS_ENUM(CLK_ENB_H_CLR_CLR_CLK_ENB_I2C5, ENABLE));
|
||||||
|
|
||||||
|
/* Disable CLDVFS clock. */
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_ENB_W_CLR, CLK_RST_REG_BITS_ENUM(CLK_ENB_W_CLR_CLR_CLK_ENB_DVFS, ENABLE));
|
||||||
|
|
||||||
|
/* Perform fast cluster RAM repair if needed. */
|
||||||
|
if (!reg::HasValue(FLOW_CTLR + FLOW_CTLR_BPMP_CLUSTER_CONTROL, FLOW_REG_BITS_ENUM(BPMP_CLUSTER_CONTROL_ACTIVE_CLUSTER, SLOW))) {
|
||||||
|
reg::Write(FLOW_CTLR + FLOW_CTLR_RAM_REPAIR, FLOW_REG_BITS_ENUM(RAM_REPAIR_REQ, ENABLE));
|
||||||
|
|
||||||
|
while (!reg::HasValue(FLOW_CTLR + FLOW_CTLR_RAM_REPAIR, FLOW_REG_BITS_ENUM(RAM_REPAIR_STS, DONE))) {
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable power to the non-cpu partition. */
|
||||||
|
EnableClusterPartition(PMC_REG_BITS_ENUM(PWRGATE_STATUS_C0NC, ON), APBDEV_PMC_PWRGATE_TOGGLE_PARTID_C0NC);
|
||||||
|
|
||||||
|
/* Enable clock to PLLP_OUT_CPU. */
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_ENB_Y_SET, CLK_RST_REG_BITS_ENUM(CLK_ENB_Y_SET_SET_CLK_ENB_PLLP_OUT_CPU, ENABLE));
|
||||||
|
util::WaitMicroSeconds(2);
|
||||||
|
|
||||||
|
/* Enable clock to the cpu complex. */
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_ENB_L_SET, CLK_RST_REG_BITS_ENUM(CLK_ENB_L_SET_SET_CLK_ENB_CPU, ENABLE));
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_ENB_V_SET, CLK_RST_REG_BITS_ENUM(CLK_ENB_V_SET_SET_CLK_ENB_CPUG, ENABLE));
|
||||||
|
util::WaitMicroSeconds(10);
|
||||||
|
|
||||||
|
/* Select cpu complex clock source. */
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_CCLKG_BURST_POLICY, CLK_RST_REG_BITS_ENUM(CCLK_BURST_POLICY_CWAKEUP_IDLE_SOURCE, PLLP_OUT0),
|
||||||
|
CLK_RST_REG_BITS_ENUM(CCLK_BURST_POLICY_CWAKEUP_RUN_SOURCE, PLLP_OUT0),
|
||||||
|
CLK_RST_REG_BITS_ENUM(CCLK_BURST_POLICY_CWAKEUP_IRQ_SOURCE, PLLP_OUT0),
|
||||||
|
CLK_RST_REG_BITS_ENUM(CCLK_BURST_POLICY_CWAKEUP_FIQ_SOURCE, PLLP_OUT0),
|
||||||
|
CLK_RST_REG_BITS_ENUM(CCLK_BURST_POLICY_CPU_STATE, RUN));
|
||||||
|
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_CCLKLP_BURST_POLICY, CLK_RST_REG_BITS_ENUM(CCLK_BURST_POLICY_CWAKEUP_IDLE_SOURCE, PLLP_OUT0),
|
||||||
|
CLK_RST_REG_BITS_ENUM(CCLK_BURST_POLICY_CWAKEUP_RUN_SOURCE, PLLP_OUT0),
|
||||||
|
CLK_RST_REG_BITS_ENUM(CCLK_BURST_POLICY_CWAKEUP_IRQ_SOURCE, PLLP_OUT0),
|
||||||
|
CLK_RST_REG_BITS_ENUM(CCLK_BURST_POLICY_CWAKEUP_FIQ_SOURCE, PLLP_OUT0),
|
||||||
|
CLK_RST_REG_BITS_ENUM(CCLK_BURST_POLICY_CPU_STATE, RUN));
|
||||||
|
util::WaitMicroSeconds(10);
|
||||||
|
|
||||||
|
/* Wake non-cpu out of reset. */
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR, CLK_RST_REG_BITS_ENUM(RST_CPUG_CMPLX_CLR_CLR_NONCPURESET, ENABLE));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PowerOnCpu() {
|
||||||
|
/* Enable power to the CE0 partition. */
|
||||||
|
EnableClusterPartition(PMC_REG_BITS_ENUM(PWRGATE_STATUS_CE0, ON), APBDEV_PMC_PWRGATE_TOGGLE_PARTID_CE0);
|
||||||
|
|
||||||
|
/* Clear CPU reset. */
|
||||||
|
reg::Write(CLKRST + CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR, CLK_RST_REG_BITS_ENUM(RST_CPUG_CMPLX_CLR_CLR_CPURESET0, ENABLE),
|
||||||
|
CLK_RST_REG_BITS_ENUM(RST_CPUG_CMPLX_CLR_CLR_CORERESET0, ENABLE));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
24
exosphere2/warmboot/source/warmboot_cpu_cluster.hpp
Normal file
24
exosphere2/warmboot/source/warmboot_cpu_cluster.hpp
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <exosphere.hpp>
|
||||||
|
|
||||||
|
namespace ams::warmboot {
|
||||||
|
|
||||||
|
void InitializeCpuCluster();
|
||||||
|
void PowerOnCpu();
|
||||||
|
|
||||||
|
}
|
130
exosphere2/warmboot/source/warmboot_dram.cpp
Normal file
130
exosphere2/warmboot/source/warmboot_dram.cpp
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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 <exosphere.hpp>
|
||||||
|
#include "warmboot_dram.hpp"
|
||||||
|
|
||||||
|
namespace ams::warmboot {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr inline const uintptr_t APB_MISC = secmon::MemoryRegionPhysicalDeviceApbMisc.GetAddress();
|
||||||
|
constexpr inline const uintptr_t EMC = EMC_ADDRESS(0);
|
||||||
|
constexpr inline const uintptr_t EMC0 = EMC0_ADDRESS(0);
|
||||||
|
constexpr inline const uintptr_t EMC1 = EMC1_ADDRESS(0);
|
||||||
|
constexpr inline const uintptr_t MC = secmon::MemoryRegionPhysicalDeviceMemoryController.GetAddress();
|
||||||
|
constexpr inline const uintptr_t MC0 = secmon::MemoryRegionPhysicalDeviceMemoryController0.GetAddress();
|
||||||
|
constexpr inline const uintptr_t MC1 = secmon::MemoryRegionPhysicalDeviceMemoryController1.GetAddress();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void RestrictBpmpAccessToMainMemory() {
|
||||||
|
/* Bpmp memory access is restricted by forcing internal access to an invalid carveout. */
|
||||||
|
constexpr u32 ForceInternalAccess0 = reg::Encode(MC_REG_BITS_ENUM(CLIENT_ACCESS0_AVPCARM7R, ENABLE));
|
||||||
|
constexpr u32 ForceInternalAccess1 = reg::Encode(MC_REG_BITS_ENUM(CLIENT_ACCESS1_AVPCARM7W, ENABLE));
|
||||||
|
|
||||||
|
constexpr u32 CarveoutConfig = reg::Encode(MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_IS_WPR, DISABLED),
|
||||||
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_FORCE_APERTURE_ID_MATCH, DISABLED),
|
||||||
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ALLOW_APERTURE_ID_MISMATCH, DISABLED),
|
||||||
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_RD_EN, DISABLED),
|
||||||
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_WR_EN, DISABLED),
|
||||||
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_SEND_CFG_TO_GPU, DISABLED),
|
||||||
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS),
|
||||||
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS),
|
||||||
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS),
|
||||||
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS),
|
||||||
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS),
|
||||||
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS),
|
||||||
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS),
|
||||||
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS),
|
||||||
|
MC_REG_BITS_VALUE(SECURITY_CARVEOUT_CFG0_APERTURE_ID, 0),
|
||||||
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL3, DISABLED),
|
||||||
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL2, DISABLED),
|
||||||
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL1, DISABLED),
|
||||||
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL0, ENABLED),
|
||||||
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL3, DISABLED),
|
||||||
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL2, DISABLED),
|
||||||
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL1, DISABLED),
|
||||||
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL0, ENABLED),
|
||||||
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ADDRESS_TYPE, UNTRANSLATED_ONLY),
|
||||||
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_LOCK_MODE, LOCKED),
|
||||||
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_PROTECT_MODE, TZ_SECURE));
|
||||||
|
|
||||||
|
/* Specify a 128KB carveout at NULL with no clients allowed access, and bpmp forced to access. */
|
||||||
|
reg::Write(MC + MC_SECURITY_CARVEOUT4_BOM, 0);
|
||||||
|
reg::Write(MC + MC_SECURITY_CARVEOUT4_BOM_HI, 0);
|
||||||
|
reg::Write(MC + MC_SECURITY_CARVEOUT4_SIZE_128KB, 1);
|
||||||
|
reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0, 0);
|
||||||
|
reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_ACCESS1, 0);
|
||||||
|
reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2, 0);
|
||||||
|
reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_ACCESS3, 0);
|
||||||
|
reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4, 0);
|
||||||
|
reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS0, ForceInternalAccess0);
|
||||||
|
reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS1, ForceInternalAccess1);
|
||||||
|
reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS2, 0);
|
||||||
|
reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3, 0);
|
||||||
|
reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4, 0);
|
||||||
|
reg::Write(MC + MC_SECURITY_CARVEOUT4_CFG0, CarveoutConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RestoreRamSvop() {
|
||||||
|
reg::ReadWrite(APB_MISC + APB_MISC_GP_ASDBGREG, APB_MISC_REG_BITS_VALUE(GP_ASDBGREG_CFG2TMC_RAM_SVOP_PDP, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigureEmcPmacroTraining() {
|
||||||
|
/* Disable writes to BYTE0-7. */
|
||||||
|
reg::Write(EMC + EMC_PMACRO_CFG_PM_GLOBAL_0, EMC_REG_BITS_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE0, ENABLE),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE1, ENABLE),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE2, ENABLE),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE3, ENABLE),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE4, ENABLE),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE5, ENABLE),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE6, ENABLE),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE7, ENABLE),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_CMD0, DISABLE),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_CMD1, DISABLE),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_CMD2, DISABLE),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_CMD3, DISABLE));
|
||||||
|
|
||||||
|
/* Set E_WRPTR on Channel 0. */
|
||||||
|
reg::Write(EMC + EMC_PMACRO_TRAINING_CTRL_0, EMC_REG_BITS_ENUM(PMACRO_TRAINING_CTRL_0_CH0_TRAINING_ENABLED, DISABLED),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_TRAINING_CTRL_0_CH0_TRAINING_TRAIN_QPOP, DISABLED),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_TRAINING_CTRL_0_CH0_TRAINING_RX_E_DIRECT_ZI, DISABLED),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_TRAINING_CTRL_0_CH0_TRAINING_E_WRPTR, ENABLED),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_TRAINING_CTRL_0_CH0_TRAINING_DRV_DQS, DISABLED));
|
||||||
|
|
||||||
|
/* Set E_WRPTR on Channel 1. */
|
||||||
|
reg::Write(EMC + EMC_PMACRO_TRAINING_CTRL_1, EMC_REG_BITS_ENUM(PMACRO_TRAINING_CTRL_1_CH1_TRAINING_ENABLED, DISABLED),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_TRAINING_CTRL_1_CH1_TRAINING_TRAIN_QPOP, DISABLED),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_TRAINING_CTRL_1_CH1_TRAINING_RX_E_DIRECT_ZI, DISABLED),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_TRAINING_CTRL_1_CH1_TRAINING_E_WRPTR, ENABLED),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_TRAINING_CTRL_1_CH1_TRAINING_DRV_DQS, DISABLED));
|
||||||
|
|
||||||
|
/* Re-enable writes to BYTE0-7. */
|
||||||
|
reg::Write(EMC + EMC_PMACRO_CFG_PM_GLOBAL_0, EMC_REG_BITS_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE0, DISABLE),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE1, DISABLE),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE2, DISABLE),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE3, DISABLE),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE4, DISABLE),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE5, DISABLE),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE6, DISABLE),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE7, DISABLE),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_CMD0, DISABLE),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_CMD1, DISABLE),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_CMD2, DISABLE),
|
||||||
|
EMC_REG_BITS_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_CMD3, DISABLE));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
25
exosphere2/warmboot/source/warmboot_dram.hpp
Normal file
25
exosphere2/warmboot/source/warmboot_dram.hpp
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <exosphere.hpp>
|
||||||
|
|
||||||
|
namespace ams::warmboot {
|
||||||
|
|
||||||
|
void RestrictBpmpAccessToMainMemory();
|
||||||
|
void RestoreRamSvop();
|
||||||
|
void ConfigureEmcPmacroTraining();
|
||||||
|
|
||||||
|
}
|
63
exosphere2/warmboot/source/warmboot_exception_vectors.s
Normal file
63
exosphere2/warmboot/source/warmboot_exception_vectors.s
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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 .vectors, "ax", %progbits
|
||||||
|
.align 3
|
||||||
|
.global warmboot_header
|
||||||
|
warmboot_header:
|
||||||
|
/* TODO: If Mariko warmboothax ever happens, generate a mariko header? */
|
||||||
|
/* Warmboot header. */
|
||||||
|
.word __total_size__
|
||||||
|
.rept 3
|
||||||
|
.word 0x00000000
|
||||||
|
.endr
|
||||||
|
|
||||||
|
/* RSA modulus. */
|
||||||
|
.rept 0x40
|
||||||
|
.word 0xFFFFFFFF
|
||||||
|
.endr
|
||||||
|
|
||||||
|
/* Padding */
|
||||||
|
.rept 4
|
||||||
|
.word 0x00000000
|
||||||
|
.endr
|
||||||
|
|
||||||
|
/* RSA signature */
|
||||||
|
.rept 0x40
|
||||||
|
.word 0xFFFFFFFF
|
||||||
|
.endr
|
||||||
|
|
||||||
|
/* Padding */
|
||||||
|
.rept 4
|
||||||
|
.word 0x00000000
|
||||||
|
.endr
|
||||||
|
|
||||||
|
/* Firmware metadata. */
|
||||||
|
.word __total_size__
|
||||||
|
.word _reset
|
||||||
|
.word _reset
|
||||||
|
.word __executable_size__
|
||||||
|
|
||||||
|
.global _reset
|
||||||
|
_reset:
|
||||||
|
b _ZN3ams8warmboot5StartEv
|
||||||
|
|
||||||
|
.global _metadata
|
||||||
|
_metadata:
|
||||||
|
.ascii "WBT0" /* Magic number */
|
||||||
|
.word 0x00000000 /* Target firmware. */
|
||||||
|
.word 0x00000000 /* Reserved */
|
||||||
|
.word 0x00000000 /* Reserved */
|
105
exosphere2/warmboot/source/warmboot_main.cpp
Normal file
105
exosphere2/warmboot/source/warmboot_main.cpp
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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 <exosphere.hpp>
|
||||||
|
#include "warmboot_bootrom_workaround.hpp"
|
||||||
|
#include "warmboot_clkrst.hpp"
|
||||||
|
#include "warmboot_cpu_cluster.hpp"
|
||||||
|
#include "warmboot_dram.hpp"
|
||||||
|
#include "warmboot_main.hpp"
|
||||||
|
#include "warmboot_misc.hpp"
|
||||||
|
#include "warmboot_secure_monitor.hpp"
|
||||||
|
|
||||||
|
namespace ams::warmboot {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr inline const uintptr_t PMC = secmon::MemoryRegionPhysicalDevicePmc.GetAddress();
|
||||||
|
constexpr inline const uintptr_t FLOW_CTLR = secmon::MemoryRegionPhysicalDeviceFlowController.GetAddress();
|
||||||
|
|
||||||
|
constexpr inline const uintptr_t ExpectedMetadataAddress = 0x40010244;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Main(const Metadata *metadata) {
|
||||||
|
/* Ensure that we're running under vaguely sane conditions. */
|
||||||
|
AMS_ABORT_UNLESS(metadata->magic == Metadata::Magic);
|
||||||
|
AMS_ABORT_UNLESS(metadata->target_firmware <= ams::TargetFirmware_Max);
|
||||||
|
|
||||||
|
/* Restrict the bpmp's access to dram. */
|
||||||
|
if (metadata->target_firmware >= TargetFirmware_4_0_0) {
|
||||||
|
RestrictBpmpAccessToMainMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure rtck-daisychaining/jtag. */
|
||||||
|
ConfigureMiscSystemDebug();
|
||||||
|
|
||||||
|
/* NOTE: Here, Nintendo checks that the number of burnt anti-downgrade fuses is valid. */
|
||||||
|
|
||||||
|
/* NOTE: Here, Nintendo validates that APBDEV_PMC_SECURE_SCRATCH32 contains the correct magic number for the current warmboot firmware revision. */
|
||||||
|
|
||||||
|
/* Validate that we're executing at the correct address. */
|
||||||
|
AMS_ABORT_UNLESS(reinterpret_cast<uintptr_t>(metadata) == ExpectedMetadataAddress);
|
||||||
|
|
||||||
|
/* Validate that we're executing on the bpmp. */
|
||||||
|
AMS_ABORT_UNLESS(reg::Read(PG_UP(PG_UP_TAG)) == PG_UP_TAG_PID_COP);
|
||||||
|
|
||||||
|
/* Configure fuse bypass. */
|
||||||
|
fuse::ConfigureFuseBypass();
|
||||||
|
|
||||||
|
/* Configure system oscillators. */
|
||||||
|
ConfigureOscillators();
|
||||||
|
|
||||||
|
/* Restore DRAM configuration. */
|
||||||
|
RestoreRamSvop();
|
||||||
|
ConfigureEmcPmacroTraining();
|
||||||
|
|
||||||
|
/* If on Erista, work around the bootrom mbist issue. */
|
||||||
|
if (fuse::GetSocType() == fuse::SocType_Erista) {
|
||||||
|
ApplyMbistWorkaround();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the cpu cluster. */
|
||||||
|
InitializeCpuCluster();
|
||||||
|
|
||||||
|
/* Restore the secure monitor to tzram. */
|
||||||
|
RestoreSecureMonitorToTzram(metadata->target_firmware);
|
||||||
|
|
||||||
|
/* Power on the cpu. */
|
||||||
|
PowerOnCpu();
|
||||||
|
|
||||||
|
/* Halt ourselves. */
|
||||||
|
const bool disable_jtag = metadata->target_firmware >= TargetFirmware_4_0_0;
|
||||||
|
while (true) {
|
||||||
|
reg::Write(secmon::MemoryRegionPhysicalDeviceFlowController.GetAddress() + FLOW_CTLR_HALT_COP_EVENTS, FLOW_REG_BITS_ENUM (HALT_COP_EVENTS_MODE, FLOW_MODE_STOP),
|
||||||
|
FLOW_REG_BITS_ENUM_SEL(HALT_COP_EVENTS_JTAG, disable_jtag, DISABLED, ENABLED));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NORETURN void ExceptionHandler() {
|
||||||
|
/* Write enable to MAIN_RESET. */
|
||||||
|
reg::Write(PMC + APBDEV_PMC_CNTRL, PMC_REG_BITS_ENUM(CNTRL_MAIN_RESET, ENABLE));
|
||||||
|
while (true) { /* ... */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ams::diag {
|
||||||
|
|
||||||
|
void AbortImpl() {
|
||||||
|
warmboot::ExceptionHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
31
exosphere2/warmboot/source/warmboot_main.hpp
Normal file
31
exosphere2/warmboot/source/warmboot_main.hpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <exosphere.hpp>
|
||||||
|
|
||||||
|
namespace ams::warmboot {
|
||||||
|
|
||||||
|
struct Metadata {
|
||||||
|
static constexpr u32 Magic = util::FourCC<'W','B','T','0'>::Code;
|
||||||
|
|
||||||
|
u32 magic;
|
||||||
|
ams::TargetFirmware target_firmware;
|
||||||
|
u32 reserved[2];
|
||||||
|
};
|
||||||
|
static_assert(util::is_pod<Metadata>::value);
|
||||||
|
static_assert(sizeof(Metadata) == 0x10);
|
||||||
|
|
||||||
|
}
|
56
exosphere2/warmboot/source/warmboot_misc.cpp
Normal file
56
exosphere2/warmboot/source/warmboot_misc.cpp
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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 <exosphere.hpp>
|
||||||
|
#include "warmboot_misc.hpp"
|
||||||
|
|
||||||
|
namespace ams::warmboot {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr inline const uintptr_t APB_MISC = secmon::MemoryRegionPhysicalDeviceApbMisc.GetAddress();
|
||||||
|
constexpr inline const uintptr_t PMC = secmon::MemoryRegionPhysicalDevicePmc.GetAddress();
|
||||||
|
constexpr inline const uintptr_t SYSTEM = secmon::MemoryRegionPhysicalDeviceSystem.GetAddress();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigureMiscSystemDebug() {
|
||||||
|
/* Enable RTCK daisy-chaining. */
|
||||||
|
reg::Write(APB_MISC + APB_MISC_PP_CONFIG_CTL, APB_MISC_REG_BITS_ENUM(PP_CONFIG_CTL_TBE, ENABLE));
|
||||||
|
|
||||||
|
/* If we're in production mode, perform JTAG configuration. */
|
||||||
|
/* NOTE: While this is what NVidia's code does, this is almost certainly a logic error. */
|
||||||
|
/* They intend to configure JTAG only when *not* in production mode. */
|
||||||
|
/* However, here we will do what they do, and not what they intend. */
|
||||||
|
const bool production_mode = fuse::IsOdmProductionMode();
|
||||||
|
if (production_mode) {
|
||||||
|
const bool jtag_sts = reg::HasValue(PMC + APBDEV_PMC_STICKY_BITS, PMC_REG_BITS_ENUM(STICKY_BITS_JTAG_STS, ENABLE));
|
||||||
|
|
||||||
|
reg::ReadWrite(SYSTEM + SB_PFCFG, SB_REG_BITS_ENUM_SEL(PFCFG_DBGEN, jtag_sts, ENABLE, DISABLE),
|
||||||
|
SB_REG_BITS_ENUM_SEL(PFCFG_NIDEN, jtag_sts, ENABLE, DISABLE),
|
||||||
|
SB_REG_BITS_ENUM_SEL(PFCFG_SPNIDEN, jtag_sts, ENABLE, DISABLE),
|
||||||
|
SB_REG_BITS_ENUM (PFCFG_SPIDEN, DISABLE));
|
||||||
|
|
||||||
|
reg::ReadWrite(APB_MISC + APB_MISC_PP_CONFIG_CTL, APB_MISC_REG_BITS_ENUM_SEL(PP_CONFIG_CTL_JTAG, jtag_sts, ENABLE, DISABLE));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure HDA codec disable. */
|
||||||
|
reg::ReadWrite(PMC + APBDEV_PMC_STICKY_BITS, PMC_REG_BITS_ENUM_SEL(STICKY_BITS_HDA_LPBK_DIS, production_mode, ENABLE, DISABLE));
|
||||||
|
|
||||||
|
/* Set E_INPUT in PINMUX_AUX_GPIO_PA6 (needed by the XUSB and SATA controllers). */
|
||||||
|
reg::ReadWrite(APB_MISC + PINMUX_AUX_GPIO_PA6, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
23
exosphere2/warmboot/source/warmboot_misc.hpp
Normal file
23
exosphere2/warmboot/source/warmboot_misc.hpp
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <exosphere.hpp>
|
||||||
|
|
||||||
|
namespace ams::warmboot {
|
||||||
|
|
||||||
|
void ConfigureMiscSystemDebug();
|
||||||
|
|
||||||
|
}
|
130
exosphere2/warmboot/source/warmboot_secure_monitor.cpp
Normal file
130
exosphere2/warmboot/source/warmboot_secure_monitor.cpp
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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 <exosphere.hpp>
|
||||||
|
#include "warmboot_secure_monitor.hpp"
|
||||||
|
|
||||||
|
namespace ams::warmboot {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr inline const uintptr_t PMC = secmon::MemoryRegionPhysicalDevicePmc.GetAddress();
|
||||||
|
|
||||||
|
constexpr inline const pkg1::AesKeySlot SavedAesKeySlots[] = {
|
||||||
|
pkg1::AesKeySlot_TzramSaveKek,
|
||||||
|
pkg1::AesKeySlot_RandomForUserWrap,
|
||||||
|
pkg1::AesKeySlot_RandomForKeyStorageWrap,
|
||||||
|
pkg1::AesKeySlot_DeviceMaster,
|
||||||
|
pkg1::AesKeySlot_Master,
|
||||||
|
pkg1::AesKeySlot_Device,
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE bool IsSavedAesKeySlot(int slot) {
|
||||||
|
for (const auto SavedSlot : SavedAesKeySlots) {
|
||||||
|
if (slot == SavedSlot) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearUnsavedSecurityEngineKeySlots() {
|
||||||
|
/* Clear unsaved aes keys and all ivs. */
|
||||||
|
for (int slot = 0; slot < se::AesKeySlotCount; ++slot) {
|
||||||
|
if (!IsSavedAesKeySlot(slot)) {
|
||||||
|
se::ClearAesKeySlot(slot);
|
||||||
|
}
|
||||||
|
se::ClearAesKeyIv(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear all rsa keys. */
|
||||||
|
for (int slot = 0; slot < se::RsaKeySlotCount; ++slot) {
|
||||||
|
se::ClearRsaKeySlot(slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RestoreEncryptedTzram(void * const tzram_dst, const void * const tzram_src, size_t tzram_size) {
|
||||||
|
/* Derive the save key from the save kek. */
|
||||||
|
const u32 key_source[se::AesBlockSize / sizeof(u32)] = { reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH24), reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH25), reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH26), reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH27)};
|
||||||
|
se::ClearAesKeySlot(pkg1::AesKeySlot_TzramSaveKey);
|
||||||
|
se::SetEncryptedAesKey256(pkg1::AesKeySlot_TzramSaveKey, pkg1::AesKeySlot_TzramSaveKek, key_source, sizeof(key_source));
|
||||||
|
|
||||||
|
/* Decrypt tzram. */
|
||||||
|
const u8 tzram_iv[se::AesBlockSize] = {};
|
||||||
|
se::DecryptAes256Cbc(tzram_dst, tzram_size, pkg1::AesKeySlot_TzramSaveKey, tzram_src, tzram_size, tzram_iv, sizeof(tzram_iv));
|
||||||
|
|
||||||
|
/* Calculate the cmac of decrypted tzram. */
|
||||||
|
u8 tzram_mac[se::AesBlockSize] = {};
|
||||||
|
se::ComputeAes256Cmac(tzram_mac, sizeof(tzram_mac), pkg1::AesKeySlot_TzramSaveKey, tzram_dst, tzram_size);
|
||||||
|
|
||||||
|
/* Get the expected mac from pmc scratch. */
|
||||||
|
const u32 expected_mac[sizeof(tzram_mac) / sizeof(u32)] = { reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH112), reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH113), reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH114), reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH115)};
|
||||||
|
|
||||||
|
/* Validate that the calculated mac is correct. */
|
||||||
|
AMS_ABORT_UNLESS(crypto::IsSameBytes(tzram_mac, expected_mac, sizeof(tzram_mac)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void RestoreSecureMonitorToTzramErista(const TargetFirmware target_fw) {
|
||||||
|
/* Clear all unsaved security engine keyslots. */
|
||||||
|
ClearUnsavedSecurityEngineKeySlots();
|
||||||
|
|
||||||
|
/* Restore encrypted tzram contents. */
|
||||||
|
void * const tzram_src = secmon::MemoryRegionPhysicalDramSecureDataStoreTzram.GetPointer<void>();
|
||||||
|
void * const tzram_dst = secmon::MemoryRegionPhysicalTzramNonVolatile.GetPointer<void>();
|
||||||
|
const size_t tzram_size = secmon::MemoryRegionPhysicalTzramNonVolatile.GetSize();
|
||||||
|
RestoreEncryptedTzram(tzram_dst, tzram_src, tzram_size);
|
||||||
|
|
||||||
|
/* Clear the tzram kek registers. */
|
||||||
|
reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH24, 0);
|
||||||
|
reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH25, 0);
|
||||||
|
reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH26, 0);
|
||||||
|
reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH27, 0);
|
||||||
|
|
||||||
|
/* Clear the tzram cmac registers. */
|
||||||
|
reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH112, 0);
|
||||||
|
reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH113, 0);
|
||||||
|
reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH114, 0);
|
||||||
|
reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH115, 0);
|
||||||
|
|
||||||
|
/* Clear the keydata used to protect tzram. */
|
||||||
|
se::ClearAesKeySlot(pkg1::AesKeySlot_TzramSaveKek);
|
||||||
|
se::ClearAesKeySlot(pkg1::AesKeySlot_TzramSaveKey);
|
||||||
|
|
||||||
|
/* Clear the encrypted copy of tzram in dram. */
|
||||||
|
/* NOTE: This does not actually clear the encrypted copy, because BPMP access to main memory has been restricted. */
|
||||||
|
/* Nintendo seems to not realize this, though, so we'll do the same. */
|
||||||
|
std::memset(tzram_src, 0, tzram_size);
|
||||||
|
|
||||||
|
/* Set Tzram to secure-world only. */
|
||||||
|
se::SetTzramSecure();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void RestoreSecureMonitorToTzram(const TargetFirmware target_fw) {
|
||||||
|
/* If erista, perform restoration procedure. */
|
||||||
|
if (fuse::GetSocType() == fuse::SocType_Erista) {
|
||||||
|
RestoreSecureMonitorToTzramErista(target_fw);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lock secure scratch. */
|
||||||
|
pmc::LockSecureRegister(static_cast<pmc::SecureRegister>(pmc::SecureRegister_DramParameters | pmc::SecureRegister_Other));
|
||||||
|
|
||||||
|
/* Lockout fuses. */
|
||||||
|
fuse::Lockout();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
23
exosphere2/warmboot/source/warmboot_secure_monitor.hpp
Normal file
23
exosphere2/warmboot/source/warmboot_secure_monitor.hpp
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <exosphere.hpp>
|
||||||
|
|
||||||
|
namespace ams::warmboot {
|
||||||
|
|
||||||
|
void RestoreSecureMonitorToTzram(const TargetFirmware target_fw);
|
||||||
|
|
||||||
|
}
|
36
exosphere2/warmboot/source/warmboot_start.s
Normal file
36
exosphere2/warmboot/source/warmboot_start.s
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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._ZN3ams8warmboot5StartEv, "ax", %progbits
|
||||||
|
.align 3
|
||||||
|
.global _ZN3ams8warmboot5StartEv
|
||||||
|
_ZN3ams8warmboot5StartEv:
|
||||||
|
/* Set CPSR_cf and CPSR_cf. */
|
||||||
|
msr cpsr_f, #0xC0
|
||||||
|
msr cpsr_cf, #0xD3
|
||||||
|
|
||||||
|
/* Set the stack pointer. */
|
||||||
|
ldr sp, =__stack_top__
|
||||||
|
|
||||||
|
/* Set our link register to the exception handler. */
|
||||||
|
ldr lr, =_ZN3ams8warmboot16ExceptionHandlerEv
|
||||||
|
|
||||||
|
/* Invoke main. */
|
||||||
|
ldr r0, =_metadata
|
||||||
|
bl _ZN3ams8warmboot4MainEPKNS0_8MetadataE
|
||||||
|
|
||||||
|
/* Infinite loop. */
|
||||||
|
1: b 1b
|
23
exosphere2/warmboot/source/warmboot_util.hpp
Normal file
23
exosphere2/warmboot/source/warmboot_util.hpp
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <exosphere.hpp>
|
||||||
|
|
||||||
|
namespace ams::warmboot {
|
||||||
|
|
||||||
|
void SpinLoop(unsigned int num);
|
||||||
|
|
||||||
|
}
|
30
exosphere2/warmboot/source/warmboot_util_asm.s
Normal file
30
exosphere2/warmboot/source/warmboot_util_asm.s
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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._ZN3ams8warmboot8SpinLoopEj, "ax", %progbits
|
||||||
|
.global _ZN3ams8warmboot8SpinLoopEj
|
||||||
|
.thumb_func
|
||||||
|
.syntax unified
|
||||||
|
_ZN3ams8warmboot8SpinLoopEj:
|
||||||
|
1:
|
||||||
|
/* Subtract one from the count. */
|
||||||
|
subs r0, r0, #1
|
||||||
|
|
||||||
|
/* If we aren't at zero, continue looping. */
|
||||||
|
bgt 1b
|
||||||
|
|
||||||
|
/* Return. */
|
||||||
|
bx lr
|
189
exosphere2/warmboot/warmboot.ld
Normal file
189
exosphere2/warmboot/warmboot.ld
Normal file
|
@ -0,0 +1,189 @@
|
||||||
|
OUTPUT_ARCH(arm)
|
||||||
|
ENTRY(_reset)
|
||||||
|
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
NULL : ORIGIN = 0, LENGTH = 4K
|
||||||
|
lp0fw : ORIGIN = 0x40010000, LENGTH = 16K
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
/* =========== CODE section =========== */
|
||||||
|
PROVIDE(__start__ = ORIGIN(lp0fw));
|
||||||
|
. = __start__;
|
||||||
|
__code_start = . ;
|
||||||
|
|
||||||
|
.vectors :
|
||||||
|
{
|
||||||
|
KEEP (*(.vectors .vectors.*))
|
||||||
|
. = ALIGN(8);
|
||||||
|
} >lp0fw
|
||||||
|
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||||
|
*(.text.exit .text.exit.*)
|
||||||
|
*(.text.startup .text.startup.*)
|
||||||
|
*(.text.hot .text.hot.*)
|
||||||
|
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||||
|
. = ALIGN(8);
|
||||||
|
} >lp0fw
|
||||||
|
|
||||||
|
.init :
|
||||||
|
{
|
||||||
|
KEEP( *(.init) )
|
||||||
|
. = ALIGN(8);
|
||||||
|
} >lp0fw
|
||||||
|
|
||||||
|
.plt :
|
||||||
|
{
|
||||||
|
*(.plt)
|
||||||
|
*(.iplt)
|
||||||
|
. = ALIGN(8);
|
||||||
|
} >lp0fw
|
||||||
|
|
||||||
|
.fini :
|
||||||
|
{
|
||||||
|
KEEP( *(.fini) )
|
||||||
|
. = ALIGN(8);
|
||||||
|
} >lp0fw
|
||||||
|
|
||||||
|
|
||||||
|
/* =========== RODATA section =========== */
|
||||||
|
. = ALIGN(8);
|
||||||
|
__rodata_start = . ;
|
||||||
|
|
||||||
|
.rodata :
|
||||||
|
{
|
||||||
|
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||||
|
. = ALIGN(8);
|
||||||
|
} >lp0fw
|
||||||
|
|
||||||
|
.eh_frame_hdr : { __eh_frame_hdr_start = .; *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) __eh_frame_hdr_end = .; } >lp0fw
|
||||||
|
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } >lp0fw
|
||||||
|
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } >lp0fw
|
||||||
|
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } >lp0fw
|
||||||
|
|
||||||
|
.hash : { *(.hash) } >lp0fw
|
||||||
|
|
||||||
|
/* =========== DATA section =========== */
|
||||||
|
. = ALIGN(8);
|
||||||
|
__data_start = . ;
|
||||||
|
|
||||||
|
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } >lp0fw
|
||||||
|
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } >lp0fw
|
||||||
|
.gnu_extab : ONLY_IF_RW { *(.gnu_extab*) } >lp0fw
|
||||||
|
.exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } >lp0fw
|
||||||
|
|
||||||
|
.preinit_array ALIGN(8) :
|
||||||
|
{
|
||||||
|
PROVIDE (__preinit_array_start = .);
|
||||||
|
KEEP (*(.preinit_array))
|
||||||
|
PROVIDE (__preinit_array_end = .);
|
||||||
|
} >lp0fw
|
||||||
|
|
||||||
|
.init_array ALIGN(8) :
|
||||||
|
{
|
||||||
|
PROVIDE (__init_array_start = .);
|
||||||
|
KEEP (*(SORT(.init_array.*)))
|
||||||
|
KEEP (*(.init_array))
|
||||||
|
PROVIDE (__init_array_end = .);
|
||||||
|
} >lp0fw
|
||||||
|
|
||||||
|
.fini_array ALIGN(8) :
|
||||||
|
{
|
||||||
|
PROVIDE (__fini_array_start = .);
|
||||||
|
KEEP (*(.fini_array))
|
||||||
|
KEEP (*(SORT(.fini_array.*)))
|
||||||
|
PROVIDE (__fini_array_end = .);
|
||||||
|
} >lp0fw
|
||||||
|
|
||||||
|
.ctors ALIGN(8) :
|
||||||
|
{
|
||||||
|
KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||||
|
KEEP (*(SORT(.ctors.*)))
|
||||||
|
KEEP (*(.ctors))
|
||||||
|
} >lp0fw
|
||||||
|
|
||||||
|
.dtors ALIGN(8) :
|
||||||
|
{
|
||||||
|
KEEP (*crtbegin.o(.dtors))
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||||
|
KEEP (*(SORT(.dtors.*)))
|
||||||
|
KEEP (*(.dtors))
|
||||||
|
} >lp0fw
|
||||||
|
|
||||||
|
__got_start__ = .;
|
||||||
|
|
||||||
|
.got : { *(.got) *(.igot) } >lp0fw
|
||||||
|
.got.plt : { *(.got.plt) *(.igot.plt) } >lp0fw
|
||||||
|
|
||||||
|
__got_end__ = .;
|
||||||
|
|
||||||
|
.data ALIGN(8) :
|
||||||
|
{
|
||||||
|
*(.data .data.* .gnu.linkonce.d.*)
|
||||||
|
SORT(CONSTRUCTORS)
|
||||||
|
} >lp0fw
|
||||||
|
|
||||||
|
__bss_start__ = .;
|
||||||
|
.bss ALIGN(8) :
|
||||||
|
{
|
||||||
|
*(.dynbss)
|
||||||
|
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||||
|
*(COMMON)
|
||||||
|
. = ALIGN(16);
|
||||||
|
} >lp0fw
|
||||||
|
__bss_end__ = .;
|
||||||
|
|
||||||
|
__end__ = ABSOLUTE(.) ;
|
||||||
|
|
||||||
|
__total_size__ = (__end__ - __start__);
|
||||||
|
__executable_size__ = (__end__ - _reset);
|
||||||
|
|
||||||
|
__stack_top__ = 0x40013000;
|
||||||
|
__stack_bottom__ = 0x40012000;
|
||||||
|
|
||||||
|
/* ==================
|
||||||
|
==== Metadata ====
|
||||||
|
================== */
|
||||||
|
|
||||||
|
/* Discard sections that difficult post-processing */
|
||||||
|
/DISCARD/ : { *(.group .comment .note .interp) }
|
||||||
|
|
||||||
|
/* Stabs debugging sections. */
|
||||||
|
.stab 0 : { *(.stab) }
|
||||||
|
.stabstr 0 : { *(.stabstr) }
|
||||||
|
.stab.excl 0 : { *(.stab.excl) }
|
||||||
|
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||||
|
.stab.index 0 : { *(.stab.index) }
|
||||||
|
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||||
|
|
||||||
|
/* DWARF debug sections.
|
||||||
|
Symbols in the DWARF debugging sections are relative to the beginning
|
||||||
|
of the section so we begin them at 0. */
|
||||||
|
|
||||||
|
/* DWARF 1 */
|
||||||
|
.debug 0 : { *(.debug) }
|
||||||
|
.line 0 : { *(.line) }
|
||||||
|
|
||||||
|
/* GNU DWARF 1 extensions */
|
||||||
|
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||||
|
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||||
|
|
||||||
|
/* DWARF 1.1 and DWARF 2 */
|
||||||
|
.debug_aranges 0 : { *(.debug_aranges) }
|
||||||
|
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||||
|
|
||||||
|
/* DWARF 2 */
|
||||||
|
.debug_info 0 : { *(.debug_info) }
|
||||||
|
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||||
|
.debug_line 0 : { *(.debug_line) }
|
||||||
|
.debug_frame 0 : { *(.debug_frame) }
|
||||||
|
.debug_str 0 : { *(.debug_str) }
|
||||||
|
.debug_loc 0 : { *(.debug_loc) }
|
||||||
|
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||||
|
}
|
7
exosphere2/warmboot/warmboot.specs
Normal file
7
exosphere2/warmboot/warmboot.specs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
%rename link old_link
|
||||||
|
|
||||||
|
*link:
|
||||||
|
%(old_link) -T %:getenv(TOPDIR /warmboot.ld) --gc-sections --nmagic -nostdlib -nostartfiles
|
||||||
|
|
||||||
|
*startfile:
|
||||||
|
crti%O%s crtbegin%O%s
|
|
@ -109,4 +109,7 @@ namespace ams::fuse {
|
||||||
int GetExpectedFuseVersion(TargetFirmware target_fw);
|
int GetExpectedFuseVersion(TargetFirmware target_fw);
|
||||||
bool HasRcmVulnerabilityPatch();
|
bool HasRcmVulnerabilityPatch();
|
||||||
|
|
||||||
|
bool IsOdmProductionMode();
|
||||||
|
void ConfigureFuseBypass();
|
||||||
|
|
||||||
}
|
}
|
|
@ -27,6 +27,7 @@ namespace ams::pmic {
|
||||||
Regulator_Mariko_Max77812_B = 2, /* Device code 0x3A000006 */
|
Regulator_Mariko_Max77812_B = 2, /* Device code 0x3A000006 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void SetEnBit(Regulator regulator);
|
||||||
void EnableVddCpu(Regulator regulator);
|
void EnableVddCpu(Regulator regulator);
|
||||||
void DisableVddCpu(Regulator regulator);
|
void DisableVddCpu(Regulator regulator);
|
||||||
void EnableSleep();
|
void EnableSleep();
|
||||||
|
|
|
@ -87,6 +87,10 @@ namespace ams::reg {
|
||||||
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
template<typename... Values> requires ((sizeof...(Values) > 0) && (std::is_same<Values, BitsValue>::value && ...))
|
||||||
ALWAYS_INLINE bool HasValue(uintptr_t reg, const Values... values) { return Read(reg, (EncodeMask(values) | ...)) == Encode(values...); }
|
ALWAYS_INLINE bool HasValue(uintptr_t reg, const Values... values) { return Read(reg, (EncodeMask(values) | ...)) == Encode(values...); }
|
||||||
|
|
||||||
|
ALWAYS_INLINE u32 GetValue(volatile u32 *reg, const BitsMask mask) { return Read(reg, mask) >> GetOffset(mask); }
|
||||||
|
ALWAYS_INLINE u32 GetValue(volatile u32 ®, const BitsMask mask) { return Read(reg, mask) >> GetOffset(mask); }
|
||||||
|
ALWAYS_INLINE u32 GetValue(uintptr_t reg, const BitsMask mask) { return Read(reg, mask) >> GetOffset(mask); }
|
||||||
|
|
||||||
ALWAYS_INLINE void ReadWrite(volatile u32 *reg, u32 val, u32 mask) { *reg = (*reg & (~mask)) | (val & mask); }
|
ALWAYS_INLINE void ReadWrite(volatile u32 *reg, u32 val, u32 mask) { *reg = (*reg & (~mask)) | (val & mask); }
|
||||||
ALWAYS_INLINE void ReadWrite(volatile u32 ®, u32 val, u32 mask) { reg = ( reg & (~mask)) | (val & mask); }
|
ALWAYS_INLINE void ReadWrite(volatile u32 ®, u32 val, u32 mask) { reg = ( reg & (~mask)) | (val & mask); }
|
||||||
ALWAYS_INLINE void ReadWrite(uintptr_t reg, u32 val, u32 mask) { ReadWrite(reinterpret_cast<volatile u32 *>(reg), val, mask); }
|
ALWAYS_INLINE void ReadWrite(uintptr_t reg, u32 val, u32 mask) { ReadWrite(reinterpret_cast<volatile u32 *>(reg), val, mask); }
|
||||||
|
|
|
@ -23,6 +23,7 @@ namespace ams::se {
|
||||||
constexpr inline size_t AesBlockSize = crypto::AesEncryptor128::BlockSize;
|
constexpr inline size_t AesBlockSize = crypto::AesEncryptor128::BlockSize;
|
||||||
|
|
||||||
void ClearAesKeySlot(int slot);
|
void ClearAesKeySlot(int slot);
|
||||||
|
void ClearAesKeyIv(int slot);
|
||||||
void LockAesKeySlot(int slot, u32 flags);
|
void LockAesKeySlot(int slot, u32 flags);
|
||||||
|
|
||||||
void SetAesKey(int slot, const void *key, size_t key_size);
|
void SetAesKey(int slot, const void *key, size_t key_size);
|
||||||
|
@ -40,6 +41,8 @@ namespace ams::se {
|
||||||
|
|
||||||
void EncryptAes128Cbc(void *dst, size_t dst_size, int slot, const void *src, size_t src_size, const void *iv, size_t iv_size);
|
void EncryptAes128Cbc(void *dst, size_t dst_size, int slot, const void *src, size_t src_size, const void *iv, size_t iv_size);
|
||||||
void EncryptAes256Cbc(void *dst, size_t dst_size, int slot, const void *src, size_t src_size, const void *iv, size_t iv_size);
|
void EncryptAes256Cbc(void *dst, size_t dst_size, int slot, const void *src, size_t src_size, const void *iv, size_t iv_size);
|
||||||
|
void DecryptAes128Cbc(void *dst, size_t dst_size, int slot, const void *src, size_t src_size, const void *iv, size_t iv_size);
|
||||||
|
void DecryptAes256Cbc(void *dst, size_t dst_size, int slot, const void *src, size_t src_size, const void *iv, size_t iv_size);
|
||||||
|
|
||||||
void EncryptAes128CbcAsync(u32 out_ll_address, int slot, u32 in_ll_address, u32 size, const void *iv, size_t iv_size, DoneHandler handler);
|
void EncryptAes128CbcAsync(u32 out_ll_address, int slot, u32 in_ll_address, u32 size, const void *iv, size_t iv_size, DoneHandler handler);
|
||||||
void DecryptAes128CbcAsync(u32 out_ll_address, int slot, u32 in_ll_address, u32 size, const void *iv, size_t iv_size, DoneHandler handler);
|
void DecryptAes128CbcAsync(u32 out_ll_address, int slot, u32 in_ll_address, u32 size, const void *iv, size_t iv_size, DoneHandler handler);
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
#include <exosphere/tegra/tegra_ictlr.hpp>
|
#include <exosphere/tegra/tegra_ictlr.hpp>
|
||||||
#include <exosphere/tegra/tegra_mc.hpp>
|
#include <exosphere/tegra/tegra_mc.hpp>
|
||||||
#include <exosphere/tegra/tegra_mselect.hpp>
|
#include <exosphere/tegra/tegra_mselect.hpp>
|
||||||
|
#include <exosphere/tegra/tegra_pinmux.hpp>
|
||||||
|
#include <exosphere/tegra/tegra_pg_up.hpp>
|
||||||
#include <exosphere/tegra/tegra_pmc.hpp>
|
#include <exosphere/tegra/tegra_pmc.hpp>
|
||||||
#include <exosphere/tegra/tegra_sb.hpp>
|
#include <exosphere/tegra/tegra_sb.hpp>
|
||||||
#include <exosphere/tegra/tegra_sysctr0.hpp>
|
#include <exosphere/tegra/tegra_sysctr0.hpp>
|
||||||
|
|
|
@ -16,22 +16,32 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <vapours.hpp>
|
#include <vapours.hpp>
|
||||||
|
|
||||||
|
#define APB_MISC_PP_CONFIG_CTL (0x024)
|
||||||
|
|
||||||
|
#define APB_MISC_GP_ASDBGREG (0x810)
|
||||||
|
|
||||||
|
#define APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 (0xc00)
|
||||||
#define APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 (0xc00)
|
#define APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 (0xc00)
|
||||||
#define APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0 (0xc04)
|
#define APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0 (0xc04)
|
||||||
#define APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG2_0 (0xc08)
|
#define APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG2_0 (0xc08)
|
||||||
|
|
||||||
#define AHB_MISC_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (AHB_MISC, NAME)
|
#define APB_MISC_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (APB_MISC, NAME)
|
||||||
#define AHB_MISC_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (AHB_MISC, NAME, VALUE)
|
#define APB_MISC_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (APB_MISC, NAME, VALUE)
|
||||||
#define AHB_MISC_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (AHB_MISC, NAME, ENUM)
|
#define APB_MISC_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (APB_MISC, NAME, ENUM)
|
||||||
#define AHB_MISC_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(AHB_MISC, NAME, __COND__, TRUE_ENUM, FALSE_ENUM)
|
#define APB_MISC_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(APB_MISC, NAME, __COND__, TRUE_ENUM, FALSE_ENUM)
|
||||||
|
|
||||||
#define DEFINE_AHB_MISC_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (AHB_MISC, NAME, __OFFSET__, __WIDTH__)
|
#define DEFINE_APB_MISC_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (APB_MISC, NAME, __OFFSET__, __WIDTH__)
|
||||||
#define DEFINE_AHB_MISC_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (AHB_MISC, NAME, __OFFSET__, ZERO, ONE)
|
#define DEFINE_APB_MISC_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (APB_MISC, NAME, __OFFSET__, ZERO, ONE)
|
||||||
#define DEFINE_AHB_MISC_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (AHB_MISC, NAME, __OFFSET__, ZERO, ONE, TWO, THREE)
|
#define DEFINE_APB_MISC_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (APB_MISC, NAME, __OFFSET__, ZERO, ONE, TWO, THREE)
|
||||||
#define DEFINE_AHB_MISC_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(AHB_MISC, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN)
|
#define DEFINE_APB_MISC_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(APB_MISC, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN)
|
||||||
#define DEFINE_AHB_MISC_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (AHB_MISC, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
|
#define DEFINE_APB_MISC_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (APB_MISC, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
|
||||||
|
|
||||||
#define DEFINE_SLAVE_SECURITY_REG(RINDEX, INDEX, NAME) DEFINE_AHB_MISC_REG_BIT_ENUM(SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG##RINDEX##_##NAME##_SECURITY_EN, INDEX, DISABLE, ENABLE)
|
DEFINE_APB_MISC_REG_BIT_ENUM(PP_CONFIG_CTL_JTAG, 6, DISABLE, ENABLE);
|
||||||
|
DEFINE_APB_MISC_REG_BIT_ENUM(PP_CONFIG_CTL_TBE, 7, DISABLE, ENABLE);
|
||||||
|
|
||||||
|
DEFINE_APB_MISC_REG(GP_ASDBGREG_CFG2TMC_RAM_SVOP_PDP, 24, 2);
|
||||||
|
|
||||||
|
#define DEFINE_SLAVE_SECURITY_REG(RINDEX, INDEX, NAME) DEFINE_APB_MISC_REG_BIT_ENUM(SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG##RINDEX##_##NAME##_SECURITY_EN, INDEX, DISABLE, ENABLE)
|
||||||
|
|
||||||
DEFINE_SLAVE_SECURITY_REG(0, 29, STM);
|
DEFINE_SLAVE_SECURITY_REG(0, 29, STM);
|
||||||
DEFINE_SLAVE_SECURITY_REG(0, 24, CEC);
|
DEFINE_SLAVE_SECURITY_REG(0, 24, CEC);
|
||||||
|
@ -96,4 +106,4 @@ DEFINE_SLAVE_SECURITY_REG(2, 0, SDMMC1);
|
||||||
|
|
||||||
#undef DEFINE_SLAVE_SECURITY_REG
|
#undef DEFINE_SLAVE_SECURITY_REG
|
||||||
|
|
||||||
#define SLAVE_SECURITY_REG_BITS_ENUM(RINDEX, NAME, ENUM) AHB_MISC_REG_BITS_ENUM(SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG##RINDEX##_##NAME##_SECURITY_EN, ENUM)
|
#define SLAVE_SECURITY_REG_BITS_ENUM(RINDEX, NAME, ENUM) APB_MISC_REG_BITS_ENUM(SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG##RINDEX##_##NAME##_SECURITY_EN, ENUM)
|
||||||
|
|
|
@ -32,11 +32,48 @@
|
||||||
#define CLK_RST_CONTROLLER_RST_SOURCE (0x000)
|
#define CLK_RST_CONTROLLER_RST_SOURCE (0x000)
|
||||||
|
|
||||||
#define CLK_RST_CONTROLLER_MISC_CLK_ENB (0x048)
|
#define CLK_RST_CONTROLLER_MISC_CLK_ENB (0x048)
|
||||||
|
#define CLK_RST_CONTROLLER_OSC_CTRL (0x050)
|
||||||
|
#define CLK_RST_CONTROLLER_PLLX_BASE (0x0E0)
|
||||||
|
#define CLK_RST_CONTROLLER_CCLKG_BURST_POLICY (0x368)
|
||||||
|
#define CLK_RST_CONTROLLER_SUPER_CCLKG_DIVIDER (0x36C)
|
||||||
|
#define CLK_RST_CONTROLLER_CCLKLP_BURST_POLICY (0x370)
|
||||||
|
#define CLK_RST_CONTROLLER_SUPER_CCLKLP_DIVIDER (0x374)
|
||||||
|
#define CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2 (0x388)
|
||||||
|
#define CLK_RST_CONTROLLER_SPARE_REG0 (0x55C)
|
||||||
|
|
||||||
|
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA (0x0F8)
|
||||||
|
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB (0x0FC)
|
||||||
|
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRC (0x3A0)
|
||||||
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD (0x3A4)
|
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD (0x3A4)
|
||||||
|
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRE (0x554)
|
||||||
|
|
||||||
DEFINE_CLK_RST_REG(MISC_CLK_ENB_CFG_ALL_VISIBLE, 28, 1);
|
DEFINE_CLK_RST_REG(MISC_CLK_ENB_CFG_ALL_VISIBLE, 28, 1);
|
||||||
|
|
||||||
|
DEFINE_CLK_RST_REG_BIT_ENUM(OSC_CTRL_XOE, 0, DISABLE, ENABLE);
|
||||||
|
DEFINE_CLK_RST_REG(OSC_CTRL_XOFS, 4, 6);
|
||||||
|
|
||||||
|
DEFINE_CLK_RST_REG_BIT_ENUM(PLLX_BASE_PLLX_ENABLE, 30, DISABLE, ENABLE);
|
||||||
|
|
||||||
|
DEFINE_CLK_RST_REG(SUPER_CCLK_DIVIDER_SUPER_CDIV_DIVISOR, 0, 8);
|
||||||
|
DEFINE_CLK_RST_REG(SUPER_CCLK_DIVIDER_SUPER_CDIV_DIVIDEND, 8, 8);
|
||||||
|
DEFINE_CLK_RST_REG_BIT_ENUM(SUPER_CCLK_DIVIDER_SUPER_CDIV_DIS_FROM_CPU_IRQ, 24, NO_IMPACT, DISABLE);
|
||||||
|
DEFINE_CLK_RST_REG_BIT_ENUM(SUPER_CCLK_DIVIDER_SUPER_CDIV_DIS_FROM_COP_IRQ, 25, NO_IMPACT, DISABLE);
|
||||||
|
DEFINE_CLK_RST_REG_BIT_ENUM(SUPER_CCLK_DIVIDER_SUPER_CDIV_DIS_FROM_CPU_FIQ, 26, NO_IMPACT, DISABLE);
|
||||||
|
DEFINE_CLK_RST_REG_BIT_ENUM(SUPER_CCLK_DIVIDER_SUPER_CDIV_DIS_FROM_COP_FIQ, 27, NO_IMPACT, DISABLE);
|
||||||
|
|
||||||
|
DEFINE_CLK_RST_REG_BIT_ENUM(SUPER_CCLKG_DIVIDER_SUPER_CDIV_ENB, 31, DISABLE, ENABLE);
|
||||||
|
DEFINE_CLK_RST_REG_BIT_ENUM(SUPER_CCLKLP_DIVIDER_SUPER_CDIV_ENB, 31, DISABLE, ENABLE);
|
||||||
|
|
||||||
|
DEFINE_CLK_RST_REG_FOUR_BIT_ENUM(CCLK_BURST_POLICY_CWAKEUP_IDLE_SOURCE, 0, CLKM, RSVD1, CLKS, RSVD3, PLLP_OUT0, PLLP_OUT4, RSVD6, RSVD7, PLLX_OUT0_LJ, DVFS_CPU_CLK, RSVD10, RSVD11, RSVD12, RSVD13, PLLX_OUT0, DVFS_CPU_CLK_LJ);
|
||||||
|
DEFINE_CLK_RST_REG_FOUR_BIT_ENUM(CCLK_BURST_POLICY_CWAKEUP_RUN_SOURCE, 4, CLKM, RSVD1, CLKS, RSVD3, PLLP_OUT0, PLLP_OUT4, RSVD6, RSVD7, PLLX_OUT0_LJ, DVFS_CPU_CLK, RSVD10, RSVD11, RSVD12, RSVD13, PLLX_OUT0, DVFS_CPU_CLK_LJ);
|
||||||
|
DEFINE_CLK_RST_REG_FOUR_BIT_ENUM(CCLK_BURST_POLICY_CWAKEUP_IRQ_SOURCE, 8, CLKM, RSVD1, CLKS, RSVD3, PLLP_OUT0, PLLP_OUT4, RSVD6, RSVD7, PLLX_OUT0_LJ, DVFS_CPU_CLK, RSVD10, RSVD11, RSVD12, RSVD13, PLLX_OUT0, DVFS_CPU_CLK_LJ);
|
||||||
|
DEFINE_CLK_RST_REG_FOUR_BIT_ENUM(CCLK_BURST_POLICY_CWAKEUP_FIQ_SOURCE, 12, CLKM, RSVD1, CLKS, RSVD3, PLLP_OUT0, PLLP_OUT4, RSVD6, RSVD7, PLLX_OUT0_LJ, DVFS_CPU_CLK, RSVD10, RSVD11, RSVD12, RSVD13, PLLX_OUT0, DVFS_CPU_CLK_LJ);
|
||||||
|
DEFINE_CLK_RST_REG_FOUR_BIT_ENUM(CCLK_BURST_POLICY_CPU_STATE, 28, STDBY, IDLE, RUN, RSVD3, IRQ, RSVD5, RSVD6, RSVD7, FIQ, RSVD9, RSVD10, RSVD11, RSVD12, RSVD13, RSVD14, RSVD15);
|
||||||
|
|
||||||
|
DEFINE_CLK_RST_REG(CPU_SOFTRST_CTRL2_CAR2PMC_CPU_ACK_WIDTH, 0, 12);
|
||||||
|
|
||||||
|
DEFINE_CLK_RST_REG_TWO_BIT_ENUM(SPARE_REG0_CLK_M_DIVISOR, 2, CLK_M_DIVISOR1, CLK_M_DIVISOR2, CLK_M_DIVISOR3, CLK_M_DIVISOR4);
|
||||||
|
|
||||||
/* RST_DEVICES */
|
/* RST_DEVICES */
|
||||||
#define CLK_RST_CONTROLLER_RST_DEVICES_L (0x004)
|
#define CLK_RST_CONTROLLER_RST_DEVICES_L (0x004)
|
||||||
#define CLK_RST_CONTROLLER_RST_DEVICES_H (0x008)
|
#define CLK_RST_CONTROLLER_RST_DEVICES_H (0x008)
|
||||||
|
@ -61,13 +98,40 @@ DEFINE_CLK_RST_REG(MISC_CLK_ENB_CFG_ALL_VISIBLE, 28, 1);
|
||||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTA (0x178)
|
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTA (0x178)
|
||||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTB (0x17C)
|
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTB (0x17C)
|
||||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTC (0x1A0)
|
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTC (0x1A0)
|
||||||
|
#define CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT (0x3B4)
|
||||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_ACTMON (0x3E8)
|
#define CLK_RST_CONTROLLER_CLK_SOURCE_ACTMON (0x3E8)
|
||||||
|
#define CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_REF (0x62C)
|
||||||
|
#define CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_SOC (0x630)
|
||||||
|
|
||||||
/* RST_DEV_*_SET */
|
/* RST_DEV_*_SET */
|
||||||
#define CLK_RST_CONTROLLER_RST_DEV_L_SET (0x300)
|
#define CLK_RST_CONTROLLER_RST_DEV_L_SET (0x300)
|
||||||
|
#define CLK_RST_CONTROLLER_RST_DEV_H_SET (0x308)
|
||||||
|
#define CLK_RST_CONTROLLER_RST_DEV_U_SET (0x310)
|
||||||
|
#define CLK_RST_CONTROLLER_RST_DEV_V_SET (0x430)
|
||||||
|
|
||||||
/* RST_DEV_*_CLR */
|
/* RST_DEV_*_CLR */
|
||||||
#define CLK_RST_CONTROLLER_RST_DEV_L_CLR (0x304)
|
#define CLK_RST_CONTROLLER_RST_DEV_L_CLR (0x304)
|
||||||
|
#define CLK_RST_CONTROLLER_RST_DEV_H_CLR (0x30C)
|
||||||
|
#define CLK_RST_CONTROLLER_RST_DEV_U_CLR (0x314)
|
||||||
|
#define CLK_RST_CONTROLLER_RST_DEV_V_CLR (0x434)
|
||||||
|
|
||||||
|
/* CLK_ENB_*_SET */
|
||||||
|
#define CLK_RST_CONTROLLER_CLK_ENB_L_SET (0x320)
|
||||||
|
#define CLK_RST_CONTROLLER_CLK_ENB_H_SET (0x328)
|
||||||
|
#define CLK_RST_CONTROLLER_CLK_ENB_U_SET (0x330)
|
||||||
|
#define CLK_RST_CONTROLLER_CLK_ENB_V_SET (0x440)
|
||||||
|
#define CLK_RST_CONTROLLER_CLK_ENB_W_SET (0x448)
|
||||||
|
#define CLK_RST_CONTROLLER_CLK_ENB_X_SET (0x284)
|
||||||
|
#define CLK_RST_CONTROLLER_CLK_ENB_Y_SET (0x29C)
|
||||||
|
|
||||||
|
/* CLK_ENB_*_CLR */
|
||||||
|
#define CLK_RST_CONTROLLER_CLK_ENB_L_CLR (0x324)
|
||||||
|
#define CLK_RST_CONTROLLER_CLK_ENB_H_CLR (0x32C)
|
||||||
|
#define CLK_RST_CONTROLLER_CLK_ENB_U_CLR (0x334)
|
||||||
|
#define CLK_RST_CONTROLLER_CLK_ENB_X_CLR (0x288)
|
||||||
|
#define CLK_RST_CONTROLLER_CLK_ENB_Y_CLR (0x2A0)
|
||||||
|
#define CLK_RST_CONTROLLER_CLK_ENB_V_CLR (0x444)
|
||||||
|
#define CLK_RST_CONTROLLER_CLK_ENB_W_CLR (0x44C)
|
||||||
|
|
||||||
/* CLK_ENB_*_INDEX */
|
/* CLK_ENB_*_INDEX */
|
||||||
#define CLK_RST_CONTROLLER_CLK_ENB_I2C1_INDEX (0x0C)
|
#define CLK_RST_CONTROLLER_CLK_ENB_I2C1_INDEX (0x0C)
|
||||||
|
@ -95,14 +159,92 @@ DEFINE_CLK_RST_REG_BIT_ENUM(LVL2_CLK_GATE_OVRD_SDMMC3_LEGACY_TMCLK_OVR_ON, 30, O
|
||||||
DEFINE_CLK_RST_REG_BIT_ENUM(LVL2_CLK_GATE_OVRD_SDMMC4_LEGACY_TMCLK_OVR_ON, 31, OFF, ON);
|
DEFINE_CLK_RST_REG_BIT_ENUM(LVL2_CLK_GATE_OVRD_SDMMC4_LEGACY_TMCLK_OVR_ON, 31, OFF, ON);
|
||||||
|
|
||||||
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_I2C1_I2C1_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2);
|
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_I2C1_I2C1_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2);
|
||||||
|
DEFINE_CLK_RST_REG(CLK_SOURCE_I2C1_I2C1_CLK_DIVISOR, 0, 8);
|
||||||
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_I2C5_I2C5_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2);
|
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_I2C5_I2C5_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2);
|
||||||
|
DEFINE_CLK_RST_REG(CLK_SOURCE_I2C5_I2C5_CLK_DIVISOR, 0, 8);
|
||||||
|
|
||||||
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_UARTA_UARTA_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2);
|
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_UARTA_UARTA_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2);
|
||||||
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_UARTB_UARTB_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2);
|
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_UARTB_UARTB_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2);
|
||||||
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_UARTC_UARTC_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2);
|
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_UARTC_UARTC_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2);
|
||||||
|
|
||||||
|
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_MSELECT_MSELECT_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT2, PLLC4_OUT1, CLK_S, CLK_M, PLLC4_OUT0);
|
||||||
|
DEFINE_CLK_RST_REG(CLK_SOURCE_MSELECT_MSELECT_CLK_DIVISOR, 0, 8);
|
||||||
|
|
||||||
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_ACTMON_ACTMON_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, CLK_S, PLLC4_OUT1, CLK_M, PLLC4_OUT2);
|
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_ACTMON_ACTMON_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, CLK_S, PLLC4_OUT1, CLK_M, PLLC4_OUT2);
|
||||||
|
|
||||||
|
DEFINE_CLK_RST_REG(CLK_SOURCE_DVFS_REF_DVFS_REF_DIVISOR, 0, 8);
|
||||||
|
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_DVFS_REF_DVFS_REF_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2);
|
||||||
|
|
||||||
|
DEFINE_CLK_RST_REG(CLK_SOURCE_DVFS_SOC_DVFS_SOC_DIVISOR, 0, 8);
|
||||||
|
DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_DVFS_SOC_DVFS_SOC_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2);
|
||||||
|
|
||||||
DEFINE_CLK_RST_REG_BIT_ENUM(RST_DEV_L_SET_SET_COP_RST, 1, DISABLE, ENABLE);
|
DEFINE_CLK_RST_REG_BIT_ENUM(RST_DEV_L_SET_SET_COP_RST, 1, DISABLE, ENABLE);
|
||||||
|
|
||||||
DEFINE_CLK_RST_REG_BIT_ENUM(RST_DEV_L_CLR_CLR_COP_RST, 1, DISABLE, ENABLE);
|
DEFINE_CLK_RST_REG_BIT_ENUM(RST_DEV_L_CLR_CLR_COP_RST, 1, DISABLE, ENABLE);
|
||||||
|
|
||||||
|
DEFINE_CLK_RST_REG_BIT_ENUM(RST_CPUG_CMPLX_CLR_CLR_CPURESET0, 0, DISABLE, ENABLE);
|
||||||
|
DEFINE_CLK_RST_REG_BIT_ENUM(RST_CPUG_CMPLX_CLR_CLR_CPURESET1, 1, DISABLE, ENABLE);
|
||||||
|
DEFINE_CLK_RST_REG_BIT_ENUM(RST_CPUG_CMPLX_CLR_CLR_CPURESET2, 2, DISABLE, ENABLE);
|
||||||
|
DEFINE_CLK_RST_REG_BIT_ENUM(RST_CPUG_CMPLX_CLR_CLR_CPURESET3, 3, DISABLE, ENABLE);
|
||||||
|
DEFINE_CLK_RST_REG_BIT_ENUM(RST_CPUG_CMPLX_CLR_CLR_CORERESET0, 16, DISABLE, ENABLE);
|
||||||
|
DEFINE_CLK_RST_REG_BIT_ENUM(RST_CPUG_CMPLX_CLR_CLR_CORERESET1, 17, DISABLE, ENABLE);
|
||||||
|
DEFINE_CLK_RST_REG_BIT_ENUM(RST_CPUG_CMPLX_CLR_CLR_CORERESET2, 18, DISABLE, ENABLE);
|
||||||
|
DEFINE_CLK_RST_REG_BIT_ENUM(RST_CPUG_CMPLX_CLR_CLR_CORERESET3, 19, DISABLE, ENABLE);
|
||||||
|
DEFINE_CLK_RST_REG_BIT_ENUM(RST_CPUG_CMPLX_CLR_CLR_NONCPURESET, 29, DISABLE, ENABLE);
|
||||||
|
|
||||||
|
/* TODO: Actually include all devices. */
|
||||||
|
#define CLK_RST_FOREACH_DEVICE(HANDLER) \
|
||||||
|
HANDLER(L, CPU, 0, 0) \
|
||||||
|
HANDLER(L, RTC, 0, 4) \
|
||||||
|
HANDLER(L, TMR, 0, 5) \
|
||||||
|
HANDLER(L, GPIO, 0, 8) \
|
||||||
|
HANDLER(L, CACHE2, 0, 31) \
|
||||||
|
HANDLER(H, MEM, 1, 0) \
|
||||||
|
HANDLER(H, PMC, 1, 6) \
|
||||||
|
HANDLER(H, FUSE, 1, 7) \
|
||||||
|
HANDLER(H, I2C5, 1, 15) \
|
||||||
|
HANDLER(H, EMC, 1, 25) \
|
||||||
|
HANDLER(U, CSITE, 2, 9) \
|
||||||
|
HANDLER(U, IRAMA, 2, 20) \
|
||||||
|
HANDLER(U, IRAMB, 2, 21) \
|
||||||
|
HANDLER(U, IRAMC, 2, 22) \
|
||||||
|
HANDLER(U, IRAMD, 2, 23) \
|
||||||
|
HANDLER(U, CRAM2, 2, 24) \
|
||||||
|
HANDLER(V, CPUG, 3, 0) \
|
||||||
|
HANDLER(V, MSELECT, 3, 3) \
|
||||||
|
HANDLER(V, SPDIF_DOUBLER, 3, 22) \
|
||||||
|
HANDLER(V, TZRAM, 3, 30) \
|
||||||
|
HANDLER(V, SE, 3, 31) \
|
||||||
|
HANDLER(W, PCIERX0, 4, 2) \
|
||||||
|
HANDLER(W, PCIERX1, 4, 3) \
|
||||||
|
HANDLER(W, PCIERX2, 4, 4) \
|
||||||
|
HANDLER(W, PCIERX3, 4, 5) \
|
||||||
|
HANDLER(W, PCIERX4, 4, 6) \
|
||||||
|
HANDLER(W, PCIERX5, 4, 7) \
|
||||||
|
HANDLER(W, ENTROPY, 4, 21) \
|
||||||
|
HANDLER(W, DVFS, 4, 27) \
|
||||||
|
HANDLER(W, MC1, 4, 30) \
|
||||||
|
HANDLER(X, MC_CAPA, 5, 7) \
|
||||||
|
HANDLER(X, MC_CBPA, 5, 8) \
|
||||||
|
HANDLER(X, MC_CPU, 5, 9) \
|
||||||
|
HANDLER(X, MC_BBC, 5, 10) \
|
||||||
|
HANDLER(X, EMC_DLL, 5, 14) \
|
||||||
|
HANDLER(X, GPU, 5, 24) \
|
||||||
|
HANDLER(X, DBGAPB, 5, 25) \
|
||||||
|
HANDLER(X, PLLG_REF, 5, 29) \
|
||||||
|
HANDLER(Y, MC_CCPA, 6, 8) \
|
||||||
|
HANDLER(Y, MC_CDPA, 6, 9) \
|
||||||
|
HANDLER(Y, PLLP_OUT_CPU, 6, 31)
|
||||||
|
|
||||||
|
#define CLK_RST_DEFINE_SET_CLR_REG(REGISTER, DEVICE, REGISTER_INDEX, DEVICE_INDEX) \
|
||||||
|
DEFINE_CLK_RST_REG_BIT_ENUM(CLK_ENB_##REGISTER##_SET_SET_CLK_ENB_##DEVICE, DEVICE_INDEX, DISABLE, ENABLE); \
|
||||||
|
DEFINE_CLK_RST_REG_BIT_ENUM(CLK_ENB_##REGISTER##_CLR_CLR_CLK_ENB_##DEVICE, DEVICE_INDEX, DISABLE, ENABLE); \
|
||||||
|
DEFINE_CLK_RST_REG_BIT_ENUM(CLK_ENB_##REGISTER##_CLK_ENB_##DEVICE, DEVICE_INDEX, DISABLE, ENABLE); \
|
||||||
|
DEFINE_CLK_RST_REG_BIT_ENUM(RST_DEV_##REGISTER##_SET_SET_##DEVICE##_RST, DEVICE_INDEX, DISABLE, ENABLE); \
|
||||||
|
DEFINE_CLK_RST_REG_BIT_ENUM(RST_DEV_##REGISTER##_CLR_CLR_##DEVICE##_RST, DEVICE_INDEX, DISABLE, ENABLE); \
|
||||||
|
DEFINE_CLK_RST_REG_BIT_ENUM(RST_DEV_##REGISTER##_##DEVICE##_RST, DEVICE_INDEX, DISABLE, ENABLE);
|
||||||
|
|
||||||
|
CLK_RST_FOREACH_DEVICE(CLK_RST_DEFINE_SET_CLR_REG)
|
||||||
|
|
||||||
|
#undef CLK_RST_DEFINE_SET_CLR_REG
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,9 @@
|
||||||
#define EMC_ZCAL_INTERVAL (0x2E0)
|
#define EMC_ZCAL_INTERVAL (0x2E0)
|
||||||
#define EMC_PMC_SCRATCH3 (0x448)
|
#define EMC_PMC_SCRATCH3 (0x448)
|
||||||
#define EMC_FBIO_CFG7 (0x584)
|
#define EMC_FBIO_CFG7 (0x584)
|
||||||
|
#define EMC_PMACRO_CFG_PM_GLOBAL_0 (0xC30)
|
||||||
|
#define EMC_PMACRO_TRAINING_CTRL_0 (0xCF8)
|
||||||
|
#define EMC_PMACRO_TRAINING_CTRL_1 (0xCFC)
|
||||||
|
|
||||||
#define EMC_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (EMC, NAME)
|
#define EMC_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (EMC, NAME)
|
||||||
#define EMC_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (EMC, NAME, VALUE)
|
#define EMC_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (EMC, NAME, VALUE)
|
||||||
|
@ -88,3 +91,27 @@ DEFINE_EMC_REG_BIT_ENUM(PMC_SCRATCH3_WEAK_BIAS, 30, DISABLED, ENABLED);
|
||||||
|
|
||||||
DEFINE_EMC_REG_BIT_ENUM(FBIO_CFG7_CH1_ENABLE, 2, DISABLE, ENABLE);
|
DEFINE_EMC_REG_BIT_ENUM(FBIO_CFG7_CH1_ENABLE, 2, DISABLE, ENABLE);
|
||||||
|
|
||||||
|
DEFINE_EMC_REG_BIT_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE0, 16, DISABLE, ENABLE);
|
||||||
|
DEFINE_EMC_REG_BIT_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE1, 17, DISABLE, ENABLE);
|
||||||
|
DEFINE_EMC_REG_BIT_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE2, 18, DISABLE, ENABLE);
|
||||||
|
DEFINE_EMC_REG_BIT_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE3, 19, DISABLE, ENABLE);
|
||||||
|
DEFINE_EMC_REG_BIT_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE4, 20, DISABLE, ENABLE);
|
||||||
|
DEFINE_EMC_REG_BIT_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE5, 21, DISABLE, ENABLE);
|
||||||
|
DEFINE_EMC_REG_BIT_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE6, 22, DISABLE, ENABLE);
|
||||||
|
DEFINE_EMC_REG_BIT_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE7, 23, DISABLE, ENABLE);
|
||||||
|
DEFINE_EMC_REG_BIT_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_CMD0, 24, DISABLE, ENABLE);
|
||||||
|
DEFINE_EMC_REG_BIT_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_CMD1, 25, DISABLE, ENABLE);
|
||||||
|
DEFINE_EMC_REG_BIT_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_CMD2, 26, DISABLE, ENABLE);
|
||||||
|
DEFINE_EMC_REG_BIT_ENUM(PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_CMD3, 27, DISABLE, ENABLE);
|
||||||
|
|
||||||
|
DEFINE_EMC_REG_BIT_ENUM(PMACRO_TRAINING_CTRL_0_CH0_TRAINING_ENABLED, 0, DISABLED, ENABLED);
|
||||||
|
DEFINE_EMC_REG_BIT_ENUM(PMACRO_TRAINING_CTRL_0_CH0_TRAINING_TRAIN_QPOP, 1, DISABLED, ENABLED);
|
||||||
|
DEFINE_EMC_REG_BIT_ENUM(PMACRO_TRAINING_CTRL_0_CH0_TRAINING_RX_E_DIRECT_ZI, 2, DISABLED, ENABLED);
|
||||||
|
DEFINE_EMC_REG_BIT_ENUM(PMACRO_TRAINING_CTRL_0_CH0_TRAINING_E_WRPTR, 3, DISABLED, ENABLED);
|
||||||
|
DEFINE_EMC_REG_BIT_ENUM(PMACRO_TRAINING_CTRL_0_CH0_TRAINING_DRV_DQS, 4, DISABLED, ENABLED);
|
||||||
|
|
||||||
|
DEFINE_EMC_REG_BIT_ENUM(PMACRO_TRAINING_CTRL_1_CH1_TRAINING_ENABLED, 0, DISABLED, ENABLED);
|
||||||
|
DEFINE_EMC_REG_BIT_ENUM(PMACRO_TRAINING_CTRL_1_CH1_TRAINING_TRAIN_QPOP, 1, DISABLED, ENABLED);
|
||||||
|
DEFINE_EMC_REG_BIT_ENUM(PMACRO_TRAINING_CTRL_1_CH1_TRAINING_RX_E_DIRECT_ZI, 2, DISABLED, ENABLED);
|
||||||
|
DEFINE_EMC_REG_BIT_ENUM(PMACRO_TRAINING_CTRL_1_CH1_TRAINING_E_WRPTR, 3, DISABLED, ENABLED);
|
||||||
|
DEFINE_EMC_REG_BIT_ENUM(PMACRO_TRAINING_CTRL_1_CH1_TRAINING_DRV_DQS, 4, DISABLED, ENABLED);
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <vapours.hpp>
|
#include <vapours.hpp>
|
||||||
|
|
||||||
|
#define FLOW_CTLR_RAM_REPAIR (0x040)
|
||||||
#define FLOW_CTLR_FLOW_DBG_QUAL (0x050)
|
#define FLOW_CTLR_FLOW_DBG_QUAL (0x050)
|
||||||
#define FLOW_CTLR_L2FLUSH_CONTROL (0x094)
|
#define FLOW_CTLR_L2FLUSH_CONTROL (0x094)
|
||||||
#define FLOW_CTLR_BPMP_CLUSTER_CONTROL (0x098)
|
#define FLOW_CTLR_BPMP_CLUSTER_CONTROL (0x098)
|
||||||
|
@ -66,6 +66,9 @@ DEFINE_FLOW_REG_THREE_BIT_ENUM(HALT_COP_EVENTS_MODE, 29, FLOW_MODE_NONE, FLOW_MO
|
||||||
|
|
||||||
DEFINE_FLOW_REG_BIT_ENUM(FLOW_DBG_QUAL_FIQ2CCPLEX_ENABLE, 28, DISABLE, ENABLE);
|
DEFINE_FLOW_REG_BIT_ENUM(FLOW_DBG_QUAL_FIQ2CCPLEX_ENABLE, 28, DISABLE, ENABLE);
|
||||||
|
|
||||||
|
DEFINE_FLOW_REG_BIT_ENUM(RAM_REPAIR_REQ, 0, DISABLE, ENABLE);
|
||||||
|
DEFINE_FLOW_REG_BIT_ENUM(RAM_REPAIR_STS, 1, REQUESTED, DONE);
|
||||||
|
|
||||||
DEFINE_FLOW_REG_BIT_ENUM(BPMP_CLUSTER_CONTROL_ACTIVE_CLUSTER, 0, FAST, SLOW);
|
DEFINE_FLOW_REG_BIT_ENUM(BPMP_CLUSTER_CONTROL_ACTIVE_CLUSTER, 0, FAST, SLOW);
|
||||||
DEFINE_FLOW_REG_BIT_ENUM(BPMP_CLUSTER_CONTROL_CLUSTER_SWITCH_ENABLE, 1, DISABLE, ENABLE);
|
DEFINE_FLOW_REG_BIT_ENUM(BPMP_CLUSTER_CONTROL_CLUSTER_SWITCH_ENABLE, 1, DISABLE, ENABLE);
|
||||||
DEFINE_FLOW_REG_BIT_ENUM(BPMP_CLUSTER_CONTROL_ACTIVE_CLUSTER_LOCK, 2, DISABLE, ENABLE);
|
DEFINE_FLOW_REG_BIT_ENUM(BPMP_CLUSTER_CONTROL_ACTIVE_CLUSTER_LOCK, 2, DISABLE, ENABLE);
|
||||||
|
|
|
@ -20,3 +20,20 @@
|
||||||
|
|
||||||
#define MSELECT_CONFIG (0x000)
|
#define MSELECT_CONFIG (0x000)
|
||||||
|
|
||||||
|
#define MSELECT_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (MSELECT, NAME)
|
||||||
|
#define MSELECT_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (MSELECT, NAME, VALUE)
|
||||||
|
#define MSELECT_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (MSELECT, NAME, ENUM)
|
||||||
|
#define MSELECT_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(MSELECT, NAME, __COND__, TRUE_ENUM, FALSE_ENUM)
|
||||||
|
|
||||||
|
#define DEFINE_MSELECT_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (MSELECT, NAME, __OFFSET__, __WIDTH__)
|
||||||
|
#define DEFINE_MSELECT_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (MSELECT, NAME, __OFFSET__, ZERO, ONE)
|
||||||
|
#define DEFINE_MSELECT_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (MSELECT, NAME, __OFFSET__, ZERO, ONE, TWO, THREE)
|
||||||
|
#define DEFINE_MSELECT_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(MSELECT, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN)
|
||||||
|
#define DEFINE_MSELECT_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (MSELECT, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
|
||||||
|
|
||||||
|
DEFINE_MSELECT_REG_BIT_ENUM(CONFIG_ERR_RESP_EN_SLAVE1, 24, DISABLE, ENABLE);
|
||||||
|
DEFINE_MSELECT_REG_BIT_ENUM(CONFIG_ERR_RESP_EN_SLAVE2, 25, DISABLE, ENABLE);
|
||||||
|
DEFINE_MSELECT_REG_BIT_ENUM(CONFIG_WRAP_TO_INCR_SLAVE0, 27, DISABLE, ENABLE);
|
||||||
|
DEFINE_MSELECT_REG_BIT_ENUM(CONFIG_WRAP_TO_INCR_SLAVE1, 28, DISABLE, ENABLE);
|
||||||
|
DEFINE_MSELECT_REG_BIT_ENUM(CONFIG_WRAP_TO_INCR_SLAVE2, 29, DISABLE, ENABLE);
|
||||||
|
DEFINE_MSELECT_REG_BIT_ENUM(CONFIG_WRAP_TO_INCR_SLAVE3, 30, DISABLE, ENABLE);
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <vapours.hpp>
|
||||||
|
|
||||||
|
#define PG_UP(x) (0x60000000 + x)
|
||||||
|
|
||||||
|
#define PG_UP_TAG (0x000)
|
||||||
|
|
||||||
|
#define PG_UP_TAG_PID_COP 0xAAAAAAAA
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <vapours.hpp>
|
||||||
|
|
||||||
|
#define PINMUX_AUX_GEN1_I2C_SCL (0x30BC)
|
||||||
|
#define PINMUX_AUX_GEN1_I2C_SDA (0x30C0)
|
||||||
|
#define PINMUX_AUX_PWR_I2C_SCL (0x30DC)
|
||||||
|
#define PINMUX_AUX_PWR_I2C_SDA (0x30E0)
|
||||||
|
|
||||||
|
#define PINMUX_AUX_UART1_TX (0x30E4)
|
||||||
|
#define PINMUX_AUX_UART1_RX (0x30E8)
|
||||||
|
#define PINMUX_AUX_UART1_RTS (0x30EC)
|
||||||
|
#define PINMUX_AUX_UART1_CTS (0x30F0)
|
||||||
|
#define PINMUX_AUX_UART2_TX (0x30F4)
|
||||||
|
#define PINMUX_AUX_UART2_RX (0x30F8)
|
||||||
|
#define PINMUX_AUX_UART2_RTS (0x30FC)
|
||||||
|
#define PINMUX_AUX_UART2_CTS (0x3100)
|
||||||
|
#define PINMUX_AUX_UART3_TX (0x3104)
|
||||||
|
#define PINMUX_AUX_UART3_RX (0x3108)
|
||||||
|
#define PINMUX_AUX_UART3_RTS (0x310C)
|
||||||
|
#define PINMUX_AUX_UART3_CTS (0x3110)
|
||||||
|
#define PINMUX_AUX_DVFS_PWM (0x3184)
|
||||||
|
#define PINMUX_AUX_GPIO_PA6 (0x3244)
|
||||||
|
|
||||||
|
#define PINMUX_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (PINMUX, NAME)
|
||||||
|
#define PINMUX_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (PINMUX, NAME, VALUE)
|
||||||
|
#define PINMUX_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (PINMUX, NAME, ENUM)
|
||||||
|
#define PINMUX_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(PINMUX, NAME, __COND__, TRUE_ENUM, FALSE_ENUM)
|
||||||
|
|
||||||
|
#define DEFINE_PINMUX_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (PINMUX, NAME, __OFFSET__, __WIDTH__)
|
||||||
|
#define DEFINE_PINMUX_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (PINMUX, NAME, __OFFSET__, ZERO, ONE)
|
||||||
|
#define DEFINE_PINMUX_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (PINMUX, NAME, __OFFSET__, ZERO, ONE, TWO, THREE)
|
||||||
|
#define DEFINE_PINMUX_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(PINMUX, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN)
|
||||||
|
#define DEFINE_PINMUX_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (PINMUX, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
|
||||||
|
|
||||||
|
DEFINE_PINMUX_REG_TWO_BIT_ENUM(AUX_PUPD, 2, NONE, PULL_DOWN, PULL_UP, RSVD);
|
||||||
|
DEFINE_PINMUX_REG_BIT_ENUM(AUX_TRISTATE, 4, PASSTHROUGH, TRISTATE);
|
||||||
|
DEFINE_PINMUX_REG_BIT_ENUM(AUX_PARK, 5, NORMAL, PARKED);
|
||||||
|
DEFINE_PINMUX_REG_BIT_ENUM(AUX_E_INPUT, 6, DISABLE, ENABLE);
|
||||||
|
DEFINE_PINMUX_REG_BIT_ENUM(AUX_LOCK, 7, DISABLE, ENABLE);
|
||||||
|
DEFINE_PINMUX_REG_BIT_ENUM(AUX_E_LPDR, 8, DISABLE, ENABLE);
|
||||||
|
DEFINE_PINMUX_REG_BIT_ENUM(AUX_E_OD, 11, DISABLE, ENABLE);
|
||||||
|
DEFINE_PINMUX_REG_BIT_ENUM(AUX_E_SCHMT, 12, DISABLE, ENABLE);
|
||||||
|
|
||||||
|
DEFINE_PINMUX_REG_TWO_BIT_ENUM(AUX_GEN1_I2C_PM, 0, I2C1, RSVD1, RSVD2, RSVD3);
|
||||||
|
DEFINE_PINMUX_REG_TWO_BIT_ENUM(AUX_PWR_I2C_PM, 0, I2CPMU, RSVD1, RSVD2, RSVD3);
|
||||||
|
|
||||||
|
DEFINE_PINMUX_REG_TWO_BIT_ENUM(AUX_UART1_PM, 0, UARTA, RSVD1, RSVD2, RSVD3);
|
||||||
|
DEFINE_PINMUX_REG_TWO_BIT_ENUM(AUX_UART2_PM, 0, UARTB, I2S4A, RSVD2, UART);
|
||||||
|
DEFINE_PINMUX_REG_TWO_BIT_ENUM(AUX_UART3_PM, 0, UARTC, SPI4, RSVD2, RSVD3);
|
||||||
|
|
||||||
|
DEFINE_PINMUX_REG_TWO_BIT_ENUM(AUX_DVFS_PWM_PM, 0, RSVD0, CLDVFS, SPI3, RSVD3);
|
||||||
|
|
||||||
|
DEFINE_PINMUX_REG_TWO_BIT_ENUM(AUX_GPIO_PA6_PM, 0, SATA, RSVD1, RSVD2, RSVD3);
|
|
@ -50,6 +50,7 @@
|
||||||
#define APBDEV_PMC_WAKE2_LVL (0x164)
|
#define APBDEV_PMC_WAKE2_LVL (0x164)
|
||||||
#define APBDEV_PMC_WAKE2_STATUS (0x168)
|
#define APBDEV_PMC_WAKE2_STATUS (0x168)
|
||||||
#define APBDEV_PMC_AUTO_WAKE2_LVL_MASK (0x170)
|
#define APBDEV_PMC_AUTO_WAKE2_LVL_MASK (0x170)
|
||||||
|
#define APBDEV_PMC_OSC_EDPD_OVER (0x1A4)
|
||||||
#define APBDEV_PMC_CLK_OUT_CNTRL (0x1A8)
|
#define APBDEV_PMC_CLK_OUT_CNTRL (0x1A8)
|
||||||
#define APBDEV_PMC_IO_DPD_REQ (0x1B8)
|
#define APBDEV_PMC_IO_DPD_REQ (0x1B8)
|
||||||
#define APBDEV_PMC_IO_DPD_STATUS (0x1BC)
|
#define APBDEV_PMC_IO_DPD_STATUS (0x1BC)
|
||||||
|
@ -59,6 +60,7 @@
|
||||||
#define APBDEV_PMC_SCRATCH45 (0x234)
|
#define APBDEV_PMC_SCRATCH45 (0x234)
|
||||||
#define APBDEV_PMC_SCRATCH46 (0x238)
|
#define APBDEV_PMC_SCRATCH46 (0x238)
|
||||||
#define APBDEV_PMC_TSC_MULT (0x2B4)
|
#define APBDEV_PMC_TSC_MULT (0x2B4)
|
||||||
|
#define APBDEV_PMC_STICKY_BITS (0x2C0)
|
||||||
#define APBDEV_PMC_WEAK_BIAS (0x2C8)
|
#define APBDEV_PMC_WEAK_BIAS (0x2C8)
|
||||||
#define APBDEV_PMC_GPU_RG_CNTRL (0x2D4)
|
#define APBDEV_PMC_GPU_RG_CNTRL (0x2D4)
|
||||||
#define APBDEV_PMC_CNTRL2 (0x440)
|
#define APBDEV_PMC_CNTRL2 (0x440)
|
||||||
|
@ -162,6 +164,8 @@ enum APBDEV_PMC_PWRGATE_TOGGLE_PARTID : u8 {
|
||||||
APBDEV_PMC_PWRGATE_TOGGLE_PARTID_VE2 = 29,
|
APBDEV_PMC_PWRGATE_TOGGLE_PARTID_VE2 = 29,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DEFINE_PMC_REG_BIT_ENUM(REMOVE_CLAMPING_COMMAND_CRAIL, 0, DISABLE, ENABLE);
|
||||||
|
|
||||||
enum APBDEV_PMC_PWRGATE_STATUS_STATUS {
|
enum APBDEV_PMC_PWRGATE_STATUS_STATUS {
|
||||||
APBDEV_PMC_PWRGATE_STATUS_STATUS_OFF = 0,
|
APBDEV_PMC_PWRGATE_STATUS_STATUS_OFF = 0,
|
||||||
APBDEV_PMC_PWRGATE_STATUS_STATUS_ON = 1,
|
APBDEV_PMC_PWRGATE_STATUS_STATUS_ON = 1,
|
||||||
|
@ -221,4 +225,11 @@ DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_XUSBC, 22, DISABLE, ENABLE);
|
||||||
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_VIC, 23, DISABLE, ENABLE);
|
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_VIC, 23, DISABLE, ENABLE);
|
||||||
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_IRAM, 24, DISABLE, ENABLE);
|
DEFINE_PMC_REG_BIT_ENUM(CLAMP_STATUS_IRAM, 24, DISABLE, ENABLE);
|
||||||
|
|
||||||
|
DEFINE_PMC_REG(OSC_EDPD_OVER_XOFS, 1, 6);
|
||||||
|
|
||||||
|
DEFINE_PMC_REG_BIT_ENUM(STICKY_BITS_HDA_LPBK_DIS, 0, DISABLE, ENABLE);
|
||||||
|
DEFINE_PMC_REG_BIT_ENUM(STICKY_BITS_JTAG_STS, 6, ENABLE, DISABLE);
|
||||||
|
|
||||||
DEFINE_PMC_REG_BIT_ENUM(CNTRL2_WAKE_DET_EN, 9, DISABLE, ENABLE);
|
DEFINE_PMC_REG_BIT_ENUM(CNTRL2_WAKE_DET_EN, 9, DISABLE, ENABLE);
|
||||||
|
|
||||||
|
DEFINE_PMC_REG_BIT_ENUM(SEC_DISABLE2_WRITE21, 26, OFF, ON);
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <vapours.hpp>
|
#include <vapours.hpp>
|
||||||
|
|
||||||
#define SB_CSR (0x200)
|
#define SB_CSR (0x200)
|
||||||
|
#define SB_PFCFG (0x208)
|
||||||
#define SB_AA64_RESET_LOW (0x230)
|
#define SB_AA64_RESET_LOW (0x230)
|
||||||
#define SB_AA64_RESET_HIGH (0x234)
|
#define SB_AA64_RESET_HIGH (0x234)
|
||||||
|
|
||||||
|
@ -39,3 +40,8 @@ DEFINE_SB_REG_BIT_ENUM(CSR_HANG, 6, DISABLE, ENABLE);
|
||||||
DEFINE_SB_REG_BIT_ENUM(CSR_SWDM_ENABLE, 7, DISABLE, ENABLE);
|
DEFINE_SB_REG_BIT_ENUM(CSR_SWDM_ENABLE, 7, DISABLE, ENABLE);
|
||||||
DEFINE_SB_REG(CSR_SWDM_FAIL_COUNT, 8, 4);
|
DEFINE_SB_REG(CSR_SWDM_FAIL_COUNT, 8, 4);
|
||||||
DEFINE_SB_REG(CSR_COT_FAIL_COUNT, 12, 4);
|
DEFINE_SB_REG(CSR_COT_FAIL_COUNT, 12, 4);
|
||||||
|
|
||||||
|
DEFINE_SB_REG_BIT_ENUM(PFCFG_SPNIDEN, 0, DISABLE, ENABLE);
|
||||||
|
DEFINE_SB_REG_BIT_ENUM(PFCFG_SPIDEN, 1, DISABLE, ENABLE);
|
||||||
|
DEFINE_SB_REG_BIT_ENUM(PFCFG_NIDEN, 2, DISABLE, ENABLE);
|
||||||
|
DEFINE_SB_REG_BIT_ENUM(PFCFG_DBGEN, 3, DISABLE, ENABLE);
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <vapours.hpp>
|
#include <vapours.hpp>
|
||||||
|
|
||||||
|
#define TIMERUS_USEC_CFG (0x014)
|
||||||
#define TIMER_SHARED_TIMER_SECURE_CFG (0x1A4)
|
#define TIMER_SHARED_TIMER_SECURE_CFG (0x1A4)
|
||||||
|
|
||||||
#define TIMER_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (TIMER, NAME)
|
#define TIMER_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (TIMER, NAME)
|
||||||
|
@ -30,6 +30,9 @@
|
||||||
#define DEFINE_TIMER_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(TIMER, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN)
|
#define DEFINE_TIMER_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(TIMER, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN)
|
||||||
#define DEFINE_TIMER_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (TIMER, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
|
#define DEFINE_TIMER_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (TIMER, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
|
||||||
|
|
||||||
|
DEFINE_TIMER_REG(USEC_CFG_USEC_DIVISOR, 0, 8);
|
||||||
|
DEFINE_TIMER_REG(USEC_CFG_USEC_DIVIDEND, 8, 8);
|
||||||
|
|
||||||
DEFINE_TIMER_REG_BIT_ENUM(SHARED_TIMER_SECURE_CFG_TMR5, 5, DISABLE, ENABLE);
|
DEFINE_TIMER_REG_BIT_ENUM(SHARED_TIMER_SECURE_CFG_TMR5, 5, DISABLE, ENABLE);
|
||||||
DEFINE_TIMER_REG_BIT_ENUM(SHARED_TIMER_SECURE_CFG_TMR6, 6, DISABLE, ENABLE);
|
DEFINE_TIMER_REG_BIT_ENUM(SHARED_TIMER_SECURE_CFG_TMR6, 6, DISABLE, ENABLE);
|
||||||
DEFINE_TIMER_REG_BIT_ENUM(SHARED_TIMER_SECURE_CFG_TMR7, 7, DISABLE, ENABLE);
|
DEFINE_TIMER_REG_BIT_ENUM(SHARED_TIMER_SECURE_CFG_TMR7, 7, DISABLE, ENABLE);
|
||||||
|
|
|
@ -20,6 +20,11 @@ namespace ams::fuse {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
struct BypassEntry {
|
||||||
|
u32 offset;
|
||||||
|
u32 value;
|
||||||
|
};
|
||||||
|
|
||||||
struct OdmWord2 {
|
struct OdmWord2 {
|
||||||
using DeviceUniqueKeyGeneration = util::BitPack32::Field<0, 5, int>;
|
using DeviceUniqueKeyGeneration = util::BitPack32::Field<0, 5, int>;
|
||||||
using Reserved = util::BitPack32::Field<5, 27, int>;
|
using Reserved = util::BitPack32::Field<5, 27, int>;
|
||||||
|
@ -135,6 +140,12 @@ namespace ams::fuse {
|
||||||
|
|
||||||
constexpr inline int NumFuseIncrements = util::size(FuseVersionIncrementFirmwares);
|
constexpr inline int NumFuseIncrements = util::size(FuseVersionIncrementFirmwares);
|
||||||
|
|
||||||
|
constexpr const BypassEntry FuseBypassEntries[] = {
|
||||||
|
/* Don't configure any fuse bypass entries. */
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr inline int NumFuseBypassEntries = util::size(FuseBypassEntries);
|
||||||
|
|
||||||
/* Verify that the fuse version increment list is sorted. */
|
/* Verify that the fuse version increment list is sorted. */
|
||||||
static_assert([] {
|
static_assert([] {
|
||||||
for (size_t i = 0; i < util::size(FuseVersionIncrementFirmwares) - 1; ++i) {
|
for (size_t i = 0; i < util::size(FuseVersionIncrementFirmwares) - 1; ++i) {
|
||||||
|
@ -169,7 +180,7 @@ namespace ams::fuse {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lockout() {
|
void Lockout() {
|
||||||
reg::Write(GetRegisters().FUSE_DISABLEREGPROGRAM, FUSE_REG_BITS_ENUM(DISABLEREGPROGRAM_DISABLEREGPROGRAM_VAL, ENABLE));
|
reg::Write(GetRegisters().FUSE_DISABLEREGPROGRAM, FUSE_REG_BITS_ENUM(DISABLEREGPROGRAM_VAL, ENABLE));
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 ReadWord(int address) {
|
u32 ReadWord(int address) {
|
||||||
|
@ -367,4 +378,49 @@ namespace ams::fuse {
|
||||||
return g_has_rcm_bug_patch;
|
return g_has_rcm_bug_patch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsOdmProductionMode() {
|
||||||
|
return reg::HasValue(GetChipRegisters().FUSE_SECURITY_MODE, FUSE_REG_BITS_ENUM(SECURITY_MODE_SECURITY_MODE, ENABLED));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigureFuseBypass() {
|
||||||
|
/* Make the fuse registers visible. */
|
||||||
|
clkrst::SetFuseVisibility(true);
|
||||||
|
|
||||||
|
/* Only perform bypass configuration if fuse programming is allowed. */
|
||||||
|
if (!reg::HasValue(GetRegisters().FUSE_DISABLEREGPROGRAM, FUSE_REG_BITS_ENUM(DISABLEREGPROGRAM_VAL, DISABLE))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable software writes to fuses. */
|
||||||
|
reg::ReadWrite(GetRegisters().FUSE_WRITE_ACCESS_SW, FUSE_REG_BITS_ENUM(WRITE_ACCESS_SW_CTRL, READWRITE),
|
||||||
|
FUSE_REG_BITS_ENUM(WRITE_ACCESS_SW_STATUS, WRITE));
|
||||||
|
|
||||||
|
/* Enable fuse bypass. */
|
||||||
|
reg::Write(GetRegisters().FUSE_FUSEBYPASS, FUSE_REG_BITS_ENUM(FUSEBYPASS_VAL, ENABLE));
|
||||||
|
|
||||||
|
/* Override fuses. */
|
||||||
|
for (const auto &entry : FuseBypassEntries) {
|
||||||
|
reg::Write(g_register_address + entry.offset, entry.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable software writes to fuses. */
|
||||||
|
reg::ReadWrite(GetRegisters().FUSE_WRITE_ACCESS_SW, FUSE_REG_BITS_ENUM(WRITE_ACCESS_SW_CTRL, READONLY));
|
||||||
|
|
||||||
|
/* NOTE: Here, NVidia almost certainly intends to *disable* fuse bypass, but they write enable instead... */
|
||||||
|
reg::Write(GetRegisters().FUSE_FUSEBYPASS, FUSE_REG_BITS_ENUM(FUSEBYPASS_VAL, ENABLE));
|
||||||
|
|
||||||
|
/* NOTE: Here, NVidia intends to disable fuse programming. However, they fuck up -- and *clear* the disable bit. */
|
||||||
|
/* It should be noted that this is a sticky bit, and thus software clears have no effect. */
|
||||||
|
reg::ReadWrite(GetRegisters().FUSE_DISABLEREGPROGRAM, FUSE_REG_BITS_ENUM(DISABLEREGPROGRAM_VAL, DISABLE));
|
||||||
|
|
||||||
|
/* Configure FUSE_PRIVATEKEYDISABLE_TZ_STICKY_BIT. */
|
||||||
|
constexpr const uintptr_t PMC = secmon::MemoryRegionPhysicalDevicePmc.GetAddress();
|
||||||
|
const bool key_invisible = reg::HasValue(PMC + APBDEV_PMC_SECURE_SCRATCH21, FUSE_REG_BITS_ENUM(PRIVATEKEYDISABLE_TZ_STICKY_BIT_VAL, KEY_INVISIBLE));
|
||||||
|
|
||||||
|
reg::ReadWrite(GetRegisters().FUSE_PRIVATEKEYDISABLE, FUSE_REG_BITS_ENUM_SEL(PRIVATEKEYDISABLE_TZ_STICKY_BIT_VAL, key_invisible, KEY_INVISIBLE, KEY_VISIBLE));
|
||||||
|
|
||||||
|
/* Write-lock PMC_SECURE_SCRATCH21. */
|
||||||
|
reg::ReadWrite(PMC + APBDEV_PMC_SEC_DISABLE2, PMC_REG_BITS_ENUM(SEC_DISABLE2_WRITE21, ON));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,6 +241,13 @@ namespace ams::fuse {
|
||||||
DEFINE_FUSE_REG_BIT_ENUM(PRIVATEKEYDISABLE_TZ_STICKY_BIT_VAL, 4, KEY_VISIBLE, KEY_INVISIBLE);
|
DEFINE_FUSE_REG_BIT_ENUM(PRIVATEKEYDISABLE_TZ_STICKY_BIT_VAL, 4, KEY_VISIBLE, KEY_INVISIBLE);
|
||||||
DEFINE_FUSE_REG_BIT_ENUM(PRIVATEKEYDISABLE_PRIVATEKEYDISABLE_VAL_KEY, 0, VISIBLE, INVISIBLE);
|
DEFINE_FUSE_REG_BIT_ENUM(PRIVATEKEYDISABLE_PRIVATEKEYDISABLE_VAL_KEY, 0, VISIBLE, INVISIBLE);
|
||||||
|
|
||||||
DEFINE_FUSE_REG_BIT_ENUM(DISABLEREGPROGRAM_DISABLEREGPROGRAM_VAL, 0, DISABLE, ENABLE);
|
DEFINE_FUSE_REG_BIT_ENUM(FUSEBYPASS_VAL, 0, DISABLE, ENABLE);
|
||||||
|
|
||||||
|
DEFINE_FUSE_REG_BIT_ENUM(DISABLEREGPROGRAM_VAL, 0, DISABLE, ENABLE);
|
||||||
|
|
||||||
|
DEFINE_FUSE_REG_BIT_ENUM(WRITE_ACCESS_SW_CTRL, 0, READWRITE, READONLY);
|
||||||
|
DEFINE_FUSE_REG_BIT_ENUM(WRITE_ACCESS_SW_STATUS, 16, NOWRITE, WRITE);
|
||||||
|
|
||||||
|
DEFINE_FUSE_REG_BIT_ENUM(SECURITY_MODE_SECURITY_MODE, 0, DISABLED, ENABLED);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#include <exosphere.hpp>
|
#include <exosphere.hpp>
|
||||||
#include "pinmux_registers.hpp"
|
|
||||||
|
|
||||||
namespace ams::pinmux {
|
namespace ams::pinmux {
|
||||||
|
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2018-2020 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 <exosphere.hpp>
|
|
||||||
|
|
||||||
namespace ams::pinmux {
|
|
||||||
|
|
||||||
#define PINMUX_AUX_GEN1_I2C_SCL (0x30BC)
|
|
||||||
#define PINMUX_AUX_GEN1_I2C_SDA (0x30C0)
|
|
||||||
#define PINMUX_AUX_PWR_I2C_SCL (0x30DC)
|
|
||||||
#define PINMUX_AUX_PWR_I2C_SDA (0x30E0)
|
|
||||||
|
|
||||||
#define PINMUX_AUX_UART1_TX (0x30E4)
|
|
||||||
#define PINMUX_AUX_UART1_RX (0x30E8)
|
|
||||||
#define PINMUX_AUX_UART1_RTS (0x30EC)
|
|
||||||
#define PINMUX_AUX_UART1_CTS (0x30F0)
|
|
||||||
#define PINMUX_AUX_UART2_TX (0x30F4)
|
|
||||||
#define PINMUX_AUX_UART2_RX (0x30F8)
|
|
||||||
#define PINMUX_AUX_UART2_RTS (0x30FC)
|
|
||||||
#define PINMUX_AUX_UART2_CTS (0x3100)
|
|
||||||
#define PINMUX_AUX_UART3_TX (0x3104)
|
|
||||||
#define PINMUX_AUX_UART3_RX (0x3108)
|
|
||||||
#define PINMUX_AUX_UART3_RTS (0x310C)
|
|
||||||
#define PINMUX_AUX_UART3_CTS (0x3110)
|
|
||||||
|
|
||||||
#define PINMUX_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (PINMUX, NAME)
|
|
||||||
#define PINMUX_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (PINMUX, NAME, VALUE)
|
|
||||||
#define PINMUX_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (PINMUX, NAME, ENUM)
|
|
||||||
#define PINMUX_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(PINMUX, NAME, __COND__, TRUE_ENUM, FALSE_ENUM)
|
|
||||||
|
|
||||||
#define DEFINE_PINMUX_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (PINMUX, NAME, __OFFSET__, __WIDTH__)
|
|
||||||
#define DEFINE_PINMUX_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (PINMUX, NAME, __OFFSET__, ZERO, ONE)
|
|
||||||
#define DEFINE_PINMUX_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (PINMUX, NAME, __OFFSET__, ZERO, ONE, TWO, THREE)
|
|
||||||
#define DEFINE_PINMUX_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(PINMUX, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN)
|
|
||||||
#define DEFINE_PINMUX_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (PINMUX, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
|
|
||||||
|
|
||||||
DEFINE_PINMUX_REG_TWO_BIT_ENUM(AUX_PUPD, 2, NONE, PULL_DOWN, PULL_UP, RSVD);
|
|
||||||
DEFINE_PINMUX_REG_BIT_ENUM(AUX_TRISTATE, 4, PASSTHROUGH, TRISTATE);
|
|
||||||
DEFINE_PINMUX_REG_BIT_ENUM(AUX_PARK, 5, NORMAL, PARKED);
|
|
||||||
DEFINE_PINMUX_REG_BIT_ENUM(AUX_E_INPUT, 6, DISABLE, ENABLE);
|
|
||||||
DEFINE_PINMUX_REG_BIT_ENUM(AUX_LOCK, 7, DISABLE, ENABLE);
|
|
||||||
DEFINE_PINMUX_REG_BIT_ENUM(AUX_E_LPDR, 8, DISABLE, ENABLE);
|
|
||||||
DEFINE_PINMUX_REG_BIT_ENUM(AUX_E_OD, 11, DISABLE, ENABLE);
|
|
||||||
DEFINE_PINMUX_REG_BIT_ENUM(AUX_E_SCHMT, 12, DISABLE, ENABLE);
|
|
||||||
|
|
||||||
DEFINE_PINMUX_REG_TWO_BIT_ENUM(AUX_GEN1_I2C_PM, 0, I2C1, RSVD1, RSVD2, RSVD3);
|
|
||||||
DEFINE_PINMUX_REG_TWO_BIT_ENUM(AUX_PWR_I2C_PM, 0, I2CPMU, RSVD1, RSVD2, RSVD3);
|
|
||||||
|
|
||||||
DEFINE_PINMUX_REG_TWO_BIT_ENUM(AUX_UART1_PM, 0, UARTA, RSVD1, RSVD2, RSVD3);
|
|
||||||
DEFINE_PINMUX_REG_TWO_BIT_ENUM(AUX_UART2_PM, 0, UARTB, I2S4A, RSVD2, UART);
|
|
||||||
DEFINE_PINMUX_REG_TWO_BIT_ENUM(AUX_UART3_PM, 0, UARTC, SPI4, RSVD2, RSVD3);
|
|
||||||
|
|
||||||
}
|
|
|
@ -60,6 +60,10 @@ namespace ams::pmic {
|
||||||
i2c::SendByte(i2c::Port_5, I2cAddressEristaMax77621, Max77620RegisterGpio0 + gpio, MAX77620_CNFG_GPIO_DRV_PUSHPULL | MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH);
|
i2c::SendByte(i2c::Port_5, I2cAddressEristaMax77621, Max77620RegisterGpio0 + gpio, MAX77620_CNFG_GPIO_DRV_PUSHPULL | MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetEnBitErista() {
|
||||||
|
i2c::SendByte(i2c::Port_5, I2cAddressEristaMax77621, Max77621RegisterVOut, MAX77621_VOUT_ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
void EnableVddCpuErista() {
|
void EnableVddCpuErista() {
|
||||||
/* Enable GPIO 5. */
|
/* Enable GPIO 5. */
|
||||||
/* TODO: What does this control? */
|
/* TODO: What does this control? */
|
||||||
|
@ -87,6 +91,11 @@ namespace ams::pmic {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetEnBitMariko(Regulator regulator) {
|
||||||
|
/* Set EN_M3_LPM to enable BUCK Master 3 low power mode. */
|
||||||
|
i2c::SendByte(i2c::Port_5, GetI2cAddressForMarikoMax77812(regulator), Max77812RegisterEnCtrl, 0x40);
|
||||||
|
}
|
||||||
|
|
||||||
void EnableVddCpuMariko(Regulator regulator) {
|
void EnableVddCpuMariko(Regulator regulator) {
|
||||||
const int address = GetI2cAddressForMarikoMax77812(regulator);
|
const int address = GetI2cAddressForMarikoMax77812(regulator);
|
||||||
|
|
||||||
|
@ -118,6 +127,17 @@ namespace ams::pmic {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetEnBit(Regulator regulator) {
|
||||||
|
switch (regulator) {
|
||||||
|
case Regulator_Erista_Max77621:
|
||||||
|
return SetEnBitErista();
|
||||||
|
case Regulator_Mariko_Max77812_A:
|
||||||
|
case Regulator_Mariko_Max77812_B:
|
||||||
|
return SetEnBitMariko(regulator);
|
||||||
|
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EnableVddCpu(Regulator regulator) {
|
void EnableVddCpu(Regulator regulator) {
|
||||||
switch (regulator) {
|
switch (regulator) {
|
||||||
case Regulator_Erista_Max77621:
|
case Regulator_Erista_Max77621:
|
||||||
|
|
|
@ -308,6 +308,37 @@ namespace ams::se {
|
||||||
ExecuteOperation(SE, SE_OPERATION_OP_START, dst, dst_size, src, aligned_size);
|
ExecuteOperation(SE, SE_OPERATION_OP_START, dst, dst_size, src, aligned_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DecryptAesCbc(void *dst, size_t dst_size, int slot, const void *src, size_t src_size, const void *iv, size_t iv_size, AesMode mode) {
|
||||||
|
/* If nothing to decrypt, succeed. */
|
||||||
|
if (src_size == 0) { return; }
|
||||||
|
|
||||||
|
/* Validate input. */
|
||||||
|
AMS_ABORT_UNLESS(iv_size == AesBlockSize);
|
||||||
|
AMS_ABORT_UNLESS(0 <= slot && slot < AesKeySlotCount);
|
||||||
|
|
||||||
|
/* Get the engine. */
|
||||||
|
auto *SE = GetRegisters();
|
||||||
|
|
||||||
|
/* Determine extents. */
|
||||||
|
const size_t num_blocks = src_size / AesBlockSize;
|
||||||
|
const size_t aligned_size = num_blocks * AesBlockSize;
|
||||||
|
AMS_ABORT_UNLESS(src_size == aligned_size);
|
||||||
|
|
||||||
|
/* Configure for aes-cbc encryption. */
|
||||||
|
SetConfig(SE, false, SE_CONFIG_DST_MEMORY);
|
||||||
|
SetAesConfig(SE, slot, false, AesConfigCbcDecrypt);
|
||||||
|
UpdateAesMode(SE, mode);
|
||||||
|
|
||||||
|
/* Set the iv. */
|
||||||
|
SetAesKeyIv(SE, slot, iv, iv_size);
|
||||||
|
|
||||||
|
/* Set the block count. */
|
||||||
|
SetBlockCount(SE, num_blocks);
|
||||||
|
|
||||||
|
/* Execute the operation. */
|
||||||
|
ExecuteOperation(SE, SE_OPERATION_OP_START, dst, dst_size, src, aligned_size);
|
||||||
|
}
|
||||||
|
|
||||||
void ComputeAes128Async(u32 out_ll_address, int slot, u32 in_ll_address, u32 size, DoneHandler handler, u32 config, bool encrypt, volatile SecurityEngineRegisters *SE) {
|
void ComputeAes128Async(u32 out_ll_address, int slot, u32 in_ll_address, u32 size, DoneHandler handler, u32 config, bool encrypt, volatile SecurityEngineRegisters *SE) {
|
||||||
/* If nothing to decrypt, succeed. */
|
/* If nothing to decrypt, succeed. */
|
||||||
if (size == 0) { return; }
|
if (size == 0) { return; }
|
||||||
|
@ -349,6 +380,35 @@ namespace ams::se {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClearAesKeyIv(int slot) {
|
||||||
|
/* Validate the key slot. */
|
||||||
|
AMS_ABORT_UNLESS(0 <= slot && slot < AesKeySlotCount);
|
||||||
|
|
||||||
|
/* Get the engine. */
|
||||||
|
auto *SE = GetRegisters();
|
||||||
|
|
||||||
|
/* Set each iv word in order. */
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
/* Select the keyslot original iv. */
|
||||||
|
reg::Write(SE->SE_CRYPTO_KEYTABLE_ADDR, SE_REG_BITS_VALUE(CRYPTO_KEYTABLE_ADDR_KEYIV_KEY_SLOT, slot),
|
||||||
|
SE_REG_BITS_ENUM (CRYPTO_KEYTABLE_ADDR_KEYIV_KEYIV_SEL, IV),
|
||||||
|
SE_REG_BITS_ENUM (CRYPTO_KEYTABLE_ADDR_KEYIV_IV_SEL, ORIGINAL_IV),
|
||||||
|
SE_REG_BITS_VALUE(CRYPTO_KEYTABLE_ADDR_KEYIV_KEY_WORD, i));
|
||||||
|
|
||||||
|
/* Set the iv word. */
|
||||||
|
SE->SE_CRYPTO_KEYTABLE_DATA = 0;
|
||||||
|
|
||||||
|
/* Select the keyslot updated iv. */
|
||||||
|
reg::Write(SE->SE_CRYPTO_KEYTABLE_ADDR, SE_REG_BITS_VALUE(CRYPTO_KEYTABLE_ADDR_KEYIV_KEY_SLOT, slot),
|
||||||
|
SE_REG_BITS_ENUM (CRYPTO_KEYTABLE_ADDR_KEYIV_KEYIV_SEL, IV),
|
||||||
|
SE_REG_BITS_ENUM (CRYPTO_KEYTABLE_ADDR_KEYIV_IV_SEL, UPDATED_IV),
|
||||||
|
SE_REG_BITS_VALUE(CRYPTO_KEYTABLE_ADDR_KEYIV_KEY_WORD, i));
|
||||||
|
|
||||||
|
/* Set the iv word. */
|
||||||
|
SE->SE_CRYPTO_KEYTABLE_DATA = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LockAesKeySlot(int slot, u32 flags) {
|
void LockAesKeySlot(int slot, u32 flags) {
|
||||||
/* Validate the key slot. */
|
/* Validate the key slot. */
|
||||||
AMS_ABORT_UNLESS(0 <= slot && slot < AesKeySlotCount);
|
AMS_ABORT_UNLESS(0 <= slot && slot < AesKeySlotCount);
|
||||||
|
@ -487,6 +547,14 @@ namespace ams::se {
|
||||||
return EncryptAesCbc(dst, dst_size, slot, src, src_size, iv, iv_size, AesMode_Aes256);
|
return EncryptAesCbc(dst, dst_size, slot, src, src_size, iv, iv_size, AesMode_Aes256);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DecryptAes128Cbc(void *dst, size_t dst_size, int slot, const void *src, size_t src_size, const void *iv, size_t iv_size) {
|
||||||
|
return DecryptAesCbc(dst, dst_size, slot, src, src_size, iv, iv_size, AesMode_Aes128);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DecryptAes256Cbc(void *dst, size_t dst_size, int slot, const void *src, size_t src_size, const void *iv, size_t iv_size) {
|
||||||
|
return DecryptAesCbc(dst, dst_size, slot, src, src_size, iv, iv_size, AesMode_Aes256);
|
||||||
|
}
|
||||||
|
|
||||||
void EncryptAes128CbcAsync(u32 out_ll_address, int slot, u32 in_ll_address, u32 size, const void *iv, size_t iv_size, DoneHandler handler) {
|
void EncryptAes128CbcAsync(u32 out_ll_address, int slot, u32 in_ll_address, u32 size, const void *iv, size_t iv_size, DoneHandler handler) {
|
||||||
/* Validate the iv. */
|
/* Validate the iv. */
|
||||||
AMS_ABORT_UNLESS(iv_size == AesBlockSize);
|
AMS_ABORT_UNLESS(iv_size == AesBlockSize);
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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 <vapours.hpp>
|
||||||
|
|
||||||
|
namespace ams::crypto {
|
||||||
|
|
||||||
|
bool IsSameBytes(const void *lhs, const void *rhs, size_t size) {
|
||||||
|
bool result;
|
||||||
|
u8 xor_acc, ltmp, rtmp;
|
||||||
|
size_t index;
|
||||||
|
|
||||||
|
__asm__ __volatile__(
|
||||||
|
/* Clear registers and prepare for comparison. */
|
||||||
|
" movs %[xor_acc], #0\n"
|
||||||
|
" movs %[index], #0\n"
|
||||||
|
" b 1f\n"
|
||||||
|
|
||||||
|
/* Compare one byte in constant time. */
|
||||||
|
"0:\n"
|
||||||
|
" ldrb %[ltmp], [%[lhs]]\n"
|
||||||
|
" ldrb %[rtmp], [%[rhs]]\n"
|
||||||
|
" adds %[lhs], #1\n"
|
||||||
|
" adds %[rhs], #1\n"
|
||||||
|
" eors %[ltmp], %[ltmp], %[rtmp]\n"
|
||||||
|
" orrs %[xor_acc], %[xor_acc], %[ltmp]\n"
|
||||||
|
" adds %[index], #1\n"
|
||||||
|
|
||||||
|
/* Check if there is still data to compare. */
|
||||||
|
"1:\n"
|
||||||
|
" cmp %[index], %[size]\n"
|
||||||
|
" bcc 0b\n"
|
||||||
|
|
||||||
|
/* We're done, set result. */
|
||||||
|
" cmp %[xor_acc], #0\n"
|
||||||
|
" moveq %[result], #1\n"
|
||||||
|
" movne %[result], #0\n"
|
||||||
|
: [result]"=r"(result), [lhs]"+r"(lhs), [rhs]"+r"(rhs), [xor_acc]"=&r"(xor_acc), [index]"=&r"(index), [ltmp]"=&r"(ltmp), [rtmp]"=&r"(rtmp)
|
||||||
|
: [size]"r"(size)
|
||||||
|
: "cc"
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue