sdmmc: implement driver suitable for fs + bootloader
* sdmmc: begin skeletoning sdmmc driver * sdmmc: add most of SdHostStandardController * sdmmc: implement most of SdmmcController * sdmmc: Sdmmc2Controller * sdmmc: skeleton implementation of Sdmmc1Controller * sdmmc: complete abstract logic for Sdmmc1 power controller * sdmmc: implement gpio handling for sdmmc1-register-control * sdmmc: implement pinmux handling for sdmmc1-register-control * sdmmc: fix building for arm32 and in stratosphere context * sdmmc: implement voltage enable/set for sdmmc1-register-control * util: move T(V)SNPrintf from kernel to util * sdmmc: implement BaseDeviceAccessor * sdmmc: implement MmcDeviceAccessor * sdmmc: implement clock reset controller for register api * sdmmc: fix bug in WaitWhileCommandInhibit, add mmc accessors * exo: add sdmmc test program * sdmmc: fix speed mode extension, add CheckMmcConnection for debug * sdmmc: add DeviceDetector, gpio: implement client api * gpio: modernize client api instead of doing it the lazy way * sdmmc: SdCardDeviceAccessor impl * sdmmc: update test program to read first two sectors of sd card * sdmmc: fix vref sel * sdmmc: finish outward-facing api (untested) * ams: changes for libvapours including tegra register defs * sdmmc: remove hwinit
This commit is contained in:
@@ -648,7 +648,7 @@ namespace ams::secmon {
|
||||
reg::Read (MC + MC_SMMU_TLB_CONFIG);
|
||||
|
||||
/* Flush the entire page table cache, and read TLB_CONFIG to ensure the flush takes. */
|
||||
reg::Write(MC + MC_SMMU_PTC_FLUSH, 0);
|
||||
reg::Write(MC + MC_SMMU_PTC_FLUSH_0, 0);
|
||||
reg::Read (MC + MC_SMMU_TLB_CONFIG);
|
||||
|
||||
/* Flush the entire translation lookaside buffer, and read TLB_CONFIG to ensure the flush takes. */
|
||||
@@ -907,7 +907,7 @@ namespace ams::secmon {
|
||||
reg::Write(MC + MC_SMMU_PPCS1_ASID, MC_REG_BITS_ENUM(SMMU_PPCS1_ASID_PPCS1_SMMU_ENABLE, ENABLE), MC_REG_BITS_VALUE(SMMU_PPCS1_ASID_PPCS1_ASID, BpmpAsid));
|
||||
|
||||
/* Flush the entire page table cache, and read TLB_CONFIG to ensure the flush takes. */
|
||||
reg::Write(MC + MC_SMMU_PTC_FLUSH, 0);
|
||||
reg::Write(MC + MC_SMMU_PTC_FLUSH_0, 0);
|
||||
reg::Read (MC + MC_SMMU_TLB_CONFIG);
|
||||
|
||||
/* Flush the entire translation lookaside buffer, and read TLB_CONFIG to ensure the flush takes. */
|
||||
|
||||
@@ -22,7 +22,7 @@ SetRegisterAllowed(MC_SMMU_CONFIG); /* 0x010 */
|
||||
SetRegisterAllowed(MC_SMMU_PTB_ASID); /* 0x01C */
|
||||
SetRegisterAllowed(MC_SMMU_PTB_DATA); /* 0x020 */
|
||||
SetRegisterAllowed(MC_SMMU_TLB_FLUSH); /* 0x030 */
|
||||
SetRegisterAllowed(MC_SMMU_PTC_FLUSH); /* 0x034 */
|
||||
SetRegisterAllowed(MC_SMMU_PTC_FLUSH_0); /* 0x034 */
|
||||
SetRegisterAllowed(MC_EMEM_CFG); /* 0x050 */
|
||||
SetRegisterAllowed(MC_EMEM_ADR_CFG); /* 0x054 */
|
||||
SetRegisterAllowed(MC_EMEM_ARB_CFG); /* 0x090 */
|
||||
@@ -53,7 +53,7 @@ SetRegisterAllowed(MC_SMMU_DCB_ASID); /* 0x244 */
|
||||
SetRegisterAllowed(MC_SMMU_HC_ASID); /* 0x250 */
|
||||
SetRegisterAllowed(MC_SMMU_HDA_ASID); /* 0x254 */
|
||||
SetRegisterAllowed(MC_SMMU_ISP2_ASID); /* 0x258 */
|
||||
SetRegisterAllowed(MC_SMMU_NVENC_ASID); /* 0x264 */
|
||||
SetRegisterAllowed(MC_SMMU_MSENC_NVENC_ASID); /* 0x264 */
|
||||
SetRegisterAllowed(MC_SMMU_NV_ASID); /* 0x268 */
|
||||
SetRegisterAllowed(MC_SMMU_NV2_ASID); /* 0x26C */
|
||||
SetRegisterAllowed(MC_SMMU_PPCS_ASID); /* 0x270 */
|
||||
|
||||
108
exosphere/sdmmc_test/Makefile
Normal file
108
exosphere/sdmmc_test/Makefile
Normal file
@@ -0,0 +1,108 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
# 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 := $(call FIND_SOURCE_FILES,$(SOURCES),c)
|
||||
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
|
||||
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),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
|
||||
#---------------------------------------------------------------------------------------
|
||||
194
exosphere/sdmmc_test/sdmmc_test.ld
Normal file
194
exosphere/sdmmc_test/sdmmc_test.ld
Normal file
@@ -0,0 +1,194 @@
|
||||
OUTPUT_ARCH(arm)
|
||||
ENTRY(_ZN3ams10sdmmc_test5StartEv)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
NULL : ORIGIN = 0, LENGTH = 4K
|
||||
test_fw : ORIGIN = 0x40010000, LENGTH = 32K
|
||||
}
|
||||
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* =========== CODE section =========== */
|
||||
PROVIDE(__start__ = ORIGIN(test_fw));
|
||||
. = __start__;
|
||||
__code_start = . ;
|
||||
|
||||
.crt0 :
|
||||
{
|
||||
KEEP (*(.crt0 .crt0.*))
|
||||
. = ALIGN(8);
|
||||
} >test_fw
|
||||
|
||||
.vectors :
|
||||
{
|
||||
KEEP (*(.vectors .vectors.*))
|
||||
. = ALIGN(8);
|
||||
} >test_fw
|
||||
|
||||
.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);
|
||||
} >test_fw
|
||||
|
||||
.init :
|
||||
{
|
||||
KEEP( *(.init) )
|
||||
. = ALIGN(8);
|
||||
} >test_fw
|
||||
|
||||
.plt :
|
||||
{
|
||||
*(.plt)
|
||||
*(.iplt)
|
||||
. = ALIGN(8);
|
||||
} >test_fw
|
||||
|
||||
.fini :
|
||||
{
|
||||
KEEP( *(.fini) )
|
||||
. = ALIGN(8);
|
||||
} >test_fw
|
||||
|
||||
|
||||
/* =========== RODATA section =========== */
|
||||
. = ALIGN(8);
|
||||
__rodata_start = . ;
|
||||
|
||||
.rodata :
|
||||
{
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
. = ALIGN(8);
|
||||
} >test_fw
|
||||
|
||||
.eh_frame_hdr : { __eh_frame_hdr_start = .; *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) __eh_frame_hdr_end = .; } >test_fw
|
||||
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } >test_fw
|
||||
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } >test_fw
|
||||
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } >test_fw
|
||||
|
||||
.hash : { *(.hash) } >test_fw
|
||||
|
||||
/* =========== DATA section =========== */
|
||||
. = ALIGN(8);
|
||||
__data_start = . ;
|
||||
|
||||
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } >test_fw
|
||||
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } >test_fw
|
||||
.gnu_extab : ONLY_IF_RW { *(.gnu_extab*) } >test_fw
|
||||
.exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } >test_fw
|
||||
|
||||
.preinit_array ALIGN(8) :
|
||||
{
|
||||
PROVIDE (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE (__preinit_array_end = .);
|
||||
} >test_fw
|
||||
|
||||
.init_array ALIGN(8) :
|
||||
{
|
||||
PROVIDE (__init_array_start = .);
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array))
|
||||
PROVIDE (__init_array_end = .);
|
||||
} >test_fw
|
||||
|
||||
.fini_array ALIGN(8) :
|
||||
{
|
||||
PROVIDE (__fini_array_start = .);
|
||||
KEEP (*(.fini_array))
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
PROVIDE (__fini_array_end = .);
|
||||
} >test_fw
|
||||
|
||||
.ctors ALIGN(8) :
|
||||
{
|
||||
KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
} >test_fw
|
||||
|
||||
.dtors ALIGN(8) :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
} >test_fw
|
||||
|
||||
__got_start__ = .;
|
||||
|
||||
.got : { *(.got) *(.igot) } >test_fw
|
||||
.got.plt : { *(.got.plt) *(.igot.plt) } >test_fw
|
||||
|
||||
__got_end__ = .;
|
||||
|
||||
.data ALIGN(8) :
|
||||
{
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
SORT(CONSTRUCTORS)
|
||||
} >test_fw
|
||||
|
||||
__bss_start__ = .;
|
||||
.bss ALIGN(8) :
|
||||
{
|
||||
*(.dynbss)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(16);
|
||||
} >test_fw
|
||||
__bss_end__ = .;
|
||||
|
||||
__end__ = ABSOLUTE(.) ;
|
||||
|
||||
__total_size__ = (__end__ - __start__);
|
||||
|
||||
__stack_top__ = 0x40031000;
|
||||
__stack_bottom__ = 0x40030000;
|
||||
|
||||
/* ==================
|
||||
==== 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
exosphere/sdmmc_test/sdmmc_test.specs
Normal file
7
exosphere/sdmmc_test/sdmmc_test.specs
Normal file
@@ -0,0 +1,7 @@
|
||||
%rename link old_link
|
||||
|
||||
*link:
|
||||
%(old_link) -T %:getenv(TOPDIR /sdmmc_test.ld) --gc-sections --nmagic -nostdlib -nostartfiles
|
||||
|
||||
*startfile:
|
||||
crti%O%s crtbegin%O%s
|
||||
146
exosphere/sdmmc_test/source/sdmmc_test_main.cpp
Normal file
146
exosphere/sdmmc_test/source/sdmmc_test_main.cpp
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* 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::sdmmc_test {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr inline const uintptr_t PMC = secmon::MemoryRegionPhysicalDevicePmc.GetAddress();
|
||||
|
||||
constexpr inline auto Port = sdmmc::Port_SdCard0;
|
||||
alignas(8) constinit u8 g_sd_work_buffer[sdmmc::SdCardWorkBufferSize];
|
||||
|
||||
constexpr inline u32 SectorIndex = 0;
|
||||
constexpr inline u32 SectorCount = 2;
|
||||
|
||||
NORETURN void PmcMainReboot() {
|
||||
/* Write enable to MAIN_RESET. */
|
||||
reg::Write(PMC + APBDEV_PMC_CNTRL, PMC_REG_BITS_ENUM(CNTRL_MAIN_RESET, ENABLE));
|
||||
|
||||
/* Wait forever until we're reset. */
|
||||
AMS_INFINITE_LOOP();
|
||||
}
|
||||
|
||||
void CheckResult(const Result result) {
|
||||
volatile u32 * const DEBUG = reinterpret_cast<volatile u32 *>(0x4003C000);
|
||||
if (R_FAILED(result)) {
|
||||
DEBUG[1] = result.GetValue();
|
||||
PmcMainReboot();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Main() {
|
||||
/* Perform butchered hwinit. */
|
||||
/* TODO: replace with simpler, non-C logic. */
|
||||
/* nx_hwinit(); */
|
||||
|
||||
/* Clear output buffer for debug. */
|
||||
std::memset((void *)0x40038000, 0xAA, 0x400);
|
||||
|
||||
/* Normally, these pins get configured by boot sysmodule during initial pinmux config. */
|
||||
/* However, they're required to access the SD card. */
|
||||
{
|
||||
const uintptr_t apb_misc = dd::QueryIoMapping(0x70000000, 0x4000);
|
||||
|
||||
reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_CLK, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_DOWN),
|
||||
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_CLK_PM, SDMMC1));
|
||||
|
||||
reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_CMD, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
|
||||
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_CMD_PM, SDMMC1));
|
||||
|
||||
reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_DAT3, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
|
||||
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT3_PM, SDMMC1));
|
||||
|
||||
reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_DAT2, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
|
||||
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT2_PM, SDMMC1));
|
||||
|
||||
reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_DAT1, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
|
||||
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT1_PM, SDMMC1));
|
||||
|
||||
reg::ReadWrite(apb_misc + PINMUX_AUX_SDMMC1_DAT0, PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
|
||||
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT0_PM, SDMMC1));
|
||||
|
||||
reg::ReadWrite(apb_misc + PINMUX_AUX_DMIC3_CLK, PINMUX_REG_BITS_ENUM(AUX_E_OD, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_INPUT, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_SDMMC1_DAT0_PM, RSVD2));
|
||||
}
|
||||
|
||||
/* Debug signaler. */
|
||||
volatile u32 * const DEBUG = reinterpret_cast<volatile u32 *>(0x4003C000);
|
||||
DEBUG[0] = 0;
|
||||
DEBUG[1] = 0xAAAAAAAA;
|
||||
|
||||
/* Initialize sdmmc library. */
|
||||
sdmmc::Initialize(Port);
|
||||
DEBUG[0] = 1;
|
||||
|
||||
sdmmc::SetSdCardWorkBuffer(Port, g_sd_work_buffer, sizeof(g_sd_work_buffer));
|
||||
DEBUG[0] = 2;
|
||||
|
||||
Result result = sdmmc::Activate(Port);
|
||||
DEBUG[0] = 3;
|
||||
CheckResult(result);
|
||||
|
||||
/* Read the first two sectors from disk. */
|
||||
void * const sector_dst = reinterpret_cast<void *>(0x40038000);
|
||||
result = sdmmc::Read(sector_dst, SectorCount * sdmmc::SectorSize, Port, SectorIndex, SectorCount);
|
||||
DEBUG[0] = 4;
|
||||
CheckResult(result);
|
||||
|
||||
/* Get the connection status. */
|
||||
sdmmc::SpeedMode speed_mode;
|
||||
sdmmc::BusWidth bus_width;
|
||||
result = sdmmc::CheckSdCardConnection(std::addressof(speed_mode), std::addressof(bus_width), Port);
|
||||
|
||||
/* Save status for debug. */
|
||||
DEBUG[0] = 5;
|
||||
DEBUG[1] = result.GetValue();
|
||||
DEBUG[2] = static_cast<u32>(speed_mode);
|
||||
DEBUG[3] = static_cast<u32>(bus_width);
|
||||
|
||||
/* Perform a reboot. */
|
||||
PmcMainReboot();
|
||||
}
|
||||
|
||||
NORETURN void ExceptionHandler() {
|
||||
PmcMainReboot();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ams::diag {
|
||||
|
||||
void AbortImpl() {
|
||||
sdmmc_test::ExceptionHandler();
|
||||
}
|
||||
|
||||
}
|
||||
37
exosphere/sdmmc_test/source/sdmmc_test_start.s
Normal file
37
exosphere/sdmmc_test/source/sdmmc_test_start.s
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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 .crt0.text._ZN3ams10sdmmc_test5StartEv, "ax", %progbits
|
||||
.align 3
|
||||
.global _ZN3ams10sdmmc_test5StartEv
|
||||
_ZN3ams10sdmmc_test5StartEv:
|
||||
/* Switch to system mode, mask all interrupts, clear all flags */
|
||||
msr cpsr_cxsf, #0xDF
|
||||
|
||||
/* Set the stack pointer. */
|
||||
ldr sp, =__stack_top__
|
||||
|
||||
/* Set our link register to the exception handler. */
|
||||
ldr lr, =_ZN3ams10sdmmc_test16ExceptionHandlerEv
|
||||
|
||||
/* Call init array functions. */
|
||||
bl __libc_init_array
|
||||
|
||||
/* Invoke main. */
|
||||
b _ZN3ams10sdmmc_test4MainEv
|
||||
|
||||
/* Infinite loop. */
|
||||
2: b 2b
|
||||
@@ -30,7 +30,7 @@ _ZN3ams8warmboot5StartEv:
|
||||
|
||||
/* Invoke main. */
|
||||
ldr r0, =_metadata
|
||||
bl _ZN3ams8warmboot4MainEPKNS0_8MetadataE
|
||||
b _ZN3ams8warmboot4MainEPKNS0_8MetadataE
|
||||
|
||||
/* Infinite loop. */
|
||||
1: b 1b
|
||||
Reference in New Issue
Block a user