diff --git a/fusee_cpp/program/program.ld b/fusee_cpp/program/program.ld
index 6d97ae2e7..9f6d514b0 100644
--- a/fusee_cpp/program/program.ld
+++ b/fusee_cpp/program/program.ld
@@ -19,6 +19,10 @@ SECTIONS
.text :
{
+ KEEP(*(.text._ZN3ams4util15GetMicroSecondsEv))
+ KEEP(*(.text._ZN3ams4util16WaitMicroSecondsEi))
+ KEEP(*(.text._ZN3ams6nxboot14ShowFatalErrorEPKcz))
+ _*.o(SORT(.text*))
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
*(.text.exit .text.exit.*)
*(.text.startup .text.startup.*)
diff --git a/fusee_cpp/program/program_ovl.ld b/fusee_cpp/program/program_ovl.ld
index 9dfe1ce09..0f73539c8 100644
--- a/fusee_cpp/program/program_ovl.ld
+++ b/fusee_cpp/program/program_ovl.ld
@@ -23,7 +23,7 @@ SECTIONS {
BYTE(0x00);
}
.ovl_mtc_erista {
- KEEP(*(.text._ZN3ams6nxboot22DoMemoryTrainingEristaEv))
+ KEEP(*(.text._ZN3ams6nxboot22DoMemoryTrainingEristaEi))
fusee_mtc_erista.o(.text*);
fusee_mtc_erista.o(.rodata*);
fusee_mtc_erista.o(.data*);
@@ -33,7 +33,7 @@ SECTIONS {
BYTE(0x00);
}
.ovl_mtc_mariko {
- KEEP(*(.text._ZN3ams6nxboot22DoMemoryTrainingMarikoEv))
+ KEEP(*(.text._ZN3ams6nxboot22DoMemoryTrainingMarikoEi))
fusee_mtc_mariko.o(.text*);
fusee_mtc_mariko.o(.rodata*);
fusee_mtc_mariko.o(.data*);
diff --git a/fusee_cpp/program/source/fusee_setup_horizon.cpp b/fusee_cpp/program/source/fusee_setup_horizon.cpp
index c34a983a9..5437e5723 100644
--- a/fusee_cpp/program/source/fusee_setup_horizon.cpp
+++ b/fusee_cpp/program/source/fusee_setup_horizon.cpp
@@ -14,13 +14,40 @@
* along with this program. If not, see .
*/
#include
+#include "fusee_secondary_archive.hpp"
#include "fusee_setup_horizon.hpp"
#include "fusee_fatal.hpp"
namespace ams::nxboot {
+ namespace {
+
+ void DeriveAllKeys(const fuse::SocType soc_type) {
+ /* If on erista, run the TSEC keygen firmware. */
+ if (soc_type == fuse::SocType_Erista) {
+ clkrst::SetBpmpClockRate(clkrst::BpmpClockRate_408MHz);
+
+ if (!tsec::RunTsecFirmware(GetSecondaryArchive().tsec_keygen, sizeof(GetSecondaryArchive().tsec_keygen))) {
+ ShowFatalError("Failed to run tsec_keygen firmware!\n");
+ }
+
+ clkrst::SetBpmpClockRate(clkrst::BpmpClockRate_576MHz);
+ }
+
+ ShowFatalError("DeriveAllKeys not fully implemented\n");
+ }
+
+ }
+
void SetupAndStartHorizon() {
- /* TODO */
+ /* Get soc/hardware type. */
+ const auto soc_type = fuse::GetSocType();
+ const auto hw_type = fuse::GetHardwareType();
+
+ /* Derive all keys. */
+ DeriveAllKeys(soc_type);
+
+ AMS_UNUSED(hw_type);
ShowFatalError("SetupAndStartHorizon not fully implemented\n");
}
diff --git a/fusee_cpp/program/source/mtc/fusee_mtc.cpp b/fusee_cpp/program/source/mtc/fusee_mtc.cpp
index bbd7b148f..8d8596546 100644
--- a/fusee_cpp/program/source/mtc/fusee_mtc.cpp
+++ b/fusee_cpp/program/source/mtc/fusee_mtc.cpp
@@ -17,8 +17,8 @@
namespace ams::nxboot {
- void DoMemoryTrainingErista();
- void DoMemoryTrainingMariko();
+ void DoMemoryTrainingErista(int index);
+ void DoMemoryTrainingMariko(int index);
namespace {
@@ -56,21 +56,23 @@ namespace ams::nxboot {
/* DramId_MarikoAulaSamsung1y8gbX */ 0x0D,
};
+ int GetMemoryTrainingTableIndex() {
+ if (const auto dram_id = fuse::GetDramId(); dram_id < util::size(MemoryTrainingTableIndices) && MemoryTrainingTableIndices[dram_id] != MemoryTrainingTableIndex_Invalid) {
+ return static_cast(MemoryTrainingTableIndices[dram_id]);
+ } else {
+ return -1;
+ }
+ }
+
}
void DoMemoryTraining() {
- if (fuse::GetSocType() == fuse::SocType_Erista) {
- DoMemoryTrainingErista();
- } else {
- DoMemoryTrainingMariko();
- }
- }
+ const auto index = GetMemoryTrainingTableIndex();
- int GetMemoryTrainingTableIndex() {
- if (const auto dram_id = fuse::GetDramId(); dram_id < util::size(MemoryTrainingTableIndices) && MemoryTrainingTableIndices[dram_id] != MemoryTrainingTableIndex_Invalid) {
- return static_cast(MemoryTrainingTableIndices[dram_id]);
+ if (fuse::GetSocType() == fuse::SocType_Erista) {
+ DoMemoryTrainingErista(index);
} else {
- return -1;
+ DoMemoryTrainingMariko(index);
}
}
diff --git a/fusee_cpp/program/source/mtc/fusee_mtc.hpp b/fusee_cpp/program/source/mtc/fusee_mtc.hpp
index 4440cc330..2fc9e120c 100644
--- a/fusee_cpp/program/source/mtc/fusee_mtc.hpp
+++ b/fusee_cpp/program/source/mtc/fusee_mtc.hpp
@@ -20,6 +20,4 @@ namespace ams::nxboot {
void DoMemoryTraining();
- int GetMemoryTrainingTableIndex();
-
}
diff --git a/fusee_cpp/program/source/mtc/fusee_mtc_erista.cpp b/fusee_cpp/program/source/mtc/fusee_mtc_erista.cpp
index 2259db502..d723854b9 100644
--- a/fusee_cpp/program/source/mtc/fusee_mtc_erista.cpp
+++ b/fusee_cpp/program/source/mtc/fusee_mtc_erista.cpp
@@ -72,8 +72,7 @@ namespace ams::nxboot {
using EmcDvfsTimingTable = erista::EmcDvfsTimingTable;
- EmcDvfsTimingTable *GetEmcDvfsTimingTables() {
- const auto index = GetMemoryTrainingTableIndex();
+ EmcDvfsTimingTable *GetEmcDvfsTimingTables(int index) {
switch (index) {
case 0:
case 3:
@@ -2830,11 +2829,11 @@ namespace ams::nxboot {
}
- void DoMemoryTrainingErista() {
+ void DoMemoryTrainingErista(int index) {
/* Get timing tables. */
- auto *timing_tables = GetEmcDvfsTimingTables();
- auto *src_timing = timing_tables + 0;
- auto *dst_timing = timing_tables + 1;
+ auto *timing_tables = GetEmcDvfsTimingTables(index);
+ auto *src_timing = timing_tables + 0;
+ auto *dst_timing = timing_tables + 1;
/* Check timing tables. */
if (src_timing->rate_khz != 204000 || dst_timing->rate_khz != 1600000) {
diff --git a/fusee_cpp/program/source/mtc/fusee_mtc_mariko.cpp b/fusee_cpp/program/source/mtc/fusee_mtc_mariko.cpp
index e38bc1b31..8ce16623c 100644
--- a/fusee_cpp/program/source/mtc/fusee_mtc_mariko.cpp
+++ b/fusee_cpp/program/source/mtc/fusee_mtc_mariko.cpp
@@ -27,9 +27,7 @@ namespace ams::nxboot {
using EmcDvfsTimingTable = mariko::EmcDvfsTimingTable;
- EmcDvfsTimingTable *GetEmcDvfsTimingTables() {
- const auto index = GetMemoryTrainingTableIndex();
-
+ EmcDvfsTimingTable *GetEmcDvfsTimingTables(int index) {
/* Get the compressed table. */
u8 *cmp_table;
size_t cmp_table_size;
@@ -65,9 +63,9 @@ namespace ams::nxboot {
}
- void DoMemoryTrainingMariko() {
+ void DoMemoryTrainingMariko(int index) {
/* Get timing tables. */
- auto *timing_tables = GetEmcDvfsTimingTables();
+ auto *timing_tables = GetEmcDvfsTimingTables(index);
auto *src_timing_tables = timing_tables + 0;
auto *dst_timing_tables = timing_tables + 1;
diff --git a/libraries/libexosphere/arm.mk b/libraries/libexosphere/arm.mk
index 6a42c37c6..0414f3dea 100644
--- a/libraries/libexosphere/arm.mk
+++ b/libraries/libexosphere/arm.mk
@@ -149,7 +149,7 @@ $(OFILES) : $(GCH_FILES)
$(OFILES_SRC) : $(HFILES_BIN)
libc.o: CFLAGS += -fno-builtin -fno-lto
-libgcc_division.arch.arm.o: CFLAGS += -fno-builtin -fno-lto
+util_api.o: CXXFLAGS += -fno-lto
#---------------------------------------------------------------------------------
%_bin.h %.bin.o : %.bin
diff --git a/libraries/libexosphere/source/kfuse/kfuse_registers.hpp b/libraries/libexosphere/source/kfuse/kfuse_registers.hpp
new file mode 100644
index 000000000..4e6f1c6f3
--- /dev/null
+++ b/libraries/libexosphere/source/kfuse/kfuse_registers.hpp
@@ -0,0 +1,32 @@
+/*
+ * 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 LicenKFUSE,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be uKFUSEful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOKFUSE. KFUSEe the GNU General Public LicenKFUSE for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public LicenKFUSE
+ * along with this program. If not, KFUSEe .
+ */
+#include
+
+#define KFUSE_STATE (0x080)
+
+#define KFUSE_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (KFUSE, NAME)
+#define KFUSE_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (KFUSE, NAME, VALUE)
+#define KFUSE_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (KFUSE, NAME, ENUM)
+#define KFUSE_REG_BITS_ENUM_KFUSEL(NAME, __COND__, TRUE_ENUM, FALKFUSE_ENUM) REG_NAMED_BITS_ENUM_KFUSEL(KFUSE, NAME, __COND__, TRUE_ENUM, FALKFUSE_ENUM)
+
+#define DEFINE_KFUSE_REG(NAME, __OFFKFUSET__, __WIDTH__) REG_DEFINE_NAMED_REG (KFUSE, NAME, __OFFKFUSET__, __WIDTH__)
+#define DEFINE_KFUSE_REG_BIT_ENUM(NAME, __OFFKFUSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (KFUSE, NAME, __OFFKFUSET__, ZERO, ONE)
+#define DEFINE_KFUSE_REG_TWO_BIT_ENUM(NAME, __OFFKFUSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (KFUSE, NAME, __OFFKFUSET__, ZERO, ONE, TWO, THREE)
+#define DEFINE_KFUSE_REG_THREE_BIT_ENUM(NAME, __OFFKFUSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, KFUSEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(KFUSE, NAME, __OFFKFUSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, KFUSEVEN)
+#define DEFINE_KFUSE_REG_FOUR_BIT_ENUM(NAME, __OFFKFUSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, KFUSEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (KFUSE, NAME, __OFFKFUSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, KFUSEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
+
+DEFINE_KFUSE_REG_BIT_ENUM(STATE_DONE, 16, NOT_DONE, DONE);
+DEFINE_KFUSE_REG_BIT_ENUM(STATE_CRCPASS, 17, FAIL, PASS);
diff --git a/libraries/libexosphere/source/tsec/tsec_api.cpp b/libraries/libexosphere/source/tsec/tsec_api.cpp
index a251b91f2..56f6a7087 100644
--- a/libraries/libexosphere/source/tsec/tsec_api.cpp
+++ b/libraries/libexosphere/source/tsec/tsec_api.cpp
@@ -14,46 +14,154 @@
* along with this program. If not, see .
*/
#include
+#include "tsec_registers.hpp"
+#include "../kfuse/kfuse_registers.hpp"
namespace ams::tsec {
namespace {
- enum TsecResult {
+ constexpr inline const uintptr_t KFUSE = 0x7000FC00;
+ constexpr inline const uintptr_t TSEC = 0x54500000;
+
+ enum TsecResult : u32 {
TsecResult_Success = 0xB0B0B0B0,
TsecResult_Failure = 0xD0D0D0D0,
};
- bool RunFirmwareImpl(const void *fw, size_t fw_size) {
- /* Enable relevant clocks. */
- clkrst::EnableHost1xClock();
- clkrst::EnableTsecClock();
- clkrst::EnableSorSafeClock();
- clkrst::EnableSor0Clock();
- clkrst::EnableSor1Clock();
- clkrst::EnableKfuseClock();
+ enum TsecMemory {
+ TsecMemory_Imem,
+ TsecMemory_Dmem,
+ };
- /* Disable clocks once we're done. */
- ON_SCOPE_EXIT {
- clkrst::DisableHost1xClock();
- clkrst::DisableTsecClock();
- clkrst::DisableSorSafeClock();
- clkrst::DisableSor0Clock();
- clkrst::DisableSor1Clock();
- clkrst::DisableKfuseClock();
- };
+ bool WaitForKfuseReady() {
+ constexpr auto KfuseTimeout = 10 * 1000; /* 10 ms. */
- /* TODO */
- AMS_UNUSED(fw, fw_size);
- return true;
+ const u32 end_time = util::GetMicroSeconds() + KfuseTimeout;
+
+ /* Wait for STATE_DONE. */
+ while (!reg::HasValue(KFUSE + KFUSE_STATE, KFUSE_REG_BITS_ENUM(STATE_DONE, DONE))) {
+ if (util::GetMicroSeconds() >= end_time) {
+ return false;
+ }
+ }
+
+ /* Check for STATE_CRCPASS. */
+ return reg::HasValue(KFUSE + KFUSE_STATE, KFUSE_REG_BITS_ENUM(STATE_CRCPASS, PASS));
+ }
+
+ void WaitForDmaIdle() {
+ constexpr auto DmaTimeout = 10 * 1000 * 1000; /* 10 Seconds. */
+
+ u32 cur_time = util::GetMicroSeconds();
+ const u32 end_time = cur_time + DmaTimeout;
+
+ while (cur_time <= end_time) {
+ if (reg::HasValue(TSEC + TSEC_FALCON_DMATRFCMD, TSEC_REG_BITS_ENUM(FALCON_DMATRFCMD_BUSY, IDLE))) {
+ return;
+ }
+
+ cur_time = util::GetMicroSeconds();
+ }
+
+ AMS_ABORT("tsec dma timeout");
+ }
+
+ void WaitForTsecIdle() {
+ constexpr auto TsecTimeout = 2 * 1000 * 1000; /* 2 Seconds. */
+
+ u32 cur_time = util::GetMicroSeconds();
+ const u32 end_time = cur_time + TsecTimeout;
+
+ while (cur_time <= end_time) {
+ if (reg::HasValue(TSEC + TSEC_FALCON_CPUCTL, TSEC_REG_BITS_ENUM(FALCON_CPUCTL_HALTED, TRUE))) {
+ return;
+ }
+
+ cur_time = util::GetMicroSeconds();
+ }
+
+ AMS_ABORT("tsec timeout");
+ }
+
+ void DoDma256(TsecMemory memory, u32 dst_offset, u32 src_offset) {
+ reg::Write(TSEC + TSEC_FALCON_DMATRFMOFFS, TSEC_REG_BITS_VALUE(FALCON_DMATRFMOFFS_OFFSET, dst_offset));
+ reg::Write(TSEC + TSEC_FALCON_DMATRFFBOFFS, src_offset);
+
+ if (memory == TsecMemory_Imem) {
+ reg::Write(TSEC + TSEC_FALCON_DMATRFCMD, TSEC_REG_BITS_ENUM(FALCON_DMATRFCMD_TO, IMEM),
+ TSEC_REG_BITS_ENUM(FALCON_DMATRFCMD_SIZE, 4B));
+ } else {
+ reg::Write(TSEC + TSEC_FALCON_DMATRFCMD, TSEC_REG_BITS_ENUM(FALCON_DMATRFCMD_TO, DMEM),
+ TSEC_REG_BITS_ENUM(FALCON_DMATRFCMD_SIZE, 256B));
+ }
+
+ WaitForDmaIdle();
}
}
bool RunTsecFirmware(const void *fw, size_t fw_size) {
- /* TODO */
- AMS_UNUSED(fw, fw_size);
- return RunFirmwareImpl(fw, fw_size);
+ /* Enable relevant clocks. */
+ clkrst::EnableHost1xClock();
+ clkrst::EnableTsecClock();
+ clkrst::EnableSorSafeClock();
+ clkrst::EnableSor0Clock();
+ clkrst::EnableSor1Clock();
+ clkrst::EnableKfuseClock();
+
+ /* Disable clocks once we're done. */
+ ON_SCOPE_EXIT {
+ clkrst::DisableHost1xClock();
+ clkrst::DisableTsecClock();
+ clkrst::DisableSorSafeClock();
+ clkrst::DisableSor0Clock();
+ clkrst::DisableSor1Clock();
+ clkrst::DisableKfuseClock();
+ };
+
+ /* Wait for kfuse to be ready. */
+ if (!WaitForKfuseReady()) {
+ return false;
+ }
+
+ /* Configure falcon. */
+ reg::Write(TSEC + TSEC_FALCON_DMACTL, 0);
+ reg::Write(TSEC + TSEC_FALCON_IRQMSET, 0xFFF2);
+ reg::Write(TSEC + TSEC_FALCON_IRQDEST, 0xFFF0);
+ reg::Write(TSEC + TSEC_FALCON_ITFEN, 0x3);
+
+ /* Wait for TSEC dma to be idle. */
+ WaitForDmaIdle();
+
+ /* Set the base address for transfers. */
+ reg::Write(TSEC + TSEC_FALCON_DMATRFBASE, reinterpret_cast(fw) >> 8);
+
+ /* Transfer all data to TSEC imem. */
+ for (size_t i = 0; i < fw_size; i += 0x100) {
+ DoDma256(TsecMemory_Imem, i, i);
+ }
+
+ /* Write the magic value to host1x syncpoint 160. */
+ reg::Write(0x50003300, 0x34C2E1DA);
+
+ /* Execute the firmware. */
+ reg::Write(TSEC + TSEC_FALCON_MAILBOX0, 0);
+ reg::Write(TSEC + TSEC_FALCON_MAILBOX1, 0);
+ reg::Write(TSEC + TSEC_FALCON_BOOTVEC, 0);
+ reg::Write(TSEC + TSEC_FALCON_CPUCTL, TSEC_REG_BITS_ENUM(FALCON_CPUCTL_STARTCPU, TRUE));
+
+ /* Wait for TSEC dma to be idle. */
+ WaitForDmaIdle();
+
+ /* Wait for TSEC to complete. */
+ WaitForTsecIdle();
+
+ /* Clear magic value from host1x syncpoint 160. */
+ reg::Write(0x50003300, 0);
+
+ /* Return whether the tsec firmware succeeded. */
+ return reg::Read(TSEC + TSEC_FALCON_MAILBOX1) == TsecResult_Success;
}
void Lock() {
diff --git a/libraries/libexosphere/source/tsec/tsec_registers.hpp b/libraries/libexosphere/source/tsec/tsec_registers.hpp
new file mode 100644
index 000000000..fb8e758aa
--- /dev/null
+++ b/libraries/libexosphere/source/tsec/tsec_registers.hpp
@@ -0,0 +1,49 @@
+/*
+ * 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 LicenTSEC,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be uTSECful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOTSEC. TSECe the GNU General Public LicenTSEC for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public LicenTSEC
+ * along with this program. If not, TSECe .
+ */
+#include
+
+#define TSEC_FALCON_IRQMSET (0x1010)
+#define TSEC_FALCON_IRQDEST (0x101C)
+#define TSEC_FALCON_MAILBOX0 (0x1040)
+#define TSEC_FALCON_MAILBOX1 (0x1044)
+#define TSEC_FALCON_ITFEN (0x1048)
+#define TSEC_FALCON_CPUCTL (0x1100)
+#define TSEC_FALCON_BOOTVEC (0x1104)
+#define TSEC_FALCON_DMACTL (0x110C)
+#define TSEC_FALCON_DMATRFBASE (0x1110)
+#define TSEC_FALCON_DMATRFMOFFS (0x1114)
+#define TSEC_FALCON_DMATRFCMD (0x1118)
+#define TSEC_FALCON_DMATRFFBOFFS (0x111C)
+
+#define TSEC_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (TSEC, NAME)
+#define TSEC_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (TSEC, NAME, VALUE)
+#define TSEC_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (TSEC, NAME, ENUM)
+#define TSEC_REG_BITS_ENUM_TSECL(NAME, __COND__, TRUE_ENUM, FALTSEC_ENUM) REG_NAMED_BITS_ENUM_TSECL(TSEC, NAME, __COND__, TRUE_ENUM, FALTSEC_ENUM)
+
+#define DEFINE_TSEC_REG(NAME, __OFFTSECT__, __WIDTH__) REG_DEFINE_NAMED_REG (TSEC, NAME, __OFFTSECT__, __WIDTH__)
+#define DEFINE_TSEC_REG_BIT_ENUM(NAME, __OFFTSECT__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (TSEC, NAME, __OFFTSECT__, ZERO, ONE)
+#define DEFINE_TSEC_REG_TWO_BIT_ENUM(NAME, __OFFTSECT__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (TSEC, NAME, __OFFTSECT__, ZERO, ONE, TWO, THREE)
+#define DEFINE_TSEC_REG_THREE_BIT_ENUM(NAME, __OFFTSECT__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, TSECVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(TSEC, NAME, __OFFTSECT__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, TSECVEN)
+#define DEFINE_TSEC_REG_FOUR_BIT_ENUM(NAME, __OFFTSECT__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, TSECVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (TSEC, NAME, __OFFTSECT__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, TSECVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
+
+DEFINE_TSEC_REG_BIT_ENUM(FALCON_CPUCTL_STARTCPU, 1, FALSE, TRUE);
+DEFINE_TSEC_REG_BIT_ENUM(FALCON_CPUCTL_HALTED, 4, FALSE, TRUE);
+
+DEFINE_TSEC_REG(FALCON_DMATRFMOFFS_OFFSET, 0, 16);
+
+DEFINE_TSEC_REG_BIT_ENUM(FALCON_DMATRFCMD_BUSY, 1, BUSY, IDLE);
+DEFINE_TSEC_REG_BIT_ENUM(FALCON_DMATRFCMD_TO, 4, DMEM, IMEM);
+DEFINE_TSEC_REG_THREE_BIT_ENUM(FALCON_DMATRFCMD_SIZE, 8, 4B, 8B, 16B, 32B, 64B, 128B, 256B, RSVD7);
\ No newline at end of file