ams: replace sept with tsec firmware (#1594)

* ams: replace sept with tsec firmware

This replaces sept with a custom tsec key derivation firmware.

NOTE: This does not use any TSEC exploits whatsoever; it is a well-signed
TSEC binary assembled with envyas and signed with the real cauth key.

For more details, contact SciresM#0524.

* fusee: only set SBK if it's readable
This commit is contained in:
SciresM 2021-08-20 13:13:29 -07:00 committed by GitHub
parent f175802136
commit 17ca463c3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
137 changed files with 149 additions and 28364 deletions

View File

@ -32,10 +32,7 @@ mesosphere: exosphere libraries
troposphere: stratosphere
$(MAKE) -C troposphere all
sept: exosphere
$(MAKE) -C sept all
fusee: exosphere mesosphere stratosphere sept
fusee: exosphere mesosphere stratosphere
$(MAKE) -C $@ all
libraries:
@ -61,7 +58,6 @@ dist-no-debug: all
rm -rf out
mkdir atmosphere-$(AMSVER)
mkdir atmosphere-$(AMSVER)/atmosphere
mkdir atmosphere-$(AMSVER)/sept
mkdir atmosphere-$(AMSVER)/switch
mkdir -p atmosphere-$(AMSVER)/atmosphere/fatal_errors
mkdir -p atmosphere-$(AMSVER)/atmosphere/config_templates
@ -71,13 +67,6 @@ dist-no-debug: all
cp fusee/fusee-primary/fusee-primary.bin atmosphere-$(AMSVER)/atmosphere/reboot_payload.bin
cp fusee/fusee-mtc/fusee-mtc.bin atmosphere-$(AMSVER)/atmosphere/fusee-mtc.bin
cp fusee/fusee-secondary/fusee-secondary-experimental.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin
cp fusee/fusee-secondary/fusee-secondary-experimental.bin atmosphere-$(AMSVER)/sept/payload.bin
cp sept/sept-primary/sept-primary.bin atmosphere-$(AMSVER)/sept/sept-primary.bin
cp sept/sept-secondary/sept-secondary.bin atmosphere-$(AMSVER)/sept/sept-secondary.bin
cp sept/sept-secondary/sept-secondary_00.enc atmosphere-$(AMSVER)/sept/sept-secondary_00.enc
cp sept/sept-secondary/sept-secondary_01.enc atmosphere-$(AMSVER)/sept/sept-secondary_01.enc
cp sept/sept-secondary/sept-secondary_dev_00.enc atmosphere-$(AMSVER)/sept/sept-secondary_dev_00.enc
cp sept/sept-secondary/sept-secondary_dev_01.enc atmosphere-$(AMSVER)/sept/sept-secondary_dev_01.enc
cp config_templates/BCT.ini atmosphere-$(AMSVER)/atmosphere/config_templates/BCT.ini
cp config_templates/override_config.ini atmosphere-$(AMSVER)/atmosphere/config_templates/override_config.ini
cp config_templates/system_settings.ini atmosphere-$(AMSVER)/atmosphere/config_templates/system_settings.ini
@ -109,7 +98,6 @@ dist-no-debug: all
cp troposphere/daybreak/daybreak.nro atmosphere-$(AMSVER)/switch/daybreak.nro
cd atmosphere-$(AMSVER); zip -r ../atmosphere-$(AMSVER).zip ./*; cd ../;
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/sept/payload.bin
cd atmosphere-$(AMSVER); zip -r ../atmosphere-$(AMSVER)-WITHOUT_MESOSPHERE.zip ./*; cd ../;
rm -r atmosphere-$(AMSVER)
mkdir out
@ -133,9 +121,6 @@ dist: dist-no-debug
cp fusee/fusee-primary/fusee-primary.elf atmosphere-$(AMSVER)-debug/fusee-primary.elf
cp fusee/fusee-mtc/fusee-mtc.elf atmosphere-$(AMSVER)-debug/fusee-mtc.elf
cp fusee/fusee-secondary/fusee-secondary-experimental.elf atmosphere-$(AMSVER)-debug/fusee-secondary.elf
cp sept/sept-primary/sept-primary.elf atmosphere-$(AMSVER)-debug/sept-primary.elf
cp sept/sept-secondary/sept-secondary.elf atmosphere-$(AMSVER)-debug/sept-secondary.elf
cp sept/sept-secondary/key_derivation/key_derivation.elf atmosphere-$(AMSVER)-debug/sept-secondary-key-derivation.elf
cp exosphere/loader_stub/loader_stub.elf atmosphere-$(AMSVER)-debug/exosphere-loader-stub.elf
cp exosphere/program/program.elf atmosphere-$(AMSVER)-debug/exosphere-program.elf
cp exosphere/warmboot/warmboot.elf atmosphere-$(AMSVER)-debug/exosphere-warmboot.elf

View File

@ -20,13 +20,13 @@
namespace ams::secmon::loader {
NORETURN void UncompressAndExecute() {
NORETURN void UncompressAndExecute(const void *program, const void *boot_code) {
/* Uncompress the program image. */
Uncompress(secmon::MemoryRegionPhysicalTzramFullProgramImage.GetPointer(), secmon::MemoryRegionPhysicalTzramFullProgramImage.GetSize(), program_lz4, program_lz4_size);
Uncompress(secmon::MemoryRegionPhysicalTzramFullProgramImage.GetPointer(), secmon::MemoryRegionPhysicalTzramFullProgramImage.GetSize(), program, program_lz4_size);
/* Copy the boot image to the end of IRAM */
u8 *relocated_boot_code = secmon::MemoryRegionPhysicalIramBootCodeImage.GetEndPointer<u8>() - boot_code_lz4_size;
std::memcpy(relocated_boot_code, boot_code_lz4, boot_code_lz4_size);
std::memcpy(relocated_boot_code, boot_code, boot_code_lz4_size);
/* Uncompress the boot image. */
Uncompress(secmon::MemoryRegionPhysicalIramBootCodeImage.GetPointer(), secmon::MemoryRegionPhysicalIramBootCodeImage.GetSize(), relocated_boot_code, boot_code_lz4_size);

View File

@ -98,8 +98,8 @@ _start:
ldr x20, =0x7C020000
mov sp, x20
/* Call our init array functions. */
bl __libc_init_array
adr x0, program_lz4
adr x1, boot_code_lz4
/* Uncompress the program and iram boot code images. */
b _ZN3ams6secmon6loader20UncompressAndExecuteEv
b _ZN3ams6secmon6loader20UncompressAndExecuteEPKvS3_

View File

@ -17,8 +17,6 @@
#include "../../../fusee/fusee-primary/fusee-primary-main/src/fs_utils.h"
#elif defined(FUSEE_STAGE2_SRC)
#include "../../../fusee/fusee-secondary/src/device_partition.h"
#elif defined(SEPT_STAGE2_SRC)
#include "../../../sept/sept-secondary/src/fs_utils.h"
#endif
#ifdef FUSEE_STAGE2_SRC

View File

@ -30,8 +30,6 @@
#include "../../../fusee/fusee-primary/fusee-primary-main/src/timers.h"
#elif defined(FUSEE_STAGE2_SRC)
#include "../../../fusee/fusee-secondary/src/timers.h"
#elif defined(SEPT_STAGE2_SRC)
#include "../../../sept/sept-secondary/src/timers.h"
#endif
#define UNSTUFF_BITS(resp,start,size) \

View File

@ -41,15 +41,6 @@
#include "../../../fusee/fusee-secondary/src/gpio.h"
#include "../../../fusee/fusee-secondary/src/pmc.h"
#include "../../../fusee/fusee-secondary/src/max7762x.h"
#elif defined(SEPT_STAGE2_SRC)
#include "../../../sept/sept-secondary/src/car.h"
#include "../../../sept/sept-secondary/src/fuse.h"
#include "../../../sept/sept-secondary/src/pinmux.h"
#include "../../../sept/sept-secondary/src/timers.h"
#include "../../../sept/sept-secondary/src/apb_misc.h"
#include "../../../sept/sept-secondary/src/gpio.h"
#include "../../../sept/sept-secondary/src/pmc.h"
#include "../../../sept/sept-secondary/src/max7762x.h"
#endif
#include "../log.h"

View File

@ -158,7 +158,12 @@ static void config_se_brom(void) {
/* Bootrom part we skipped. */
uint32_t sbk[4] = {fuse_chip->FUSE_PRIVATE_KEY[0], fuse_chip->FUSE_PRIVATE_KEY[1], fuse_chip->FUSE_PRIVATE_KEY[2], fuse_chip->FUSE_PRIVATE_KEY[3]};
set_aes_keyslot(0xE, sbk, 0x10);
for (int i = 0; i < 4; ++i) {
if (sbk[i] != 0xFFFFFFFF) {
set_aes_keyslot(0xE, sbk, 0x10);
break;
}
}
/* Lock SBK from being read. */
se->SE_CRYPTO_KEYTABLE_ACCESS[0xE] = 0x7E;
@ -247,7 +252,7 @@ void nx_hwinit(bool enable_log) {
} else {
uint8_t val = 0x40;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CNFGBBC, &val, 1);
val = 0x60;
val = 0x58;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, &val, 1);
val = 0x38;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_CFG0, &val, 1);

View File

@ -92,8 +92,8 @@ export KIPDIRS := $(AMS)/stratosphere/loader $(AMS)/stratosphere/ncm $(AMS)/stra
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
$(AMS)/exosphere $(AMS)/exosphere/warmboot $(AMS)/exosphere/program/rebootstub \
$(AMS)/thermosphere $(AMS)/fusee/fusee-primary $(AMS)/sept/sept-primary \
$(AMS)/sept/sept-secondary $(AMS)/emummc $(AMS)/mesosphere $(AMS)/mesosphere/kernel_ldr $(KIPDIRS)
$(AMS)/thermosphere $(AMS)/fusee/fusee-primary $(AMS)/emummc $(AMS)/mesosphere \
$(KIPDIRS)
export DEPSDIR := $(CURDIR)/$(BUILD)
@ -103,9 +103,7 @@ SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
KIPFILES := loader.kip ncm.kip pm.kip sm.kip ams_mitm.kip spl.kip boot.kip
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) fusee-primary.bin \
exosphere.bin warmboot.bin rebootstub.bin thermosphere.bin splash_screen.bin \
sept-primary.bin sept-secondary_00.enc sept-secondary_01.enc emummc.kip \
sept-secondary_dev_00.enc sept-secondary_dev_01.enc mesosphere.bin kernel_ldr.bin \
mariko_fatal.bin $(KIPFILES)
emummc.kip mesosphere.bin mariko_fatal.bin $(KIPFILES)
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
@ -133,7 +131,7 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
.PHONY: $(BUILD) clean all
.PHONY: check_fusee_primary check_exosphere check_sept check_emummc check_thermosphere check_stratosphere check_libraries
.PHONY: check_fusee_primary check_exosphere check_emummc check_thermosphere check_stratosphere check_libraries
#---------------------------------------------------------------------------------
all: $(BUILD)
@ -144,9 +142,6 @@ check_fusee_primary:
check_exosphere:
@$(MAKE) -C $(AMS)/exosphere all
check_sept:
@$(MAKE) -C $(AMS)/sept all
check_emummc:
@$(MAKE) -C $(AMS)/emummc EMUMMCDIR=$(AMS)/emummc all
@ -163,7 +158,7 @@ check_libraries:
@$(MAKE) -C $(AMS)/libraries all
$(BUILD): check_fusee_primary check_exosphere check_sept check_emummc check_thermosphere check_libraries check_stratosphere check_mesosphere
$(BUILD): check_fusee_primary check_exosphere check_emummc check_thermosphere check_libraries check_stratosphere check_mesosphere
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
@ -176,7 +171,6 @@ clean:
@$(MAKE) -C $(AMS)/libraries clean
@$(MAKE) -C $(AMS)/mesosphere clean
@$(MAKE) -C $(AMS)/stratosphere clean
@$(MAKE) -C $(AMS)/sept clean
@$(MAKE) -C $(AMS)/emummc clean
@rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf
@ -216,31 +210,6 @@ fusee_primary.bin.o fusee_primary_bin.h: fusee-primary.bin
@echo $(notdir $<)
@$(_bin2o)
sept_primary.bin.o sept_primary_bin.h: sept-primary.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(_bin2o)
sept_secondary_00.enc.o sept_secondary_00_enc.h: sept-secondary_00.enc
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(_bin2o)
sept_secondary_01.enc.o sept_secondary_01_enc.h: sept-secondary_01.enc
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(_bin2o)
sept_secondary_dev_00.enc.o sept_secondary_dev_00_enc.h: sept-secondary_dev_00.enc
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(_bin2o)
sept_secondary_dev_01.enc.o sept_secondary_dev_01_enc.h: sept-secondary_dev_01.enc
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(_bin2o)
%.bin.o %_bin.h: %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)

Binary file not shown.

View File

@ -244,12 +244,6 @@ SECTIONS
PROVIDE(__pm_kip_size__ = pm_kip_end - pm_kip);
PROVIDE(__rebootstub_bin_start__ = rebootstub_bin - __start__);
PROVIDE(__rebootstub_bin_size__ = rebootstub_bin_end - rebootstub_bin);
PROVIDE(__sept_primary_bin_start__ = sept_primary_bin - __start__);
PROVIDE(__sept_primary_bin_size__ = sept_primary_bin_end - sept_primary_bin);
PROVIDE(__sept_secondary_00_enc_start__ = sept_secondary_00_enc - __start__);
PROVIDE(__sept_secondary_00_enc_size__ = sept_secondary_00_enc_end - sept_secondary_00_enc);
PROVIDE(__sept_secondary_01_enc_start__ = sept_secondary_01_enc - __start__);
PROVIDE(__sept_secondary_01_enc_size__ = sept_secondary_01_enc_end - sept_secondary_01_enc);
PROVIDE(__sm_kip_start__ = sm_kip - __start__);
PROVIDE(__sm_kip_size__ = sm_kip_end - sm_kip);
PROVIDE(__spl_kip_start__ = spl_kip - __start__);
@ -266,4 +260,6 @@ SECTIONS
PROVIDE(__mesosphere_bin_size__ = mesosphere_bin_end - mesosphere_bin);
PROVIDE(__mariko_fatal_bin_start__ = mariko_fatal_bin - __start__);
PROVIDE(__mariko_fatal_bin_size__ = mariko_fatal_bin_end - mariko_fatal_bin);
PROVIDE(__tsec_keygen_bin_start__ = tsec_keygen_bin - __start__);
PROVIDE(__tsec_keygen_bin_size__ = tsec_keygen_bin_end - tsec_keygen_bin);
}

View File

@ -51,7 +51,7 @@ typedef enum {
CARDEVICE_USB2 = ((1 << 5) | 0x1A),
CARDEVICE_CORESIGHT = ((2 << 5) | 0x9),
CARDEVICE_TSEC = ((2 << 5) | 0x13),
CARDEVICE_MSELECT = ((3 << 5) | 0x8),
CARDEVICE_MSELECT = ((3 << 5) | 0x3),
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
CARDEVICE_SE = ((3 << 5) | 0x1F),

View File

@ -21,12 +21,6 @@
#include "kernel_patches.h"
#include "ips.h"
#define u8 uint8_t
#define u32 uint32_t
#include "kernel_ldr_bin.h"
#undef u8
#undef u32
#define MAKE_BRANCH(a, o) 0x14000000 | ((((o) - (a)) >> 2) & 0x3FFFFFF)
#define MAKE_NOP 0xD503201F

View File

@ -26,19 +26,6 @@
#define AL16 ALIGN(16)
static const uint8_t AL16 keyblob_seeds[MASTERKEY_REVISION_MAX][0x10] = {
{0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3}, /* Keyblob seed 00. */
{0x0C, 0x25, 0x61, 0x5D, 0x68, 0x4C, 0xEB, 0x42, 0x1C, 0x23, 0x79, 0xEA, 0x82, 0x25, 0x12, 0xAC}, /* Keyblob seed 01. */
{0x33, 0x76, 0x85, 0xEE, 0x88, 0x4A, 0xAE, 0x0A, 0xC2, 0x8A, 0xFD, 0x7D, 0x63, 0xC0, 0x43, 0x3B}, /* Keyblob seed 02. */
{0x2D, 0x1F, 0x48, 0x80, 0xED, 0xEC, 0xED, 0x3E, 0x3C, 0xF2, 0x48, 0xB5, 0x65, 0x7D, 0xF7, 0xBE}, /* Keyblob seed 03. */
{0xBB, 0x5A, 0x01, 0xF9, 0x88, 0xAF, 0xF5, 0xFC, 0x6C, 0xFF, 0x07, 0x9E, 0x13, 0x3C, 0x39, 0x80}, /* Keyblob seed 04. */
{0xD8, 0xCC, 0xE1, 0x26, 0x6A, 0x35, 0x3F, 0xCC, 0x20, 0xF3, 0x2D, 0x3B, 0x51, 0x7D, 0xE9, 0xC0} /* Keyblob seed 05. */
};
static const uint8_t AL16 keyblob_mac_seed[0x10] = {
0x59, 0xC7, 0xFB, 0x6F, 0xBE, 0x9B, 0xBE, 0x87, 0x65, 0x6B, 0x15, 0xC0, 0x53, 0x73, 0x36, 0xA5
};
static const uint8_t AL16 masterkey_seed[0x10] = {
0xD8, 0xA2, 0x41, 0x0A, 0xC6, 0xC5, 0x90, 0x01, 0xC6, 0x1D, 0x6A, 0x26, 0x7C, 0x51, 0x3F, 0x3C
};
@ -55,164 +42,51 @@ static const uint8_t AL16 masterkey_4x_seed[0x10] = {
0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66
};
/* TODO: Bother adding 8.1.0 here? We'll never call into here... */
static const uint8_t AL16 new_master_kek_seeds[MASTERKEY_REVISION_700_800 - MASTERKEY_REVISION_600_610][0x10] = {
{0x37, 0x4B, 0x77, 0x29, 0x59, 0xB4, 0x04, 0x30, 0x81, 0xF6, 0xE5, 0x8C, 0x6D, 0x36, 0x17, 0x9A}, /* MasterKek seed 06. */
{0x9A, 0x3E, 0xA9, 0xAB, 0xFD, 0x56, 0x46, 0x1C, 0x9B, 0xF6, 0x48, 0x7F, 0x5C, 0xFA, 0x09, 0x5C}, /* MasterKek seed 07. */
static const uint8_t AL16 keyblob_seed_00[0x10] = {
0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3
};
static const uint8_t AL16 master_kek_seed_erista[0x10] = { /* TODO: Update on next change of keys. */
0x84, 0x67, 0xB6, 0x7F, 0x13, 0x11, 0xAE, 0xE6, 0x58, 0x9B, 0x19, 0xAF, 0x13, 0x6C, 0x80, 0x7A /* Erista MasterKek seed 0B. */
};
static const uint8_t AL16 master_devkey_seed_erista[0x10] = {
0xAA, 0xFD, 0xBC, 0xBB, 0x25, 0xC3, 0xA4, 0xEF, 0xE3, 0xEE, 0x58, 0x53, 0xB7, 0xF8, 0xDD, 0xD6
};
static const uint8_t AL16 master_kek_seed_mariko[0x10] = { /* TODO: Update on next change of keys. */
0xE5, 0x41, 0xAC, 0xEC, 0xD1, 0xA7, 0xD1, 0xAB, 0xED, 0x03, 0x77, 0xF1, 0x27, 0xCA, 0xF8, 0xF1, /* Mariko MasterKek seed 0B. */
};
static nx_dec_keyblob_t AL16 g_dec_keyblobs[32];
static int get_keyblob(nx_keyblob_t *dst, uint32_t revision, const nx_keyblob_t *keyblobs, uint32_t available_revision) {
if (revision >= 0x20) {
return -1;
/* TODO: what should we do? */
}
if (keyblobs != NULL) {
*dst = keyblobs[revision];
} else {
return -1;
/* TODO: what should we do? */
}
return 0;
}
static bool safe_memcmp(uint8_t *a, uint8_t *b, size_t sz) {
uint8_t different = 0;
for (unsigned int i = 0; i < sz; i++) {
different |= a[i] ^ b[i];
}
return different != 0;
}
static int decrypt_keyblob(const nx_keyblob_t *keyblobs, uint32_t revision, uint32_t available_revision) {
nx_keyblob_t AL16 keyblob;
uint8_t AL16 work_buffer[0x10];
unsigned int keyslot = revision == MASTERKEY_REVISION_100_230 ? 0xF : KEYSLOT_SWITCH_TEMPKEY;
if (get_keyblob(&keyblob, revision, keyblobs, available_revision) != 0) {
return -1;
}
se_aes_ecb_decrypt_block(0xD, work_buffer, 0x10, keyblob_seeds[revision], 0x10);
decrypt_data_into_keyslot(keyslot, 0xE, work_buffer, 0x10);
decrypt_data_into_keyslot(0xB, keyslot, keyblob_mac_seed, 0x10);
/* Validate keyblob. */
se_compute_aes_128_cmac(0xB, work_buffer, 0x10, keyblob.mac + sizeof(keyblob.mac), sizeof(keyblob) - sizeof(keyblob.mac));
if (safe_memcmp(keyblob.mac, work_buffer, 0x10)) {
return -1;
}
/* Decrypt keyblob. */
se_aes_ctr_crypt(keyslot, &g_dec_keyblobs[revision], sizeof(g_dec_keyblobs[revision]), keyblob.data, sizeof(keyblob.data), keyblob.ctr, sizeof(keyblob.ctr));
return 0;
}
int load_package1_key(uint32_t revision) {
if (revision > MASTERKEY_REVISION_600_610) {
return -1;
}
set_aes_keyslot(0xB, g_dec_keyblobs[revision].package1_key, 0x10);
return 0;
}
/* Derive all Switch keys. */
int derive_nx_keydata_erista(uint32_t target_firmware, const nx_keyblob_t *keyblobs, uint32_t available_revision, const void *tsec_key, void *tsec_root_keys, unsigned int *out_keygen_type) {
int derive_nx_keydata_erista(uint32_t target_firmware) {
uint8_t AL16 work_buffer[0x10];
uint8_t AL16 zeroes[0x10] = {0};
/* Initialize keygen type. */
*out_keygen_type = 0;
/* Get whether we're using dev keys. */
const bool is_retail = fuse_get_hardware_state() != 0;
/* TODO: Set keyslot flags properly in preparation of derivation. */
set_aes_keyslot_flags(0xE, 0x15);
set_aes_keyslot_flags(0xD, 0x15);
/* Derive Keyblob Key 00. */
se_aes_ecb_decrypt_block(0xC, work_buffer, 0x10, keyblob_seed_00, 0x10);
decrypt_data_into_keyslot(0xF, 0xE, work_buffer, 0x10);
/* Set the TSEC key. */
set_aes_keyslot(0xD, tsec_key, 0x10);
/* Derive master kek. */
decrypt_data_into_keyslot(0xE, is_retail ? 0xD : 0xB, master_kek_seed_erista, 0x10);
/* Decrypt all keyblobs, setting keyslot 0xF correctly. */
for (unsigned int rev = 0; rev <= MASTERKEY_REVISION_600_610; rev++) {
int ret = decrypt_keyblob(keyblobs, rev, available_revision);
if (ret) {
return ret;
}
}
/* Derive master key, device master key. */
decrypt_data_into_keyslot(0xD, 0xE, masterkey_seed, 0x10);
decrypt_data_into_keyslot(0xE, 0xE, masterkey_4x_seed, 0x10);
/* Do 6.2.0+ keygen. */
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_6_2_0) {
uint32_t desired_keyblob;
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_8_1_0) {
/* NOTE: We load in the current key for all >= 8.1.0 firmwares to reduce sept binaries. */
desired_keyblob = MASTERKEY_REVISION_C10_CURRENT;
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) {
desired_keyblob = MASTERKEY_REVISION_700_800;
} else {
desired_keyblob = MASTERKEY_REVISION_620;
}
/* Try emulation result. */
for (unsigned int rev = MASTERKEY_REVISION_620; rev < MASTERKEY_REVISION_MAX; rev++) {
void *tsec_root_key = (void *)((uintptr_t)tsec_root_keys + 0x10 * (rev - MASTERKEY_REVISION_620));
if (memcmp(tsec_root_key, zeroes, 0x10) != 0) {
/* We got a valid key from emulation. */
set_aes_keyslot(0xD, tsec_root_key, 0x10);
se_aes_ecb_decrypt_block(0xD, work_buffer, 0x10, new_master_kek_seeds[rev - MASTERKEY_REVISION_620], 0x10);
memcpy(g_dec_keyblobs[rev].master_kek, work_buffer, 0x10);
}
}
if (memcmp(g_dec_keyblobs[desired_keyblob].master_kek, zeroes, 0x10) == 0) {
/* Try reading the keys from a file. */
const char *keyfile = fuse_get_hardware_state() != 0 ? "atmosphere/prod.keys" : "atmosphere/dev.keys";
FILE *extkey_file = fopen(keyfile, "r");
AL16 fusee_extkeys_t extkeys = {0};
if (extkey_file == NULL) {
fatal_error("Error: failed to read %s, needed for 6.2.0+ key derivation!", keyfile);
}
extkeys_initialize_keyset(&extkeys, extkey_file);
fclose(extkey_file);
for (unsigned int rev = MASTERKEY_REVISION_620; rev < MASTERKEY_REVISION_MAX; rev++) {
if (memcmp(extkeys.tsec_root_keys[rev - MASTERKEY_REVISION_620], zeroes, 0x10) != 0) {
set_aes_keyslot(0xD, extkeys.tsec_root_keys[rev - MASTERKEY_REVISION_620], 0x10);
se_aes_ecb_decrypt_block(0xD, work_buffer, 0x10, new_master_kek_seeds[rev - MASTERKEY_REVISION_620], 0x10);
memcpy(g_dec_keyblobs[rev].master_kek, work_buffer, 0x10);
} else {
memcpy(g_dec_keyblobs[rev].master_kek, extkeys.master_keks[rev], 0x10);
}
}
}
if (memcmp(g_dec_keyblobs[available_revision].master_kek, zeroes, 0x10) == 0) {
fatal_error("Error: failed to derive master_kek_%02x!", available_revision);
}
}
/* Clear the SBK. */
clear_aes_keyslot(0xE);
/* Get needed data. */
set_aes_keyslot(0xD, g_dec_keyblobs[available_revision].master_kek, 0x10);
/* Also set the Package1 key for the revision that is stored on the eMMC boot0 partition. */
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_6_2_0) {
load_package1_key(available_revision);
}
/* Derive keys for Exosphere, lock critical keyslots. */
/* Derive device keys. */
decrypt_data_into_keyslot(0xA, 0xF, devicekey_4x_seed, 0x10);
decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10);
decrypt_data_into_keyslot(0xC, 0xD, masterkey_4x_seed, 0x10);
decrypt_data_into_keyslot(0xD, 0xD, masterkey_seed, 0x10);
decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10);
/* Derive firmware specific device key. */
se_aes_ecb_decrypt_block(0xA, work_buffer, 0x10, master_devkey_seed_erista, 0x10);
decrypt_data_into_keyslot(0xC, 0xE, work_buffer, 0x10);
/* Clear keyslots 0xB/0xE. */
clear_aes_keyslot(0xB);
clear_aes_keyslot(0xE);
/* Setup master key revision, derive older master keys for use. */
return mkey_detect_revision(fuse_get_hardware_state() != 0);

View File

@ -27,29 +27,8 @@ typedef enum BisPartition {
BisPartition_UserSystem = 2,
} BisPartition;
typedef struct {
union {
uint8_t keys[9][0x10];
struct {
uint8_t master_kek[0x10];
uint8_t _keys[7][0x10];
uint8_t package1_key[0x10];
};
};
} nx_dec_keyblob_t;
typedef struct nx_keyblob_t {
uint8_t mac[0x10];
uint8_t ctr[0x10];
union {
uint8_t data[0x90];
nx_dec_keyblob_t dec_blob;
};
} nx_keyblob_t;
int derive_nx_keydata_erista(uint32_t target_firmware, const nx_keyblob_t *keyblobs, uint32_t available_revision, const void *tsec_key, void *tsec_root_key, unsigned int *out_keygen_type);
int derive_nx_keydata_erista(uint32_t target_firmware);
int derive_nx_keydata_mariko(uint32_t target_firmware);
int load_package1_key(uint32_t revision);
void derive_bis_key(void *dst, BisPartition partition_id, uint32_t target_firmware);
#endif

View File

@ -185,8 +185,8 @@ void derive_new_device_keys(bool is_retail, unsigned int keygen_keyslot, unsigne
if (relative_revision > mkey_get_revision()) {
break;
} else if (relative_revision == mkey_get_revision()) {
/* On 7.0.0 erista, sept will have derived this key for us already. */
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_7_0_0 || is_mariko) {
/* On Erista, this will already be derived. */
if (is_mariko) {
decrypt_data_into_keyslot(is_mariko ? KEYSLOT_SWITCH_DEVICEKEY_MARIKO : KEYSLOT_SWITCH_DEVICEKEY, KEYSLOT_SWITCH_TEMPKEY, work_buffer, 0x10);
}
} else {

View File

@ -44,7 +44,6 @@
#include "masterkey.h"
#include "package1.h"
#include "package2.h"
#include "smmu.h"
#include "tsec.h"
#include "lp0.h"
#include "loader.h"
@ -59,11 +58,8 @@
#include "exosphere_bin.h"
#include "mariko_fatal_bin.h"
#include "mesosphere_bin.h"
#include "sept_secondary_00_enc.h"
#include "sept_secondary_01_enc.h"
#include "sept_secondary_dev_00_enc.h"
#include "sept_secondary_dev_01_enc.h"
#include "warmboot_bin.h"
#include "tsec_keygen_bin.h"
#include "emummc_kip.h"
#undef u8
#undef u32
@ -724,18 +720,11 @@ static void nxboot_move_bootconfig() {
free(bootconfig);
}
static bool get_and_clear_has_run_sept(void) {
bool has_run_sept = (MAKE_EMC_REG(EMC_SCRATCH0) & 0x80000000) != 0;
MAKE_EMC_REG(EMC_SCRATCH0) &= ~0x80000000;
return has_run_sept;
}
static void get_mariko_warmboot_path(char *dst, size_t dst_size, uint32_t version) {
snprintf(dst, dst_size, "warmboot_mariko/wb_%02" PRIx32 ".bin", version);
}
/* This is the main function responsible for booting Horizon. */
static nx_keyblob_t __attribute__((aligned(16))) g_keyblobs[32];
uint32_t nxboot_main(void) {
volatile tegra_pmc_t *pmc = pmc_get_regs();
loader_ctx_t *loader_ctx = get_loader_ctx();
@ -745,8 +734,6 @@ uint32_t nxboot_main(void) {
size_t package2_size;
void *tsec_fw;
size_t tsec_fw_size;
const void *sept_secondary_enc = NULL;
size_t sept_secondary_enc_size = 0;
void *warmboot_fw;
size_t warmboot_fw_size;
void *warmboot_memaddr;
@ -756,7 +743,6 @@ uint32_t nxboot_main(void) {
size_t mesosphere_size;
void *emummc;
size_t emummc_size;
uint32_t available_revision;
FILE *boot0, *pk2file;
void *exosphere_memaddr;
exo_emummc_config_t exo_emummc_cfg;
@ -844,7 +830,7 @@ uint32_t nxboot_main(void) {
fatal_error("[NXBOOT] Couldn't parse boot0: %s!\n", strerror(errno));
}
} else {
if (package1_read_and_parse_boot0_erista(&package1loader, &package1loader_size, g_keyblobs, &available_revision, boot0) == -1) {
if (package1_read_and_parse_boot0_erista(&package1loader, &package1loader_size, boot0) == -1) {
fatal_error("[NXBOOT] Couldn't parse boot0: %s!\n", strerror(errno));
}
}
@ -860,103 +846,26 @@ uint32_t nxboot_main(void) {
}
/* Handle TSEC and Sept (Erista only). */
uint8_t tsec_key[0x10] = {0};
uint8_t tsec_root_keys[0x20][0x10] = {0};
if (!is_mariko) {
/* Read the TSEC firmware from a file, otherwise from PK1L. */
if (loader_ctx->tsecfw_path[0] != '\0') {
tsec_fw_size = get_file_size(loader_ctx->tsecfw_path);
if ((tsec_fw_size != 0) && (tsec_fw_size != 0xF00 && tsec_fw_size != 0x2900 && tsec_fw_size != 0x3000 && tsec_fw_size != 0x3300)) {
fatal_error("[NXBOOT] TSEC firmware from %s has a wrong size!\n", loader_ctx->tsecfw_path);
} else if (tsec_fw_size == 0) {
fatal_error("[NXBOOT] Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path);
}
/* Use Atmosphere's tsec_keygen implementation. */
tsec_fw_size = tsec_keygen_bin_size;
tsec_fw = memalign(0x100, tsec_fw_size);
/* Allocate memory for the TSEC firmware. */
tsec_fw = memalign(0x100, tsec_fw_size);
if (tsec_fw == NULL) {
fatal_error("[NXBOOT] Out of memory!\n");
}
if (read_from_file(tsec_fw, tsec_fw_size, loader_ctx->tsecfw_path) != tsec_fw_size) {
fatal_error("[NXBOOT] Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path);
}
if (tsec_fw_size == 0x3000) {
if (fuse_get_hardware_state() != 0) {
sept_secondary_enc = sept_secondary_00_enc;
sept_secondary_enc_size = sept_secondary_00_enc_size;
} else {
sept_secondary_enc = sept_secondary_dev_00_enc;
sept_secondary_enc_size = sept_secondary_dev_00_enc_size;
}
} else if (tsec_fw_size == 0x3300) {
if (fuse_get_hardware_state() != 0) {
sept_secondary_enc = sept_secondary_01_enc;
sept_secondary_enc_size = sept_secondary_01_enc_size;
} else {
sept_secondary_enc = sept_secondary_dev_01_enc;
sept_secondary_enc_size = sept_secondary_dev_01_enc_size;
}
} else {
fatal_error("[NXBOOT] Unable to identify sept revision to run.");
}
} else {
if (!package1_get_tsec_fw(&tsec_fw, package1loader, package1loader_size)) {
fatal_error("[NXBOOT] Failed to read the TSEC firmware from Package1loader!\n");
}
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_8_1_0) {
if (fuse_get_hardware_state() != 0) {
sept_secondary_enc = sept_secondary_01_enc;
sept_secondary_enc_size = sept_secondary_01_enc_size;
} else {
sept_secondary_enc = sept_secondary_dev_01_enc;
sept_secondary_enc_size = sept_secondary_dev_01_enc_size;
}
tsec_fw_size = 0x3300;
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) {
if (fuse_get_hardware_state() != 0) {
sept_secondary_enc = sept_secondary_00_enc;
sept_secondary_enc_size = sept_secondary_00_enc_size;
} else {
sept_secondary_enc = sept_secondary_dev_00_enc;
sept_secondary_enc_size = sept_secondary_dev_00_enc_size;
}
tsec_fw_size = 0x3000;
} else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_6_2_0) {
tsec_fw_size = 0x2900;
} else {
tsec_fw_size = 0xF00;
}
if (tsec_fw == NULL) {
fatal_error("[NXBOOT] Out of memory!\n");
}
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Loaded firmware from eMMC...\n");
memcpy(tsec_fw, tsec_keygen_bin, tsec_fw_size);
/* Get the TSEC keys. */
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) {
/* Detect whether we need to run sept-secondary in order to derive keys. */
if (!get_and_clear_has_run_sept()) {
reboot_to_sept(tsec_fw, tsec_fw_size, sept_secondary_enc, sept_secondary_enc_size);
} else {
if (mkey_detect_revision(fuse_get_hardware_state() != 0) != 0) {
fatal_error("[NXBOOT] Sept derived incorrect keys!\n");
}
}
get_and_clear_has_run_sept();
} else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_6_2_0) {
uint8_t tsec_keys[0x20] = {0};
if (tsec_fw_size == 0) {
fatal_error("[NXBOOT] Could not read the warmboot firmware from Package1!\n");
}
/* Emulate the TSEC payload on 6.2.0+. */
smmu_emulate_tsec((void *)tsec_keys, package1loader, package1loader_size, package1loader);
/* Copy back the keys. */
memcpy((void *)tsec_key, (void *)tsec_keys, 0x10);
memcpy((void *)tsec_root_keys, (void *)tsec_keys + 0x10, 0x10);
} else {
/* Run the TSEC payload and get the key. */
if (tsec_get_key(tsec_key, 1, tsec_fw, tsec_fw_size) != 0) {
fatal_error("[NXBOOT] Failed to get TSEC key!\n");
}
/* Get the TSEC keys into the security engine. */
int tsec_res = tsec_run_fw(tsec_fw, tsec_fw_size);
if (tsec_res != 0) {
volatile tegra_tsec_t *tsec = tsec_get_regs();
fatal_error("[NXBOOT] Failed to run TSEC firmware %d %08x %08x!\n", tsec_res, tsec->TSEC_FALCON_MAILBOX0, tsec->TSEC_FALCON_MAILBOX1);
}
}
@ -969,8 +878,8 @@ uint32_t nxboot_main(void) {
if (derive_nx_keydata_mariko(target_firmware) != 0) {
fatal_error("[NXBOOT] Mariko key derivation failed!\n");
}
} else if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_7_0_0) { /* If on 7.0.0+, sept has already derived keys for us (Erista only). */
if (derive_nx_keydata_erista(target_firmware, g_keyblobs, available_revision, tsec_key, tsec_root_keys, &keygen_type) != 0) {
} else {
if (derive_nx_keydata_erista(target_firmware) != 0) {
fatal_error("[NXBOOT] Erista key derivation failed!\n");
}
}
@ -1230,9 +1139,6 @@ uint32_t nxboot_main(void) {
/* Clean up. */
free(package1loader);
if (loader_ctx->tsecfw_path[0] != '\0') {
free(tsec_fw);
}
if (loader_ctx->warmboot_path[0] != '\0') {
free(warmboot_fw);
}

View File

@ -24,18 +24,10 @@
#include "mc.h"
#include "nxboot.h"
#include "se.h"
#include "smmu.h"
#include "timers.h"
#include "sysreg.h"
/* Determine the current SoC for Mariko specific code. */
static bool is_soc_mariko() {
return (fuse_get_soc_type() == 1);
}
void nxboot_finish(uint32_t boot_memaddr) {
bool is_mariko = is_soc_mariko();
/* Boot up Exosphère. */
MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 0;
MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X;
@ -43,26 +35,8 @@ void nxboot_finish(uint32_t boot_memaddr) {
/* Terminate the display. */
display_end();
if (is_mariko) {
/* Boot CPU0. */
cluster_boot_cpu0(boot_memaddr);
} else {
/* Check if SMMU emulation has been used. */
uint32_t smmu_magic = *(uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0xFC);
if (smmu_magic == 0xDEADC0DE) {
/* Clear the magic. */
*(uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0xFC) = 0;
/* Pass the boot address to the already running payload. */
*(uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0xF0) = boot_memaddr;
/* Wait a while. */
mdelay(500);
} else {
/* Boot CPU0. */
cluster_boot_cpu0(boot_memaddr);
}
}
/* Boot CPU0. */
cluster_boot_cpu0(boot_memaddr);
/* Wait for Exosphère to wake up. */
while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE == 0) {

View File

@ -58,16 +58,12 @@ bool package1_is_custom_public_key(const void *bct, bool mariko) {
}
}
int package1_read_and_parse_boot0_erista(void **package1loader, size_t *package1loader_size, nx_keyblob_t *keyblobs, uint32_t *revision, FILE *boot0) {
int package1_read_and_parse_boot0_erista(void **package1loader, size_t *package1loader_size, FILE *boot0) {
nvboot_config_table *bct; /* Normal firmware BCT, primary. TODO: check? */
nv_bootloader_info *pk1l_info; /* TODO: check? */
size_t fpos, pk1l_offset;
union {
nx_keyblob_t keyblob;
uint8_t sector[0x200];
} d;
if (package1loader == NULL || package1loader_size == NULL || keyblobs == NULL || revision == NULL || boot0 == NULL) {
if (package1loader == NULL || package1loader_size == NULL || boot0 == NULL) {
errno = EINVAL;
return -1;
}
@ -105,7 +101,6 @@ int package1_read_and_parse_boot0_erista(void **package1loader, size_t *package1
return -1;
}
*revision = pk1l_info->version - 1;
*package1loader_size = pk1l_info->length;
pk1l_offset = 0x4000 * pk1l_info->start_blk + 0x200 * pk1l_info->start_page;
@ -128,14 +123,6 @@ int package1_read_and_parse_boot0_erista(void **package1loader, size_t *package1
return -1;
}
/* Read the full keyblob area.*/
for (size_t i = 0; i < 32; i++) {
if (!fread(d.sector, 0x200, 1, boot0)) {
return -1;
}
keyblobs[i] = d.keyblob;
}
return 0;
}
@ -211,24 +198,6 @@ bool package1_get_tsec_fw(void **tsec_fw, const void *package1loader, size_t pac
return false;
}
size_t package1_get_encrypted_package1(package1_header_t **package1, uint8_t *ctr, const void *package1loader, size_t package1loader_size) {
const uint8_t *crypt_hdr = (const uint8_t *)package1loader + 0x4000 - 0x20;
if (package1loader_size < 0x4000) {
return 0; /* Shouldn't happen, ever. */
}
memcpy(ctr, crypt_hdr + 0x10, 0x10);
(*package1) = (package1_header_t *)(crypt_hdr + 0x20);
return *(uint32_t *)crypt_hdr;
}
bool package1_decrypt(package1_header_t *package1, size_t package1_size, const uint8_t *ctr) {
uint8_t __attribute__((aligned(16))) ctrbuf[16];
memcpy(ctrbuf, ctr, 16);
se_aes_ctr_crypt(0xB, package1, package1_size, package1, package1_size, ctrbuf, 16);
return memcmp(package1->magic, "PK11", 4) == 0;
}
void *package1_get_warmboot_fw(const package1_header_t *package1) {
/*
The layout of pk1 changes between versions.

View File

@ -59,14 +59,10 @@ typedef struct {
bool package1_is_custom_public_key(const void *bct, bool mariko);
int package1_read_and_parse_boot0_erista(void **package1loader, size_t *package1loader_size, nx_keyblob_t *keyblobs, uint32_t *revision, FILE *boot0);
int package1_read_and_parse_boot0_erista(void **package1loader, size_t *package1loader_size, FILE *boot0);
int package1_read_and_parse_boot0_mariko(void **package1loader, size_t *package1loader_size, FILE *boot0);
bool package1_get_tsec_fw(void **tsec_fw, const void *package1loader, size_t package1loader_size);
size_t package1_get_encrypted_package1(package1_header_t **package1, uint8_t *ctr, const void *package1loader, size_t package1loader_size);
/* Must be aligned to 16 bytes. */
bool package1_decrypt(package1_header_t *package1, size_t package1_size, const uint8_t *ctr);
void *package1_get_warmboot_fw(const package1_header_t *package1);
#endif

View File

@ -1,284 +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 "smmu.h"
#include "cluster.h"
#include "mc.h"
#include "timers.h"
#include "tsec.h"
#define TSEC_KEYGEN_MAX_RETRIES 25
void *smmu_heap = (void *)SMMU_HEAP_BASE_ADDR;
static void safe_memcpy(void *dst, void *src, uint32_t sz) {
/* Aligned memcpy to read MMIO correctly. */
for (size_t i = 0; i < (sz/4); i++) {
((volatile uint32_t *)dst)[i] = ((volatile uint32_t *)src)[i];
}
}
static void smmu_flush_ppsb() {
/* Read-back barrier for interactions between the PPSB and the APB/AHB. */
(void)MAKE_MC_REG(MC_SMMU_TLB_CONFIG);
}
static void smmu_flush_regs() {
/* Flush all TLB and PTC entries. */
MAKE_MC_REG(MC_SMMU_PTC_FLUSH) = 0;
smmu_flush_ppsb();
MAKE_MC_REG(MC_SMMU_TLB_FLUSH) = 0;
smmu_flush_ppsb();
}
static void *smmu_alloc_page(uint32_t page_count) {
void *cur_page = smmu_heap;
smmu_heap += (page_count * SMMU_PAGE_SIZE);
memset(cur_page, 0, (page_count * SMMU_PAGE_SIZE));
return cur_page;
}
static uint32_t *smmu_alloc_pdir() {
uint32_t *pdir = (uint32_t *)smmu_alloc_page(1);
for (int pdn = 0; pdn < SMMU_PDIR_COUNT; pdn++) {
pdir[pdn] = _PDE_VACANT(pdn);
}
return pdir;
}
static uint32_t *smmu_locate_pte(uint32_t *pdir_page, uint32_t iova) {
uint32_t ptn = SMMU_ADDR_TO_PFN(iova);
uint32_t pdn = SMMU_ADDR_TO_PDN(iova);
uint32_t *pdir = pdir_page;
uint32_t *ptbl;
if (pdir[pdn] != _PDE_VACANT(pdn)) {
/* Mapped entry table already exists. */
ptbl = (uint32_t *)SMMU_EX_PTBL_PAGE(pdir[pdn]);
} else {
/* Allocate page table. */
ptbl = (uint32_t *)smmu_alloc_page(1);
uint32_t addr = SMMU_PDN_TO_ADDR(pdn);
for (int pn = 0; pn < SMMU_PTBL_COUNT; pn++, addr += SMMU_PAGE_SIZE) {
ptbl[pn] = _PTE_VACANT(addr);
}
pdir[pdn] = SMMU_MK_PDE((uint32_t)ptbl, _PDE_ATTR | _PDE_NEXT);
smmu_flush_regs();
}
return &ptbl[ptn % SMMU_PTBL_COUNT];
}
static void smmu_map(uint32_t *pdir, uint32_t addr, uint32_t ptpage, int pcount, uint32_t pte_attr) {
for (int i = 0; i < pcount; i++) {
uint32_t *pte = smmu_locate_pte(pdir, addr);
*pte = SMMU_PFN_TO_PTE(SMMU_ADDR_TO_PFN(ptpage), pte_attr);
addr += SMMU_PAGE_SIZE;
ptpage += SMMU_PAGE_SIZE;
}
smmu_flush_regs();
}
static uint32_t *smmu_setup_tsec_as(uint32_t asid) {
/* Allocate the page directory. */
uint32_t *pdir_page = smmu_alloc_pdir();
/* Set the PTB ASID and point it to the PDIR. */
MAKE_MC_REG(MC_SMMU_PTB_ASID) = asid;
MAKE_MC_REG(MC_SMMU_PTB_DATA) = SMMU_MK_PDIR((uint32_t)pdir_page, _PDIR_ATTR);
smmu_flush_ppsb();
/* Assign the ASID to TSEC. */
MAKE_MC_REG(MC_SMMU_TSEC_ASID) = SMMU_ASID_ENABLE((asid << 24) | (asid << 16) | (asid << 8) | asid);
smmu_flush_ppsb();
return pdir_page;
}
static void smmu_clear_tsec_as(uint32_t asid) {
/* Set the PTB ASID and clear it's data. */
MAKE_MC_REG(MC_SMMU_PTB_ASID) = asid;
MAKE_MC_REG(MC_SMMU_PTB_DATA) = 0;
/* Clear the ASID from TSEC. */
MAKE_MC_REG(MC_SMMU_TSEC_ASID) = SMMU_ASID_DISABLE;
smmu_flush_ppsb();
}
static void smmu_enable() {
/* AARCH64 payload for enabling the SMMU. */
/* Write 1 to MC_SMMU_CONFIG, read back and write the result to 0x40003F80. */
/* This will leave the CPU waiting until 0x40003FF0 is set to Exosphère's address. */
static const uint32_t aarch64_payload[20] = {
0x52800020, 0x58000162, 0x58000183, 0xB9000040,
0xB9400041, 0xB9000061, 0x58000142, 0xF9400040,
0xF100001F, 0x54FFFFA0, 0xD61F0000, 0x00000000,
0x70019010, 0x00000000, 0x40003F80, 0x00000000,
0x40003FF0, 0x00000000, 0x00000000, 0x00000000
};
/* Reset Translation Enable Registers. */
MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_0) = 0xFFFFFFFF;
MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_1) = 0xFFFFFFFF;
MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_2) = 0xFFFFFFFF;
MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_3) = 0xFFFFFFFF;
MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_4) = 0xFFFFFFFF;
/* Setup initial TLB and PTC configuration. */
MAKE_MC_REG(MC_SMMU_PTB_ASID) = 0;
MAKE_MC_REG(MC_SMMU_PTB_DATA) = 0;
MAKE_MC_REG(MC_SMMU_TLB_CONFIG) = 0x30000030;
MAKE_MC_REG(MC_SMMU_PTC_CONFIG) = 0x2800003F;
smmu_flush_regs();
/* Power on the CCPLEX to enable the SMMU globally (requires a secure write). */
volatile uint32_t *aarch64_payload_res = (volatile uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0x80);
memset((void *)SMMU_AARCH64_PAYLOAD_ADDR, 0, 0x100);
memcpy((void *)SMMU_AARCH64_PAYLOAD_ADDR, aarch64_payload, 20 * 4);
cluster_boot_cpu0(SMMU_AARCH64_PAYLOAD_ADDR);
mdelay(500);
if (*aarch64_payload_res != 1) {
fatal_error("[SMMU]: Failed to enable SMMU!\n");
}
/* Write magic for nxboot. */
*(uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0xFC) = 0xDEADC0DE;
/* Flush TLB and PTC entries. */
smmu_flush_regs();
}
void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_size, void *package1_dec) {
volatile tegra_tsec_t *tsec = tsec_get_regs();
/* Backup IRAM to DRAM. */
memcpy((void *)SMMU_IRAM_BACKUP_ADDR, (void *)0x40010000, 0x30000);
/* Copy package1 into IRAM. */
memcpy((void *)0x40010000, package1, package1_size);
/* Setup TSEC's address space. */
uint32_t *pdir = smmu_setup_tsec_as(1);
/* Allocate pages for MMIO and IRAM. */
volatile uint32_t *car_page = smmu_alloc_page(1);
volatile uint32_t *fuse_page = smmu_alloc_page(1);
volatile uint32_t *pmc_page = smmu_alloc_page(1);
volatile uint32_t *flow_page = smmu_alloc_page(1);
volatile uint32_t *se_page = smmu_alloc_page(1);
volatile uint32_t *mc_page = smmu_alloc_page(1);
volatile uint32_t *iram_pages = smmu_alloc_page(48);
volatile uint32_t *expv_page = smmu_alloc_page(1);
/* Map all necessary pages. */
smmu_map(pdir, 0x60006000, (uint32_t)car_page, 1, _READABLE | _WRITABLE | _NONSECURE);
smmu_map(pdir, 0x7000F000, (uint32_t)fuse_page, 1, _READABLE | _NONSECURE);
smmu_map(pdir, 0x7000E000, (uint32_t)pmc_page, 1, _READABLE | _NONSECURE);
smmu_map(pdir, 0x60007000, (uint32_t)flow_page, 1, _WRITABLE | _NONSECURE);
smmu_map(pdir, 0x70012000, (uint32_t)se_page, 1, _READABLE | _WRITABLE | _NONSECURE);
smmu_map(pdir, 0x70019000, (uint32_t)mc_page, 1, _READABLE | _NONSECURE);
smmu_map(pdir, 0x40010000, (uint32_t)iram_pages, 48, _READABLE | _WRITABLE | _NONSECURE);
smmu_map(pdir, 0x6000F000, (uint32_t)expv_page, 1, _READABLE | _WRITABLE | _NONSECURE);
/* Enable the SMMU. */
smmu_enable();
/* Loop retrying TSEC firmware execution, in case we lose the SE keydata race. */
uint32_t key_buf[0x20/4] = {0};
unsigned int retries = 0;
while (true) {
if (retries++ > TSEC_KEYGEN_MAX_RETRIES) {
fatal_error("[SMMU] TSEC key generation race was lost too many times!");
}
/* Load the TSEC firmware from IRAM. */
if (tsec_load_fw((void *)(0x40010000 + 0xE00), 0x2900) < 0) {
fatal_error("[SMMU]: Failed to load TSEC firmware!\n");
}
/* Disable the aperture since it has precedence over the SMMU. */
mc_disable_ahb_redirect();
/* Clear all pages. */
memset((void *)car_page, 0, SMMU_PAGE_SIZE);
memset((void *)fuse_page, 0, SMMU_PAGE_SIZE);
memset((void *)pmc_page, 0, SMMU_PAGE_SIZE);
memset((void *)flow_page, 0, SMMU_PAGE_SIZE);
memset((void *)se_page, 0, SMMU_PAGE_SIZE);
memset((void *)mc_page, 0, SMMU_PAGE_SIZE);
memset((void *)iram_pages, 0, 48 * SMMU_PAGE_SIZE);
memset((void *)expv_page, 0, SMMU_PAGE_SIZE);
/* Copy CAR, MC and FUSE. */
safe_memcpy((void *)car_page, (void *)0x60006000, 0x1000);
safe_memcpy((void *)mc_page, (void *)0x70019000, 0x1000);
safe_memcpy((void *)&fuse_page[0x800/4], (void *)0x7000F800, 0x400);
/* Copy IRAM. */
memcpy((void *)iram_pages, (void *)0x40010000, 0x30000);
/* TSEC wants CLK_RST_CONTROLLER_CLK_SOURCE_TSEC_0 to be equal to 2. */
car_page[0x1F4/4] = 2;
/* TSEC wants the aperture fully open. */
mc_page[0x65C/4] = 0;
mc_page[0x660/4] = 0x80000000;
/* Run the TSEC firmware. */
tsec_run_fw();
/* Extract the keys from SE. */
volatile uint32_t *key_data = (volatile uint32_t *)((void *)se_page + 0x320);
uint32_t old_key_data = *key_data;
uint32_t buf_counter = 0;
while (!(tsec->TSEC_FALCON_CPUCTL & 0x10)) {
const uint32_t new_key_data = *key_data;
if (new_key_data != old_key_data) {
old_key_data = new_key_data;
key_buf[buf_counter] = new_key_data;
buf_counter++;
}
}
/* Enable back the aperture. */
mc_enable_ahb_redirect();
if (buf_counter == 8) {
break;
}
}
/* Check if the TSEC firmware wrote over the exception vectors. */
volatile uint32_t *tsec_done_check = (volatile uint32_t *)((void *)expv_page + 0x200);
if (!(*tsec_done_check)) {
fatal_error("[SMMU]: Failed to emulate the TSEC firmware!\n");
}
/* Copy back the extracted keys. */
memcpy((void *)tsec_keys, (void *)key_buf, 0x20);
/* Manually disable TSEC clocks. */
tsec_disable_clkrst();
/* Clear TSEC's address space. */
smmu_clear_tsec_as(1);
/* Return the decrypted package1 from emulated IRAM. */
memcpy(package1_dec, (void *)iram_pages, package1_size);
/* Restore IRAM from DRAM. */
memcpy((void *)0x40010000, (void *)SMMU_IRAM_BACKUP_ADDR, 0x30000);
}

View File

@ -1,63 +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/>.
*/
#ifndef FUSEE_SMMU_H_
#define FUSEE_SMMU_H_
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#define SMMU_HEAP_BASE_ADDR 0x81000000
#define SMMU_IRAM_BACKUP_ADDR 0x82000000
#define SMMU_AARCH64_PAYLOAD_ADDR 0x40003F00
#define SMMU_PAGE_SHIFT 12
#define SMMU_PAGE_SIZE (1 << SMMU_PAGE_SHIFT)
#define SMMU_PDIR_COUNT 1024
#define SMMU_PDIR_SIZE (sizeof(uint32_t) * SMMU_PDIR_COUNT)
#define SMMU_PTBL_COUNT 1024
#define SMMU_PTBL_SIZE (sizeof(uint32_t) * SMMU_PTBL_COUNT)
#define SMMU_PDIR_SHIFT 12
#define SMMU_PDE_SHIFT 12
#define SMMU_PTE_SHIFT 12
#define SMMU_PFN_MASK 0x000fffff
#define SMMU_PDE_NEXT_SHIFT 28
#define SMMU_ADDR_TO_PFN(addr) ((addr) >> 12)
#define SMMU_ADDR_TO_PDN(addr) ((addr) >> 22)
#define SMMU_PDN_TO_ADDR(pdn) ((pdn) << 22)
#define _READABLE (1 << 31)
#define _WRITABLE (1 << 30)
#define _NONSECURE (1 << 29)
#define _PDE_NEXT (1 << SMMU_PDE_NEXT_SHIFT)
#define _MASK_ATTR (_READABLE | _WRITABLE | _NONSECURE)
#define _PDIR_ATTR (_READABLE | _WRITABLE | _NONSECURE)
#define _PDE_ATTR (_READABLE | _WRITABLE | _NONSECURE)
#define _PDE_ATTR_N (_PDE_ATTR | _PDE_NEXT)
#define _PDE_VACANT(pdn) (((pdn) << 10) | _PDE_ATTR)
#define _PTE_ATTR (_READABLE | _WRITABLE | _NONSECURE)
#define _PTE_VACANT(addr) (((addr) >> SMMU_PAGE_SHIFT) | _PTE_ATTR)
#define SMMU_MK_PDIR(page, attr) (((page) >> SMMU_PDIR_SHIFT) | (attr))
#define SMMU_MK_PDE(page, attr) (((page) >> SMMU_PDE_SHIFT) | (attr))
#define SMMU_EX_PTBL_PAGE(pde) (((pde) & SMMU_PFN_MASK) << SMMU_PDIR_SHIFT)
#define SMMU_PFN_TO_PTE(pfn, attr) ((pfn) | (attr))
#define SMMU_ASID_ENABLE(asid) ((asid) | (1 << 31))
#define SMMU_ASID_DISABLE 0
#define SMMU_ASID_ASID(n) ((n) & ~SMMU_ASID_ENABLE(0))
void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_size, void *package1_dec);
#endif

View File

@ -108,6 +108,7 @@ _metadata:
#define CONTENT_TYPE_KLD 9
#define CONTENT_TYPE_KRN 10
#define CONTENT_TYPE_EXF 11
#define CONTENT_TYPE_TKG 12
#define CONTENT_FLAG_NONE (0 << 0)
@ -213,39 +214,6 @@ _content_headers:
.asciz "rebootstub"
.align 5
/* sept_primary content header */
.word __sept_primary_bin_start__
.word __sept_primary_bin_size__
.byte CONTENT_TYPE_SP1
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "sept_primary"
.align 5
/* sept_secondary 00 content header */
.word __sept_secondary_00_enc_start__
.word __sept_secondary_00_enc_size__
.byte CONTENT_TYPE_SP2
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "septsecondary00"
.align 5
/* sept_secondary 01 content header */
.word __sept_secondary_01_enc_start__
.word __sept_secondary_01_enc_size__
.byte CONTENT_TYPE_SP2
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "septsecondary01"
.align 5
/* sm content header */
.word __sm_kip_start__
.word __sm_kip_size__
@ -301,6 +269,17 @@ _content_headers:
.asciz "exosphere_fatal"
.align 5
/* tsec_keygen content header */
.word __tsec_keygen_bin_start__
.word __tsec_keygen_bin_size__
.byte CONTENT_TYPE_TKG
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "tsec_keygen"
.align 5
_content_headers_end:
/* No need to include this in normal programs: */

View File

@ -19,6 +19,7 @@
#include "di.h"
#include "timers.h"
#include "car.h"
#include "mc.h"
static int tsec_dma_wait_idle()
{
@ -91,7 +92,7 @@ void tsec_disable_clkrst()
clkrst_disable(CARDEVICE_HOST1X);
}
int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw_size)
static int tsec_run_fw_impl(const void *tsec_fw, size_t tsec_fw_size)
{
volatile tegra_tsec_t *tsec = tsec_get_regs();
@ -140,7 +141,7 @@ int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw
/* Execute firmware. */
tsec->TSEC_FALCON_MAILBOX1 = 0;
tsec->TSEC_FALCON_MAILBOX0 = rev;
tsec->TSEC_FALCON_MAILBOX0 = 1;
tsec->TSEC_FALCON_BOOTVEC = 0;
tsec->TSEC_FALCON_CPUCTL = 2;
@ -153,11 +154,9 @@ int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw
return -4;
}
uint32_t timeout = (get_time_ms() + 2000);
while (!tsec->TSEC_FALCON_MAILBOX1)
{
if (get_time_ms() > timeout)
{
uint32_t timeout = (get_time_ms() + 4000);
while (!(tsec->TSEC_FALCON_CPUCTL & 0x10)) {
if (get_time_ms() > timeout) {
/* Disable clocks. */
tsec_disable_clkrst();
@ -176,82 +175,27 @@ int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw
/* Clear magic value from HOST1X scratch register. */
MAKE_HOST1X_REG(0x3300) = 0;
/* Fetch result from SOR1. */
uint32_t tmp[0x4] = {0};
tmp[0] = SOR1_DP_HDCP_BKSV_LSB;
tmp[1] = SOR1_TMDS_HDCP_BKSV_LSB;
tmp[2] = SOR1_TMDS_HDCP_CN_MSB;
tmp[3] = SOR1_TMDS_HDCP_CN_LSB;
/* Clear SOR1 registers. */
SOR1_DP_HDCP_BKSV_LSB = 0;
SOR1_TMDS_HDCP_BKSV_LSB = 0;
SOR1_TMDS_HDCP_CN_MSB = 0;
SOR1_TMDS_HDCP_CN_LSB = 0;
/* Copy back the key. */
memcpy(key, &tmp, 0x10);
return 0;
}
int tsec_load_fw(const void *tsec_fw, size_t tsec_fw_size)
{
volatile tegra_tsec_t *tsec = tsec_get_regs();
int tsec_run_fw(const void *tsec_fw, size_t tsec_fw_size) {
/* Ensure that the ahb redirect is enabled. */
mc_enable_ahb_redirect();
/* Enable clocks. */
tsec_enable_clkrst();
/* Get bom/tom */
uint32_t bom = MAKE_MC_REG(MC_IRAM_BOM);
uint32_t tom = MAKE_MC_REG(MC_IRAM_TOM);
/* Make sure KFUSE is ready. */
if (!tsec_kfuse_wait_ready())
{
/* Disable clocks. */
tsec_disable_clkrst();
/* Override the ahb redirect extents. */
MAKE_MC_REG(MC_IRAM_BOM) = 0x40000000;
MAKE_MC_REG(MC_IRAM_TOM) = 0x80000000;
return -1;
}
/* Run the fw. */
int res = tsec_run_fw_impl(tsec_fw, tsec_fw_size);
/* Configure Falcon. */
tsec->TSEC_FALCON_DMACTL = 0;
tsec->TSEC_FALCON_IRQMSET = 0xFFF2;
tsec->TSEC_FALCON_IRQDEST = 0xFFF0;
tsec->TSEC_FALCON_ITFEN = 3;
/* Reset the ahb redirect extents. */
MAKE_MC_REG(MC_IRAM_BOM) = bom;
MAKE_MC_REG(MC_IRAM_TOM) = tom;
/* Make sure the DMA block is idle. */
if (!tsec_dma_wait_idle())
{
/* Disable clocks. */
tsec_disable_clkrst();
return -2;
}
/* Load firmware. */
tsec->TSEC_FALCON_DMATRFBASE = (uint32_t)tsec_fw >> 8;
for (uint32_t addr = 0; addr < tsec_fw_size; addr += 0x100)
{
if (!tsec_dma_phys_to_flcn(true, addr, addr))
{
/* Disable clocks. */
tsec_disable_clkrst();
return -3;
}
}
return 0;
}
void tsec_run_fw()
{
volatile tegra_tsec_t *tsec = tsec_get_regs();
/* Write magic value to HOST1X scratch register. */
MAKE_HOST1X_REG(0x3300) = 0x34C2E1DA;
/* Execute firmware. */
tsec->TSEC_FALCON_MAILBOX1 = 0;
tsec->TSEC_FALCON_MAILBOX0 = 1;
tsec->TSEC_FALCON_BOOTVEC = 0;
tsec->TSEC_FALCON_CPUCTL = 2;
return res;
}

View File

@ -306,8 +306,7 @@ static inline volatile tegra_tsec_t *tsec_get_regs(void)
void tsec_enable_clkrst();
void tsec_disable_clkrst();
int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw_size);
int tsec_load_fw(const void *tsec_fw, size_t tsec_fw_size);
void tsec_run_fw();
int tsec_run_fw(const void *tsec_fw, size_t tsec_fw_size);
#endif

View File

@ -34,7 +34,6 @@
#define u8 uint8_t
#define u32 uint32_t
#include "fusee_primary_bin.h"
#include "sept_primary_bin.h"
#include "rebootstub_bin.h"
#undef u8
#undef u32
@ -131,42 +130,8 @@ __attribute__((noreturn)) void reboot_to_fusee_primary(void) {
reboot_to_payload();
}
__attribute__((noreturn)) void reboot_to_sept(const void *tsec_fw, size_t tsec_fw_length, const void *stage2, size_t stage2_size) {
if (is_soc_mariko()) {
/* Reboot to sept isn't possible on mariko, so just do normal reboot. */
shutdown_system(true);
} else {
/* Copy tsec firmware. */
for (size_t i = 0; i < tsec_fw_length; i += sizeof(uint32_t)) {
write32le((void *)0x40010F00, i, read32le(tsec_fw, i));
}
MAKE_REG32(0x40010EFC) = tsec_fw_length;
/* Copy stage 2. */
for (size_t i = 0; i < stage2_size; i += sizeof(uint32_t)) {
write32le((void *)0x40016FE0, i, read32le(stage2, i));
}
/* Copy sept into IRAM low. */
for (size_t i = 0; i < sept_primary_bin_size; i += sizeof(uint32_t)) {
write32le((void *)0x4003F000, i, read32le(sept_primary_bin, i));
}
/* Patch SDRAM init to perform an SVC immediately after second write */
APBDEV_PMC_SCRATCH45_0 = 0x2E38DFFF;
APBDEV_PMC_SCRATCH46_0 = 0x6001DC28;
/* Set SVC handler to jump to reboot stub in IRAM. */
APBDEV_PMC_SCRATCH33_0 = 0x4003F000;
APBDEV_PMC_SCRATCH40_0 = 0x6000F208;
/* Trigger warm reboot. */
pmc_reboot(1 << 0);
while (true) { }
}
}
__attribute__((noreturn)) void reboot_to_iram_payload(void *payload, size_t payload_size) {
/* Copy sept into IRAM low. */
/* Copy payload into IRAM low. */
for (size_t i = 0; i < payload_size; i += sizeof(uint32_t)) {
write32le((void *)0x40010000, i, read32le(payload, i));
}

View File

@ -121,7 +121,6 @@ static inline bool check_32bit_address_range_in_program(uintptr_t addr, size_t s
__attribute__((noreturn)) void watchdog_reboot(void);
__attribute__((noreturn)) void pmc_reboot(uint32_t scratch0);
__attribute__((noreturn)) void reboot_to_fusee_primary(void);
__attribute__((noreturn)) void reboot_to_sept(const void *tsec_fw, size_t tsec_fw_length, const void *stage2, size_t stage2_size);
__attribute__((noreturn)) void reboot_to_iram_payload(void *payload, size_t payload_size);
__attribute__((noreturn)) void wait_for_button_and_reboot(void);
void wait_for_button(void);

View File

@ -1,10 +0,0 @@
SUBFOLDERS := sept-primary sept-secondary
TOPTARGETS := all clean
$(TOPTARGETS): $(SUBFOLDERS)
$(SUBFOLDERS):
$(MAKE) -C $@ $(MAKECMDGOALS)
.PHONY: $(TOPTARGETS) $(SUBFOLDERS)

View File

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

View File

@ -1,168 +0,0 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
PHDRS
{
crt0 PT_LOAD;
main PT_LOAD;
}
/* Mostly copied from https://github.com/devkitPro/buildscripts/blob/master/dkarm-eabi/crtls/3dsx.ld */
MEMORY
{
NULL : ORIGIN = 0x00000000, LENGTH = 0x1000
main : ORIGIN = 0x40010000, LENGTH = 0x1000
high_iram : ORIGIN = 0x4003F000, LENGTH = 0x1000
low_iram : ORIGIN = 0x40003000, LENGTH = 0x8000
}
SECTIONS
{
PROVIDE(__crt0_start__ = 0x4003F000);
PROVIDE(__main_start__ = 0x40010000);
PROVIDE(__stack_top__ = 0x40010000);
PROVIDE(__stack_bottom__ = 0x4000C000);
PROVIDE(__heap_start__ = 0);
PROVIDE(__heap_end__ = 0);
. = __crt0_start__;
.crt0 :
{
KEEP( *(.text.start) )
KEEP( *(.text.ipatch_word) )
KEEP( *(.init) )
. = ALIGN(32);
} >high_iram AT>high_iram :crt0
__main_phys_start__ = ABSOLUTE(.) ;
.text :
{
/* .text */
KEEP( *(.text.jump_to_main) )
*(.text)
*(.text.*)
*(.glue_7)
*(.glue_7t)
*(.stub)
*(.gnu.warning)
*(.gnu.linkonce.t*)
/* .fini */
KEEP( *(.fini) )
. = ALIGN(8);
} >main AT>high_iram :main
.rodata :
{
*(.rodata)
*(.roda)
*(.rodata.*)
*all.rodata*(*)
*(.gnu.linkonce.r*)
SORT(CONSTRUCTORS)
. = ALIGN(8);
} >main AT>high_iram
.preinit_array :
{
PROVIDE (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE (__preinit_array_end = .);
} >main AT>high_iram
.init_array ALIGN(4) :
{
PROVIDE (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
PROVIDE (__init_array_end = .);
} >main AT>high_iram
.fini_array ALIGN(4) :
{
PROVIDE (__fini_array_start = .);
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
PROVIDE (__fini_array_end = .);
} >main AT>high_iram
.ctors ALIGN(4) :
{
KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >main AT>high_iram
.dtors ALIGN(4) :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >main AT>high_iram
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) __exidx_start = ABSOLUTE(.);} >main AT>high_iram
ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) __exidx_end = ABSOLUTE(.);} >main AT>high_iram
.bss (NOLOAD) :
{
. = ALIGN(32);
PROVIDE (__bss_start__ = ABSOLUTE(.));
*(.dynbss)
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b*)
*(COMMON)
. = ALIGN(32);
PROVIDE (__bss_end__ = ABSOLUTE(.));
} >main AT>high_iram :NONE
__main_end__ = ABSOLUTE(.) ;
PROVIDE(__main_size__ = (__main_end__ - __main_start__));
/* ==================
==== Metadata ====
================== */
/* Discard sections that difficult post-processing */
/DISCARD/ : { *(.group .comment .note) }
/* 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) }
}

View File

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

View File

@ -1,96 +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/>.
*/
#ifndef FUSEE_APB_MISC_H
#define FUSEE_APB_MISC_H
#include <stdint.h>
#define APB_MISC_BASE 0x70000000
#define APB_PADCTL_BASE 0x70000810
#define MAKE_APB_MISC_REG(n) MAKE_REG32(APB_MISC_BASE + n)
#define MAKE_APB_PADCTL_REG(n) MAKE_REG32(APB_PADCTL_BASE + n)
#define APB_MISC_PP_PINMUX_GLOBAL_0 MAKE_APB_MISC_REG(0x40)
#define APB_MISC_GP_DSI_PAD_CONTROL_0 MAKE_APB_MISC_REG(0xAC0)
#define APB_MISC_GP_WIFI_EN_CFGPADCTRL_0 MAKE_APB_MISC_REG(0xB64)
#define APB_MISC_GP_WIFI_RST_CFGPADCTRL_0 MAKE_APB_MISC_REG(0xB68)
#define SDMMC1_PAD_CAL_DRVUP_SHIFT (20)
#define SDMMC1_PAD_CAL_DRVDN_SHIFT (12)
#define SDMMC1_CLK_CFG_CAL_DRVDN_SLWR_SHIFT (28)
#define SDMMC1_CLK_CFG_CAL_DRVDN_SLWF_SHIFT (30)
#define SDMMC1_PAD_CAL_DRVUP_MASK (0x7Fu << SDMMC1_PAD_CAL_DRVUP_SHIFT)
#define SDMMC1_PAD_CAL_DRVDN_MASK (0x7Fu << SDMMC1_PAD_CAL_DRVDN_SHIFT)
#define SDMMC1_CLK_CFG_CAL_DRVDN_SLWR_MASK (0x03u << SDMMC1_CLK_CFG_CAL_DRVDN_SLWR_SHIFT)
#define SDMMC1_CLK_CFG_CAL_DRVDN_SLWF_MASK (0x03u << SDMMC1_CLK_CFG_CAL_DRVDN_SLWF_SHIFT)
#define EMMC2_PAD_DRVUP_COMP_SHIFT (8)
#define EMMC2_PAD_DRVDN_COMP_SHIFT (2)
#define EMMC2_PAD_DRVUP_COMP_MASK (0x3Fu << EMMC2_PAD_DRVUP_COMP_SHIFT)
#define EMMC2_PAD_DRVDN_COMP_MASK (0x3Fu << EMMC2_PAD_DRVDN_COMP_SHIFT)
#define SDMMC2_PAD_CAL_DRVUP_SHIFT (20)
#define SDMMC2_PAD_CAL_DRVDN_SHIFT (12)
#define SDMMC2_PAD_CAL_DRVUP_MASK (0x7Fu << SDMMC2_PAD_CAL_DRVUP_SHIFT)
#define SDMMC2_PAD_CAL_DRVDN_MASK (0x7Fu << SDMMC2_PAD_CAL_DRVDN_SHIFT)
#define EMMC4_PAD_DRVUP_COMP_SHIFT (8)
#define EMMC4_PAD_DRVDN_COMP_SHIFT (2)
#define EMMC4_PAD_DRVUP_COMP_MASK (0x3Fu << EMMC4_PAD_DRVUP_COMP_SHIFT)
#define EMMC4_PAD_DRVDN_COMP_MASK (0x3Fu << EMMC4_PAD_DRVDN_COMP_SHIFT)
#define PADCTL_SDMMC1_DEEP_LOOPBACK (1 << 0)
#define PADCTL_SDMMC3_DEEP_LOOPBACK (1 << 0)
#define PADCTL_SDMMC2_ENABLE_DATA_IN (0xFF << 8)
#define PADCTL_SDMMC2_ENABLE_CLK_IN (0x3 << 4)
#define PADCTL_SDMMC2_DEEP_LOOPBACK (1 << 0)
#define PADCTL_SDMMC4_ENABLE_DATA_IN (0xFF << 8)
#define PADCTL_SDMMC4_ENABLE_CLK_IN (0x3 << 4)
#define PADCTL_SDMMC4_DEEP_LOOPBACK (1 << 0)
#define PADCTL_SDMMC1_CD_SOURCE (1 << 0)
#define PADCTL_SDMMC1_WP_SOURCE (1 << 1)
#define PADCTL_SDMMC3_CD_SOURCE (1 << 2)
#define PADCTL_SDMMC3_WP_SOURCE (1 << 3)
typedef struct {
uint32_t asdbgreg; /* 0x810 */
uint32_t _0x814[0x31];
uint32_t sdmmc1_clk_lpbk_control; /* 0x8D4 */
uint32_t sdmmc3_clk_lpbk_control; /* 0x8D8 */
uint32_t emmc2_pad_cfg_control; /* 0x8DC */
uint32_t emmc4_pad_cfg_control; /* 0x8E0 */
uint32_t _0x8E4[0x6E];
uint32_t sdmmc1_pad_cfgpadctrl; /* 0xA98 */
uint32_t emmc2_pad_cfgpadctrl; /* 0xA9C */
uint32_t emmc2_pad_drv_type_cfgpadctrl; /* 0xAA0 */
uint32_t emmc2_pad_pupd_cfgpadctrl; /* 0xAA4 */
uint32_t _0xAA8[0x03];
uint32_t sdmmc3_pad_cfgpadctrl; /* 0xAB0 */
uint32_t emmc4_pad_cfgpadctrl; /* 0xAB4 */
uint32_t emmc4_pad_drv_type_cfgpadctrl; /* 0xAB8 */
uint32_t emmc4_pad_pupd_cfgpadctrl; /* 0xABC */
uint32_t _0xAC0[0x2E];
uint32_t vgpio_gpio_mux_sel; /* 0xB74 */
uint32_t qspi_sck_lpbk_control; /* 0xB78 */
} tegra_padctl_t;
static inline volatile tegra_padctl_t *padctl_get_regs(void)
{
return (volatile tegra_padctl_t *)APB_PADCTL_BASE;
}
#endif

View File

@ -1,82 +0,0 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer
* 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 <stdint.h>
#include "btn.h"
#include "i2c.h"
#include "gpio.h"
#include "timers.h"
uint32_t btn_read()
{
uint32_t res = 0;
if (!gpio_read(GPIO_BUTTON_VOL_DOWN))
res |= BTN_VOL_DOWN;
if (!gpio_read(GPIO_BUTTON_VOL_UP))
res |= BTN_VOL_UP;
uint32_t val = 0;
if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x15, &val, 1))
{
if (val & 0x4)
res |= BTN_POWER;
}
return res;
}
uint32_t btn_wait()
{
uint32_t res = 0, btn = btn_read();
int pwr = 0;
if (btn & BTN_POWER)
{
pwr = 1;
btn &= ~BTN_POWER;
}
do
{
res = btn_read();
if (!(res & BTN_POWER) && pwr)
pwr = 0;
else if (pwr)
res &= ~BTN_POWER;
} while (btn == res);
return res;
}
uint32_t btn_wait_timeout(uint32_t time_ms, uint32_t mask)
{
uint32_t timeout = get_time_us() + time_ms * 1000;
uint32_t res = btn_read() & mask;
do
{
if (!(res & mask))
res = btn_read() & mask;
} while (get_time_us() < timeout);
return res;
}

View File

@ -1,30 +0,0 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer
* 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/>.
*/
#ifndef FUSEE_BTN_H_
#define FUSEE_BTN_H_
#define BTN_POWER 0x1
#define BTN_VOL_DOWN 0x2
#define BTN_VOL_UP 0x4
uint32_t btn_read();
uint32_t btn_wait();
uint32_t btn_wait_timeout(uint32_t time_ms, uint32_t mask);
#endif

View File

@ -1,142 +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 "car.h"
#include "timers.h"
#include "utils.h"
static inline uint32_t get_clk_source_reg(CarDevice dev) {
switch (dev) {
case CARDEVICE_UARTA: return 0x178;
case CARDEVICE_UARTB: return 0x17C;
case CARDEVICE_UARTC: return 0x1A0;
case CARDEVICE_I2C1: return 0x124;
case CARDEVICE_I2C5: return 0x128;
case CARDEVICE_TZRAM: return 0;
case CARDEVICE_SE: return 0x42C;
case CARDEVICE_HOST1X: return 0x180;
case CARDEVICE_TSEC: return 0x1F4;
case CARDEVICE_SOR_SAFE: return 0;
case CARDEVICE_SOR0: return 0;
case CARDEVICE_SOR1: return 0x410;
case CARDEVICE_KFUSE: return 0;
case CARDEVICE_CL_DVFS: return 0;
case CARDEVICE_CORESIGHT: return 0x1D4;
case CARDEVICE_MSELECT: return 0x3B4;
case CARDEVICE_ACTMON: return 0x3E8;
case CARDEVICE_BPMP: return 0;
default: generic_panic();
}
}
static inline uint32_t get_clk_source_val(CarDevice dev) {
switch (dev) {
case CARDEVICE_UARTA: return 0;
case CARDEVICE_UARTB: return 0;
case CARDEVICE_UARTC: return 0;
case CARDEVICE_I2C1: return 6;
case CARDEVICE_I2C5: return 6;
case CARDEVICE_TZRAM: return 0;
case CARDEVICE_SE: return 0;
case CARDEVICE_HOST1X: return 4;
case CARDEVICE_TSEC: return 0;
case CARDEVICE_SOR_SAFE: return 0;
case CARDEVICE_SOR0: return 0;
case CARDEVICE_SOR1: return 0;
case CARDEVICE_KFUSE: return 0;
case CARDEVICE_CL_DVFS: return 0;
case CARDEVICE_CORESIGHT: return 0;
case CARDEVICE_MSELECT: return 0;
case CARDEVICE_ACTMON: return 6;
case CARDEVICE_BPMP: return 0;
default: generic_panic();
}
}
static inline uint32_t get_clk_source_div(CarDevice dev) {
switch (dev) {
case CARDEVICE_UARTA: return 0;
case CARDEVICE_UARTB: return 0;
case CARDEVICE_UARTC: return 0;
case CARDEVICE_I2C1: return 0;
case CARDEVICE_I2C5: return 0;
case CARDEVICE_TZRAM: return 0;
case CARDEVICE_SE: return 0;
case CARDEVICE_HOST1X: return 3;
case CARDEVICE_TSEC: return 2;
case CARDEVICE_SOR_SAFE: return 0;
case CARDEVICE_SOR0: return 0;
case CARDEVICE_SOR1: return 2;
case CARDEVICE_KFUSE: return 0;
case CARDEVICE_CL_DVFS: return 0;
case CARDEVICE_CORESIGHT: return 4;
case CARDEVICE_MSELECT: return 6;
case CARDEVICE_ACTMON: return 0;
case CARDEVICE_BPMP: return 0;
default: generic_panic();
}
}
static uint32_t g_clk_reg_offsets[NUM_CAR_BANKS] = {0x010, 0x014, 0x018, 0x360, 0x364, 0x280, 0x298};
static uint32_t g_rst_reg_offsets[NUM_CAR_BANKS] = {0x004, 0x008, 0x00C, 0x358, 0x35C, 0x28C, 0x2A4};
void clk_enable(CarDevice dev) {
uint32_t clk_source_reg;
if ((clk_source_reg = get_clk_source_reg(dev))) {
MAKE_CAR_REG(clk_source_reg) = (get_clk_source_val(dev) << 29) | get_clk_source_div(dev);
}
MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F);
}
void clk_disable(CarDevice dev) {
MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F));
}
void rst_enable(CarDevice dev) {
MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F);
}
void rst_disable(CarDevice dev) {
MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F));
}
void clkrst_enable(CarDevice dev) {
clk_enable(dev);
rst_disable(dev);
}
void clkrst_disable(CarDevice dev) {
rst_enable(dev);
clk_disable(dev);
}
void clkrst_reboot(CarDevice dev) {
clkrst_disable(dev);
if (dev == CARDEVICE_KFUSE) {
/* Workaround for KFUSE clock. */
clk_enable(dev);
udelay(100);
rst_disable(dev);
udelay(200);
} else {
clkrst_enable(dev);
}
}
void clkrst_enable_fuse_regs(bool enable) {
volatile tegra_car_t *car = car_get_regs();
car->misc_clk_enb = ((car->misc_clk_enb & 0xEFFFFFFF) | ((enable & 1) << 28));
}

View File

@ -1,510 +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/>.
*/
#ifndef FUSEE_CAR_H
#define FUSEE_CAR_H
#include <stdint.h>
#include <stdbool.h>
#define CAR_BASE 0x60006000
#define MAKE_CAR_REG(n) MAKE_REG32(CAR_BASE + n)
#define CLK_L_SDMMC1 (1 << 14)
#define CLK_L_SDMMC2 (1 << 9)
#define CLK_U_SDMMC3 (1 << 5)
#define CLK_L_SDMMC4 (1 << 15)
#define CLK_SOURCE_MASK (0b111 << 29)
#define CLK_SOURCE_FIRST (0b000 << 29)
#define CLK_DIVIDER_MASK (0xff << 0)
#define CLK_DIVIDER_UNITY (0x00 << 0)
#define NUM_CAR_BANKS 7
/* Clock and reset devices. */
typedef enum {
CARDEVICE_BPMP = ((0 << 5) | 0x1),
CARDEVICE_UARTA = ((0 << 5) | 0x6),
CARDEVICE_UARTB = ((0 << 5) | 0x7),
CARDEVICE_I2C1 = ((0 << 5) | 0xC),
CARDEVICE_USBD = ((0 << 5) | 0x16),
CARDEVICE_HOST1X = ((0 << 5) | 0x1C),
CARDEVICE_AHBDMA = ((1 << 5) | 0x1),
CARDEVICE_APBDMA = ((1 << 5) | 0x2),
CARDEVICE_KFUSE = ((1 << 5) | 0x8),
CARDEVICE_I2C5 = ((1 << 5) | 0xF),
CARDEVICE_UARTC = ((1 << 5) | 0x17),
CARDEVICE_USB2 = ((1 << 5) | 0x1A),
CARDEVICE_CORESIGHT = ((2 << 5) | 0x9),
CARDEVICE_TSEC = ((2 << 5) | 0x13),
CARDEVICE_MSELECT = ((3 << 5) | 0x8),
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
CARDEVICE_SE = ((3 << 5) | 0x1F),
CARDEVICE_CL_DVFS = ((4 << 5) | 0x1B),
CARDEVICE_SOR0 = ((5 << 5) | 0x16),
CARDEVICE_SOR1 = ((5 << 5) | 0x17),
CARDEVICE_SOR_SAFE = ((6 << 5) | 0x1E),
} CarDevice;
/* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */
typedef struct {
uint32_t rst_src; /* _RST_SOURCE_0, 0x00 */
/* _RST_DEVICES_L/H/U_0 0x4-0xc */
uint32_t rst_dev_l;
uint32_t rst_dev_h;
uint32_t rst_dev_u;
/* _CLK_OUT_ENB_L/H/U_0 0x10-0x18 */
uint32_t clk_out_enb_l;
uint32_t clk_out_enb_h;
uint32_t clk_out_enb_u;
uint32_t _0x1C;
uint32_t cclk_brst_pol; /* _CCLK_BURST_POLICY_0, 0x20 */
uint32_t super_cclk_div; /* _SUPER_CCLK_DIVIDER_0, 0x24 */
uint32_t sclk_brst_pol; /* _SCLK_BURST_POLICY_0, 0x28 */
uint32_t super_sclk_div; /* _SUPER_SCLK_DIVIDER_0, 0x2c */
uint32_t clk_sys_rate; /* _CLK_SYSTEM_RATE_0, 0x30 */
uint32_t prog_dly_clk; /* _PROG_DLY_CLK_0, 0x34 */
uint32_t aud_sync_clk_rate; /* _AUDIO_SYNC_CLK_RATE_0, 0x38 */
uint32_t _0x3C;
uint32_t cop_clk_skip_plcy; /* _COP_CLK_SKIP_POLICY_0, 0x40 */
uint32_t clk_mask_arm; /* _CLK_MASK_ARM_0, 0x44 */
uint32_t misc_clk_enb; /* _MISC_CLK_ENB_0, 0x48 */
uint32_t clk_cpu_cmplx; /* _CLK_CPU_CMPLX_0, 0x4c */
uint32_t osc_ctrl; /* _OSC_CTRL_0, 0x50 */
uint32_t pll_lfsr; /* _PLL_LFSR_0, 0x54 */
uint32_t osc_freq_det; /* _OSC_FREQ_DET_0, 0x58 */
uint32_t osc_freq_det_stat; /* _OSC_FREQ_DET_STATUS_0, 0x5c */
uint32_t _0x60[2];
uint32_t plle_ss_cntl; /* _PLLE_SS_CNTL_0, 0x68 */
uint32_t plle_misc1; /* _PLLE_MISC1_0, 0x6c */
uint32_t _0x70[4];
/* PLLC 0x80-0x8c */
uint32_t pllc_base;
uint32_t pllc_out;
uint32_t pllc_misc0;
uint32_t pllc_misc1;
/* PLLM 0x90-0x9c */
uint32_t pllm_base;
uint32_t pllm_out;
uint32_t pllm_misc1;
uint32_t pllm_misc2;
/* PLLP 0xa0-0xac */
uint32_t pllp_base;
uint32_t pllp_outa;
uint32_t pllp_outb;
uint32_t pllp_misc;
/* PLLA 0xb0-0xbc */
uint32_t plla_base;
uint32_t plla_out;
uint32_t plla_misc0;
uint32_t plla_misc1;
/* PLLU 0xc0-0xcc */
uint32_t pllu_base;
uint32_t pllu_out;
uint32_t pllu_misc1;
uint32_t pllu_misc2;
/* PLLD 0xd0-0xdc */
uint32_t plld_base;
uint32_t plld_out;
uint32_t plld_misc1;
uint32_t plld_misc2;
/* PLLX 0xe0-0xe4 */
uint32_t pllx_base;
uint32_t pllx_misc;
/* PLLE 0xe8-0xf4 */
uint32_t plle_base;
uint32_t plle_misc;
uint32_t plle_ss_cntl1;
uint32_t plle_ss_cntl2;
uint32_t lvl2_clk_gate_ovra; /* _LVL2_CLK_GATE_OVRA_0, 0xf8 */
uint32_t lvl2_clk_gate_ovrb; /* _LVL2_CLK_GATE_OVRB_0, 0xfc */
uint32_t clk_source_i2s2; /* _CLK_SOURCE_I2S2_0, 0x100 */
uint32_t clk_source_i2s3; /* _CLK_SOURCE_I2S3_0, 0x104 */
uint32_t clk_source_spdif_out; /* _CLK_SOURCE_SPDIF_OUT_0, 0x108 */
uint32_t clk_source_spdif_in; /* _CLK_SOURCE_SPDIF_IN_0, 0x10c */
uint32_t clk_source_pwm; /* _CLK_SOURCE_PWM_0, 0x110 */
uint32_t _0x114;
uint32_t clk_source_spi2; /* _CLK_SOURCE_SPI2_0, 0x118 */
uint32_t clk_source_spi3; /* _CLK_SOURCE_SPI3_0, 0x11c */
uint32_t _0x120;
uint32_t clk_source_i2c1; /* _CLK_SOURCE_I2C1_0, 0x124 */
uint32_t clk_source_i2c5; /* _CLK_SOURCE_I2C5_0, 0x128 */
uint32_t _0x12c[2];
uint32_t clk_source_spi1; /* _CLK_SOURCE_SPI1_0, 0x134 */
uint32_t clk_source_disp1; /* _CLK_SOURCE_DISP1_0, 0x138 */
uint32_t clk_source_disp2; /* _CLK_SOURCE_DISP2_0, 0x13c */
uint32_t _0x140;
uint32_t clk_source_isp; /* _CLK_SOURCE_ISP_0, 0x144 */
uint32_t clk_source_vi; /* _CLK_SOURCE_VI_0, 0x148 */
uint32_t _0x14c;
uint32_t clk_source_sdmmc1; /* _CLK_SOURCE_SDMMC1_0, 0x150 */
uint32_t clk_source_sdmmc2; /* _CLK_SOURCE_SDMMC2_0, 0x154 */
uint32_t _0x158[3];
uint32_t clk_source_sdmmc4; /* _CLK_SOURCE_SDMMC4_0, 0x164 */
uint32_t _0x168[4];
uint32_t clk_source_uarta; /* _CLK_SOURCE_UARTA_0, 0x178 */
uint32_t clk_source_uartb; /* _CLK_SOURCE_UARTB_0, 0x17c */
uint32_t clk_source_host1x; /* _CLK_SOURCE_HOST1X_0, 0x180 */
uint32_t _0x184[5];
uint32_t clk_source_i2c2; /* _CLK_SOURCE_I2C2_0, 0x198 */
uint32_t clk_source_emc; /* _CLK_SOURCE_EMC_0, 0x19c */
uint32_t clk_source_uartc; /* _CLK_SOURCE_UARTC_0, 0x1a0 */
uint32_t _0x1a4;
uint32_t clk_source_vi_sensor; /* _CLK_SOURCE_VI_SENSOR_0, 0x1a8 */
uint32_t _0x1ac[2];
uint32_t clk_source_spi4; /* _CLK_SOURCE_SPI4_0, 0x1b4 */
uint32_t clk_source_i2c3; /* _CLK_SOURCE_I2C3_0, 0x1b8 */
uint32_t clk_source_sdmmc3; /* _CLK_SOURCE_SDMMC3_0, 0x1bc */
uint32_t clk_source_uartd; /* _CLK_SOURCE_UARTD_0, 0x1c0 */
uint32_t _0x1c4[2];
uint32_t clk_source_owr; /* _CLK_SOURCE_OWR_0, 0x1cc */
uint32_t _0x1d0;
uint32_t clk_source_csite; /* _CLK_SOURCE_CSITE_0, 0x1d4 */
uint32_t clk_source_i2s1; /* _CLK_SOURCE_I2S1_0, 0x1d8 */
uint32_t clk_source_dtv; /* _CLK_SOURCE_DTV_0, 0x1dc */
uint32_t _0x1e0[5];
uint32_t clk_source_tsec; /* _CLK_SOURCE_TSEC_0, 0x1f4 */
uint32_t _0x1f8;
uint32_t clk_spare2; /* _CLK_SPARE2_0, 0x1fc */
uint32_t _0x200[32];
uint32_t clk_out_enb_x; /* _CLK_OUT_ENB_X_0, 0x280 */
uint32_t clk_enb_x_set; /* _CLK_ENB_X_SET_0, 0x284 */
uint32_t clk_enb_x_clr; /* _CLK_ENB_X_CLR_0, 0x288 */
uint32_t rst_devices_x; /* _RST_DEVICES_X_0, 0x28c */
uint32_t rst_dev_x_set; /* _RST_DEV_X_SET_0, 0x290 */
uint32_t rst_dev_x_clr; /* _RST_DEV_X_CLR_0, 0x294 */
uint32_t clk_out_enb_y; /* _CLK_OUT_ENB_Y_0, 0x298 */
uint32_t clk_enb_y_set; /* _CLK_ENB_Y_SET_0, 0x29c */
uint32_t clk_enb_y_clr; /* _CLK_ENB_Y_CLR_0, 0x2a0 */
uint32_t rst_devices_y; /* _RST_DEVICES_Y_0, 0x2a4 */
uint32_t rst_dev_y_set; /* _RST_DEV_Y_SET_0, 0x2a8 */
uint32_t rst_dev_y_clr; /* _RST_DEV_Y_CLR_0, 0x2ac */
uint32_t _0x2b0[17];
uint32_t dfll_base; /* _DFLL_BASE_0, 0x2f4 */
uint32_t _0x2f8[2];
/* _RST_DEV_L/H/U_SET_0 0x300-0x314 */
uint32_t rst_dev_l_set;
uint32_t rst_dev_l_clr;
uint32_t rst_dev_h_set;
uint32_t rst_dev_h_clr;
uint32_t rst_dev_u_set;
uint32_t rst_dev_u_clr;
uint32_t _0x318[2];
/* _CLK_ENB_L/H/U_CLR_0 0x320-0x334 */
uint32_t clk_enb_l_set;
uint32_t clk_enb_l_clr;
uint32_t clk_enb_h_set;
uint32_t clk_enb_h_clr;
uint32_t clk_enb_u_set;
uint32_t clk_enb_u_clr;
uint32_t _0x338;
uint32_t ccplex_pg_sm_ovrd; /* _CCPLEX_PG_SM_OVRD_0, 0x33c */
uint32_t rst_cpu_cmplx_set; /* _RST_CPU_CMPLX_SET_0, 0x340 */
uint32_t rst_cpu_cmplx_clr; /* _RST_CPU_CMPLX_CLR_0, 0x344 */
/* Additional (T30) registers */
uint32_t clk_cpu_cmplx_set; /* _CLK_CPU_CMPLX_SET_0, 0x348 */
uint32_t clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET_0, 0x34c */
uint32_t _0x350[2];
uint32_t rst_dev_v; /* _RST_DEVICES_V_0, 0x358 */
uint32_t rst_dev_w; /* _RST_DEVICES_W_0, 0x35c */
uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V_0, 0x360 */
uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_W_0, 0x364 */
uint32_t cclkg_brst_pol; /* _CCLKG_BURST_POLICY_0, 0x368 */
uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36c */
uint32_t cclklp_brst_pol; /* _CCLKLP_BURST_POLICY_0, 0x370 */
uint32_t super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER_0, 0x374 */
uint32_t clk_cpug_cmplx; /* _CLK_CPUG_CMPLX_0, 0x378 */
uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37c */
uint32_t cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL_0, 0x380 */
uint32_t cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1_0, 0x384 */
uint32_t cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2_0, 0x388 */
uint32_t _0x38c[5];
uint32_t lvl2_clk_gate_ovrc; /* _LVL2_CLK_GATE_OVRC, 0x3a0 */
uint32_t lvl2_clk_gate_ovrd; /* _LVL2_CLK_GATE_OVRD, 0x3a4 */
uint32_t _0x3a8[2];
uint32_t _0x3b0;
uint32_t clk_source_mselect; /* _CLK_SOURCE_MSELECT_0, 0x3b4 */
uint32_t clk_source_tsensor; /* _CLK_SOURCE_TSENSOR_0, 0x3b8 */
uint32_t clk_source_i2s4; /* _CLK_SOURCE_I2S4_0, 0x3bc */
uint32_t clk_source_i2s5; /* _CLK_SOURCE_I2S5_0, 0x3c0 */
uint32_t clk_source_i2c4; /* _CLK_SOURCE_I2C4_0, 0x3c4 */
uint32_t _0x3c8[2];
uint32_t clk_source_ahub; /* _CLK_SOURCE_AHUB_0, 0x3d0 */
uint32_t _0x3d4[4];
uint32_t clk_source_hda2codec_2x; /* _CLK_SOURCE_HDA2CODEC_2X_0, 0x3e4 */
uint32_t clk_source_actmon; /* _CLK_SOURCE_ACTMON_0, 0x3e8 */
uint32_t clk_source_extperiph1; /* _CLK_SOURCE_EXTPERIPH1_0, 0x3ec */
uint32_t clk_source_extperiph2; /* _CLK_SOURCE_EXTPERIPH2_0, 0x3f0 */
uint32_t clk_source_extperiph3; /* _CLK_SOURCE_EXTPERIPH3_0, 0x3f4 */
uint32_t _0x3f8;
uint32_t clk_source_i2c_slow; /* _CLK_SOURCE_I2C_SLOW_0, 0x3fc */
uint32_t clk_source_sys; /* _CLK_SOURCE_SYS_0, 0x400 */
uint32_t clk_source_ispb; /* _CLK_SOURCE_ISPB_0, 0x404 */
uint32_t _0x408[2];
uint32_t clk_source_sor1; /* _CLK_SOURCE_SOR1_0, 0x410 */
uint32_t clk_source_sor0; /* _CLK_SOURCE_SOR0_0, 0x414 */
uint32_t _0x418[2];
uint32_t clk_source_sata_oob; /* _CLK_SOURCE_SATA_OOB_0, 0x420 */
uint32_t clk_source_sata; /* _CLK_SOURCE_SATA_0, 0x424 */
uint32_t clk_source_hda; /* _CLK_SOURCE_HDA_0, 0x428 */
uint32_t clk_source_se; /* _CLK_SOURCE_SE_0, 0x42c */
/* _RST_DEV_V/W_SET_0 0x430-0x43c */
uint32_t rst_dev_v_set;
uint32_t rst_dev_v_clr;
uint32_t rst_dev_w_set;
uint32_t rst_dev_w_clr;
/* _CLK_ENB_V/W_CLR_0 0x440-0x44c */
uint32_t clk_enb_v_set;
uint32_t clk_enb_v_clr;
uint32_t clk_enb_w_set;
uint32_t clk_enb_w_clr;
/* Additional (T114+) registers */
uint32_t rst_cpug_cmplx_set; /* _RST_CPUG_CMPLX_SET_0, 0x450 */
uint32_t rst_cpug_cmplx_clr; /* _RST_CPUG_CMPLX_CLR_0, 0x454 */
uint32_t rst_cpulp_cmplx_set; /* _RST_CPULP_CMPLX_SET_0, 0x458 */
uint32_t rst_cpulp_cmplx_clr; /* _RST_CPULP_CMPLX_CLR_0, 0x45c */
uint32_t clk_cpug_cmplx_set; /* _CLK_CPUG_CMPLX_SET_0, 0x460 */
uint32_t clk_cpug_cmplx_clr; /* _CLK_CPUG_CMPLX_CLR_0, 0x464 */
uint32_t clk_cpulp_cmplx_set; /* _CLK_CPULP_CMPLX_SET_0, 0x468 */
uint32_t clk_cpulp_cmplx_clr; /* _CLK_CPULP_CMPLX_CLR_0, 0x46c */
uint32_t cpu_cmplx_status; /* _CPU_CMPLX_STATUS_0, 0x470 */
uint32_t _0x474;
uint32_t intstatus; /* _INTSTATUS_0, 0x478 */
uint32_t intmask; /* _INTMASK_0, 0x47c */
uint32_t utmip_pll_cfg0; /* _UTMIP_PLL_CFG0_0, 0x480 */
uint32_t utmip_pll_cfg1; /* _UTMIP_PLL_CFG1_0, 0x484 */
uint32_t utmip_pll_cfg2; /* _UTMIP_PLL_CFG2_0, 0x488 */
uint32_t plle_aux; /* _PLLE_AUX_0, 0x48c */
uint32_t sata_pll_cfg0; /* _SATA_PLL_CFG0_0, 0x490 */
uint32_t sata_pll_cfg1; /* _SATA_PLL_CFG1_0, 0x494 */
uint32_t pcie_pll_cfg0; /* _PCIE_PLL_CFG0_0, 0x498 */
uint32_t prog_audio_dly_clk; /* _PROG_AUDIO_DLY_CLK_0, 0x49c */
uint32_t audio_sync_clk_i2s0; /* _AUDIO_SYNC_CLK_I2S0_0, 0x4a0 */
uint32_t audio_sync_clk_i2s1; /* _AUDIO_SYNC_CLK_I2S1_0, 0x4a4 */
uint32_t audio_sync_clk_i2s2; /* _AUDIO_SYNC_CLK_I2S2_0, 0x4a8 */
uint32_t audio_sync_clk_i2s3; /* _AUDIO_SYNC_CLK_I2S3_0, 0x4ac */
uint32_t audio_sync_clk_i2s4; /* _AUDIO_SYNC_CLK_I2S4_0, 0x4b0 */
uint32_t audio_sync_clk_spdif; /* _AUDIO_SYNC_CLK_SPDIF_0, 0x4b4 */
uint32_t plld2_base; /* _PLLD2_BASE_0, 0x4b8 */
uint32_t plld2_misc; /* _PLLD2_MISC_0, 0x4bc */
uint32_t utmip_pll_cfg3; /* _UTMIP_PLL_CFG3_0, 0x4c0 */
uint32_t pllrefe_base; /* _PLLREFE_BASE_0, 0x4c4 */
uint32_t pllrefe_misc; /* _PLLREFE_MISC_0, 0x4c8 */
uint32_t pllrefe_out; /* _PLLREFE_OUT_0, 0x4cc */
uint32_t cpu_finetrim_byp; /* _CPU_FINETRIM_BYP_0, 0x4d0 */
uint32_t cpu_finetrim_select; /* _CPU_FINETRIM_SELECT_0, 0x4d4 */
uint32_t cpu_finetrim_dr; /* _CPU_FINETRIM_DR_0, 0x4d8 */
uint32_t cpu_finetrim_df; /* _CPU_FINETRIM_DF_0, 0x4dc */
uint32_t cpu_finetrim_f; /* _CPU_FINETRIM_F_0, 0x4e0 */
uint32_t cpu_finetrim_r; /* _CPU_FINETRIM_R_0, 0x4e4 */
uint32_t pllc2_base; /* _PLLC2_BASE_0, 0x4e8 */
uint32_t pllc2_misc0; /* _PLLC2_MISC_0_0, 0x4ec */
uint32_t pllc2_misc1; /* _PLLC2_MISC_1_0, 0x4f0 */
uint32_t pllc2_misc2; /* _PLLC2_MISC_2_0, 0x4f4 */
uint32_t pllc2_misc3; /* _PLLC2_MISC_3_0, 0x4f8 */
uint32_t pllc3_base; /* _PLLC3_BASE_0, 0x4fc */
uint32_t pllc3_misc0; /* _PLLC3_MISC_0_0, 0x500 */
uint32_t pllc3_misc1; /* _PLLC3_MISC_1_0, 0x504 */
uint32_t pllc3_misc2; /* _PLLC3_MISC_2_0, 0x508 */
uint32_t pllc3_misc3; /* _PLLC3_MISC_3_0, 0x50c */
uint32_t pllx_misc1; /* _PLLX_MISC_1_0, 0x510 */
uint32_t pllx_misc2; /* _PLLX_MISC_2_0, 0x514 */
uint32_t pllx_misc3; /* _PLLX_MISC_3_0, 0x518 */
uint32_t xusbio_pll_cfg0; /* _XUSBIO_PLL_CFG0_0, 0x51c */
uint32_t xusbio_pll_cfg1; /* _XUSBIO_PLL_CFG0_1, 0x520 */
uint32_t plle_aux1; /* _PLLE_AUX1_0, 0x524 */
uint32_t pllp_reshift; /* _PLLP_RESHIFT_0, 0x528 */
uint32_t utmipll_hw_pwrdn_cfg0; /* _UTMIPLL_HW_PWRDN_CFG0_0, 0x52c */
uint32_t pllu_hw_pwrdn_cfg0; /* _PLLU_HW_PWRDN_CFG0_0, 0x530 */
uint32_t xusb_pll_cfg0; /* _XUSB_PLL_CFG0_0, 0x534 */
uint32_t _0x538;
uint32_t clk_cpu_misc; /* _CLK_CPU_MISC_0, 0x53c */
uint32_t clk_cpug_misc; /* _CLK_CPUG_MISC_0, 0x540 */
uint32_t clk_cpulp_misc; /* _CLK_CPULP_MISC_0, 0x544 */
uint32_t pllx_hw_ctrl_cfg; /* _PLLX_HW_CTRL_CFG_0, 0x548 */
uint32_t pllx_sw_ramp_cfg; /* _PLLX_SW_RAMP_CFG_0, 0x54c */
uint32_t pllx_hw_ctrl_status; /* _PLLX_HW_CTRL_STATUS_0, 0x550 */
uint32_t lvl2_clk_gate_ovre; /* _LVL2_CLK_GATE_OVRE, 0x554 */
uint32_t super_gr3d_clk_div; /* _SUPER_GR3D_CLK_DIVIDER_0, 0x558 */
uint32_t spare_reg0; /* _SPARE_REG0_0, 0x55c */
uint32_t audio_sync_clk_dmic1; /* _AUDIO_SYNC_CLK_DMIC1_0, 0x560 */
uint32_t audio_sync_clk_dmic2; /* _AUDIO_SYNC_CLK_DMIC2_0, 0x564 */
uint32_t _0x568[2];
uint32_t plld2_ss_cfg; /* _PLLD2_SS_CFG, 0x570 */
uint32_t plld2_ss_ctrl1; /* _PLLD2_SS_CTRL1_0, 0x574 */
uint32_t plld2_ss_ctrl2; /* _PLLD2_SS_CTRL2_0, 0x578 */
uint32_t _0x57c[5];
uint32_t plldp_base; /* _PLLDP_BASE, 0x590*/
uint32_t plldp_misc; /* _PLLDP_MISC, 0x594 */
uint32_t plldp_ss_cfg; /* _PLLDP_SS_CFG, 0x598 */
uint32_t plldp_ss_ctrl1; /* _PLLDP_SS_CTRL1_0, 0x59c */
uint32_t plldp_ss_ctrl2; /* _PLLDP_SS_CTRL2_0, 0x5a0 */
uint32_t pllc4_base; /* _PLLC4_BASE_0, 0x5a4 */
uint32_t pllc4_misc; /* _PLLC4_MISC_0, 0x5a8 */
uint32_t _0x5ac[6];
uint32_t clk_spare0; /* _CLK_SPARE0_0, 0x5c4 */
uint32_t clk_spare1; /* _CLK_SPARE1_0, 0x5c8 */
uint32_t gpu_isob_ctrl; /* _GPU_ISOB_CTRL_0, 0x5cc */
uint32_t pllc_misc2; /* _PLLC_MISC_2_0, 0x5d0 */
uint32_t pllc_misc3; /* _PLLC_MISC_3_0, 0x5d4 */
uint32_t plla_misc2; /* _PLLA_MISC2_0, 0x5d8 */
uint32_t _0x5dc[2];
uint32_t pllc4_out; /* _PLLC4_OUT_0, 0x5e4 */
uint32_t pllmb_base; /* _PLLMB_BASE_0, 0x5e8 */
uint32_t pllmb_misc1; /* _PLLMB_MISC1_0, 0x5ec */
uint32_t pllx_misc4; /* _PLLX_MISC_4_0, 0x5f0 */
uint32_t pllx_misc5; /* _PLLX_MISC_5_0, 0x5f4 */
uint32_t _0x5f8[2];
uint32_t clk_source_xusb_core_host; /* _CLK_SOURCE_XUSB_CORE_HOST_0, 0x600 */
uint32_t clk_source_xusb_falcon; /* _CLK_SOURCE_XUSB_FALCON_0, 0x604 */
uint32_t clk_source_xusb_fs; /* _CLK_SOURCE_XUSB_FS_0, 0x608 */
uint32_t clk_source_xusb_core_dev; /* _CLK_SOURCE_XUSB_CORE_DEV_0, 0x60c */
uint32_t clk_source_xusb_ss; /* _CLK_SOURCE_XUSB_SS_0, 0x610 */
uint32_t clk_source_cilab; /* _CLK_SOURCE_CILAB_0, 0x614 */
uint32_t clk_source_cilcd; /* _CLK_SOURCE_CILCD_0, 0x618 */
uint32_t clk_source_cilef; /* _CLK_SOURCE_CILEF_0, 0x61c */
uint32_t clk_source_dsia_lp; /* _CLK_SOURCE_DSIA_LP_0, 0x620 */
uint32_t clk_source_dsib_lp; /* _CLK_SOURCE_DSIB_LP_0, 0x624 */
uint32_t clk_source_entropy; /* _CLK_SOURCE_ENTROPY_0, 0x628 */
uint32_t clk_source_dvfs_ref; /* _CLK_SOURCE_DVFS_REF_0, 0x62c */
uint32_t clk_source_dvfs_soc; /* _CLK_SOURCE_DVFS_SOC_0, 0x630 */
uint32_t _0x634[3];
uint32_t clk_source_emc_latency; /* _CLK_SOURCE_EMC_LATENCY_0, 0x640 */
uint32_t clk_source_soc_therm; /* _CLK_SOURCE_SOC_THERM_0, 0x644 */
uint32_t _0x648;
uint32_t clk_source_dmic1; /* _CLK_SOURCE_DMIC1_0, 0x64c */
uint32_t clk_source_dmic2; /* _CLK_SOURCE_DMIC2_0, 0x650 */
uint32_t _0x654;
uint32_t clk_source_vi_sensor2; /* _CLK_SOURCE_VI_SENSOR2_0, 0x658 */
uint32_t clk_source_i2c6; /* _CLK_SOURCE_I2C6_0, 0x65c */
uint32_t clk_source_mipibif; /* _CLK_SOURCE_MIPIBIF_0, 0x660 */
uint32_t clk_source_emc_dll; /* _CLK_SOURCE_EMC_DLL_0, 0x664 */
uint32_t _0x668;
uint32_t clk_source_uart_fst_mipi_cal; /* _CLK_SOURCE_UART_FST_MIPI_CAL_0, 0x66c */
uint32_t _0x670[2];
uint32_t clk_source_vic; /* _CLK_SOURCE_VIC_0, 0x678 */
uint32_t pllp_outc; /* _PLLP_OUTC_0, 0x67c */
uint32_t pllp_misc1; /* _PLLP_MISC1_0, 0x680 */
uint32_t _0x684[2];
uint32_t emc_div_clk_shaper_ctrl; /* _EMC_DIV_CLK_SHAPER_CTRL_0, 0x68c */
uint32_t emc_pllc_shaper_ctrl; /* _EMC_PLLC_SHAPER_CTRL_0, 0x690 */
uint32_t clk_source_sdmmc_legacy_tm; /* _CLK_SOURCE_SDMMC_LEGACY_TM_0, 0x694 */
uint32_t clk_source_nvdec; /* _CLK_SOURCE_NVDEC_0, 0x698 */
uint32_t clk_source_nvjpg; /* _CLK_SOURCE_NVJPG_0, 0x69c */
uint32_t clk_source_nvenc; /* _CLK_SOURCE_NVENC_0, 0x6a0 */
uint32_t plla1_base; /* _PLLA1_BASE_0, 0x6a4 */
uint32_t plla1_misc0; /* _PLLA1_MISC_0_0, 0x6a8 */
uint32_t plla1_misc1; /* _PLLA1_MISC_1_0, 0x6ac */
uint32_t plla1_misc2; /* _PLLA1_MISC_2_0, 0x6b0 */
uint32_t plla1_misc3; /* _PLLA1_MISC_3_0, 0x6b4 */
uint32_t audio_sync_clk_dmic3; /* _AUDIO_SYNC_CLK_DMIC3_0, 0x6b8 */
uint32_t clk_source_dmic3; /* _CLK_SOURCE_DMIC3_0, 0x6bc */
uint32_t clk_source_ape; /* _CLK_SOURCE_APE_0, 0x6c0 */
uint32_t clk_source_qspi; /* _CLK_SOURCE_QSPI_0, 0x6c4 */
uint32_t clk_source_vi_i2c; /* _CLK_SOURCE_VI_I2C_0, 0x6c8 */
uint32_t clk_source_usb2_hsic_trk; /* _CLK_SOURCE_USB2_HSIC_TRK_0, 0x6cc */
uint32_t clk_source_pex_sata_usb_rx_byp; /* _CLK_SOURCE_PEX_SATA_USB_RX_BYP_0, 0x6d0 */
uint32_t clk_source_maud; /* _CLK_SOURCE_MAUD_0, 0x6d4 */
uint32_t clk_source_tsecb; /* _CLK_SOURCE_TSECB_0, 0x6d8 */
uint32_t clk_cpug_misc1; /* _CLK_CPUG_MISC1_0, 0x6dc */
uint32_t aclk_burst_policy; /* _ACLK_BURST_POLICY_0, 0x6e0 */
uint32_t super_aclk_divider; /* _SUPER_ACLK_DIVIDER_0, 0x6e4 */
uint32_t nvenc_super_clk_divider; /* _NVENC_SUPER_CLK_DIVIDER_0, 0x6e8 */
uint32_t vi_super_clk_divider; /* _VI_SUPER_CLK_DIVIDER_0, 0x6ec */
uint32_t vic_super_clk_divider; /* _VIC_SUPER_CLK_DIVIDER_0, 0x6f0 */
uint32_t nvdec_super_clk_divider; /* _NVDEC_SUPER_CLK_DIVIDER_0, 0x6f4 */
uint32_t isp_super_clk_divider; /* _ISP_SUPER_CLK_DIVIDER_0, 0x6f8 */
uint32_t ispb_super_clk_divider; /* _ISPB_SUPER_CLK_DIVIDER_0, 0x6fc */
uint32_t nvjpg_super_clk_divider; /* _NVJPG_SUPER_CLK_DIVIDER_0, 0x700 */
uint32_t se_super_clk_divider; /* _SE_SUPER_CLK_DIVIDER_0, 0x704 */
uint32_t tsec_super_clk_divider; /* _TSEC_SUPER_CLK_DIVIDER_0, 0x708 */
uint32_t tsecb_super_clk_divider; /* _TSECB_SUPER_CLK_DIVIDER_0, 0x70c */
uint32_t clk_source_uartape; /* _CLK_SOURCE_UARTAPE_0, 0x710 */
uint32_t clk_cpug_misc2; /* _CLK_CPUG_MISC2_0, 0x714 */
uint32_t clk_source_dbgapb; /* _CLK_SOURCE_DBGAPB_0, 0x718 */
uint32_t clk_ccplex_cc4_ret_clk_enb; /* _CLK_CCPLEX_CC4_RET_CLK_ENB_0, 0x71c */
uint32_t actmon_cpu_clk; /* _ACTMON_CPU_CLK_0, 0x720 */
uint32_t clk_source_emc_safe; /* _CLK_SOURCE_EMC_SAFE_0, 0x724 */
uint32_t sdmmc2_pllc4_out0_shaper_ctrl; /* _SDMMC2_PLLC4_OUT0_SHAPER_CTRL_0, 0x728 */
uint32_t sdmmc2_pllc4_out1_shaper_ctrl; /* _SDMMC2_PLLC4_OUT1_SHAPER_CTRL_0, 0x72c */
uint32_t sdmmc2_pllc4_out2_shaper_ctrl; /* _SDMMC2_PLLC4_OUT2_SHAPER_CTRL_0, 0x730 */
uint32_t sdmmc2_div_clk_shaper_ctrl; /* _SDMMC2_DIV_CLK_SHAPER_CTRL_0, 0x734 */
uint32_t sdmmc4_pllc4_out0_shaper_ctrl; /* _SDMMC4_PLLC4_OUT0_SHAPER_CTRL_0, 0x738 */
uint32_t sdmmc4_pllc4_out1_shaper_ctrl; /* _SDMMC4_PLLC4_OUT1_SHAPER_CTRL_0, 0x73c */
uint32_t sdmmc4_pllc4_out2_shaper_ctrl; /* _SDMMC4_PLLC4_OUT2_SHAPER_CTRL_0, 0x740 */
uint32_t sdmmc4_div_clk_shaper_ctrl; /* _SDMMC4_DIV_CLK_SHAPER_CTRL_0, 0x744 */
} tegra_car_t;
static inline volatile tegra_car_t *car_get_regs(void) {
return (volatile tegra_car_t *)CAR_BASE;
}
void clk_enable(CarDevice dev);
void clk_disable(CarDevice dev);
void rst_enable(CarDevice dev);
void rst_disable(CarDevice dev);
void clkrst_enable(CarDevice dev);
void clkrst_disable(CarDevice dev);
void clkrst_reboot(CarDevice dev);
void clkrst_enable_fuse_regs(bool enable);
#endif

View File

@ -1,350 +0,0 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer
* 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/>.
*/
#ifndef FUSEE_DI_H_
#define FUSEE_DI_H_
#include <stdint.h>
#include <stdbool.h>
#define HOST1X_BASE 0x50000000
#define DI_BASE 0x54200000
#define DSI_BASE 0x54300000
#define VIC_BASE 0x54340000
#define MIPI_CAL_BASE 0x700E3000
#define MAKE_HOST1X_REG(n) MAKE_REG32(HOST1X_BASE + n)
#define MAKE_DI_REG(n) MAKE_REG32(DI_BASE + n * 4)
#define MAKE_DSI_REG(n) MAKE_REG32(DSI_BASE + n * 4)
#define MAKE_MIPI_CAL_REG(n) MAKE_REG32(MIPI_CAL_BASE + n)
#define MAKE_VIC_REG(n) MAKE_REG32(VIC_BASE + n)
/* Display registers. */
#define DC_CMD_GENERAL_INCR_SYNCPT 0x00
#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x01
#define SYNCPT_CNTRL_NO_STALL (1 << 8)
#define SYNCPT_CNTRL_SOFT_RESET (1 << 0)
#define DC_CMD_CONT_SYNCPT_VSYNC 0x28
#define SYNCPT_VSYNC_ENABLE (1 << 8)
#define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031
#define DC_CMD_DISPLAY_COMMAND 0x32
#define DISP_CTRL_MODE_STOP (0 << 5)
#define DISP_CTRL_MODE_C_DISPLAY (1 << 5)
#define DISP_CTRL_MODE_NC_DISPLAY (2 << 5)
#define DISP_CTRL_MODE_MASK (3 << 5)
#define DC_CMD_DISPLAY_POWER_CONTROL 0x36
#define PW0_ENABLE (1 << 0)
#define PW1_ENABLE (1 << 2)
#define PW2_ENABLE (1 << 4)
#define PW3_ENABLE (1 << 6)
#define PW4_ENABLE (1 << 8)
#define PM0_ENABLE (1 << 16)
#define PM1_ENABLE (1 << 18)
#define DC_CMD_INT_MASK 0x38
#define DC_CMD_INT_ENABLE 0x39
#define DC_CMD_STATE_ACCESS 0x40
#define READ_MUX (1 << 0)
#define WRITE_MUX (1 << 2)
#define DC_CMD_STATE_CONTROL 0x41
#define GENERAL_ACT_REQ (1 << 0)
#define WIN_A_ACT_REQ (1 << 1)
#define WIN_B_ACT_REQ (1 << 2)
#define WIN_C_ACT_REQ (1 << 3)
#define CURSOR_ACT_REQ (1 << 7)
#define GENERAL_UPDATE (1 << 8)
#define WIN_A_UPDATE (1 << 9)
#define WIN_B_UPDATE (1 << 10)
#define WIN_C_UPDATE (1 << 11)
#define CURSOR_UPDATE (1 << 15)
#define NC_HOST_TRIG (1 << 24)
#define DC_CMD_DISPLAY_WINDOW_HEADER 0x42
#define WINDOW_A_SELECT (1 << 4)
#define WINDOW_B_SELECT (1 << 5)
#define WINDOW_C_SELECT (1 << 6)
#define DC_CMD_REG_ACT_CONTROL 0x043
#define DC_COM_CRC_CONTROL 0x300
#define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x))
#define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x))
#define DC_COM_DSC_TOP_CTL 0x33E
#define DC_DISP_DISP_WIN_OPTIONS 0x402
#define HDMI_ENABLE (1 << 30)
#define DSI_ENABLE (1 << 29)
#define SOR1_TIMING_CYA (1 << 27)
#define SOR1_ENABLE (1 << 26)
#define SOR_ENABLE (1 << 25)
#define CURSOR_ENABLE (1 << 16)
#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403
#define DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER 0x404
#define DC_DISP_DISP_TIMING_OPTIONS 0x405
#define DC_DISP_REF_TO_SYNC 0x406
#define DC_DISP_SYNC_WIDTH 0x407
#define DC_DISP_BACK_PORCH 0x408
#define DC_DISP_ACTIVE 0x409
#define DC_DISP_FRONT_PORCH 0x40A
#define DC_DISP_DISP_CLOCK_CONTROL 0x42E
#define PIXEL_CLK_DIVIDER_PCD1 (0 << 8)
#define PIXEL_CLK_DIVIDER_PCD1H (1 << 8)
#define PIXEL_CLK_DIVIDER_PCD2 (2 << 8)
#define PIXEL_CLK_DIVIDER_PCD3 (3 << 8)
#define PIXEL_CLK_DIVIDER_PCD4 (4 << 8)
#define PIXEL_CLK_DIVIDER_PCD6 (5 << 8)
#define PIXEL_CLK_DIVIDER_PCD8 (6 << 8)
#define PIXEL_CLK_DIVIDER_PCD9 (7 << 8)
#define PIXEL_CLK_DIVIDER_PCD12 (8 << 8)
#define PIXEL_CLK_DIVIDER_PCD16 (9 << 8)
#define PIXEL_CLK_DIVIDER_PCD18 (10 << 8)
#define PIXEL_CLK_DIVIDER_PCD24 (11 << 8)
#define PIXEL_CLK_DIVIDER_PCD13 (12 << 8)
#define SHIFT_CLK_DIVIDER(x) ((x) & 0xff)
#define DC_DISP_DISP_INTERFACE_CONTROL 0x42F
#define DISP_DATA_FORMAT_DF1P1C (0 << 0)
#define DISP_DATA_FORMAT_DF1P2C24B (1 << 0)
#define DISP_DATA_FORMAT_DF1P2C18B (2 << 0)
#define DISP_DATA_FORMAT_DF1P2C16B (3 << 0)
#define DISP_DATA_FORMAT_DF2S (4 << 0)
#define DISP_DATA_FORMAT_DF3S (5 << 0)
#define DISP_DATA_FORMAT_DFSPI (6 << 0)
#define DISP_DATA_FORMAT_DF1P3C24B (7 << 0)
#define DISP_DATA_FORMAT_DF1P3C18B (8 << 0)
#define DISP_ALIGNMENT_MSB (0 << 8)
#define DISP_ALIGNMENT_LSB (1 << 8)
#define DISP_ORDER_RED_BLUE (0 << 9)
#define DISP_ORDER_BLUE_RED (1 << 9)
#define DC_DISP_DISP_COLOR_CONTROL 0x430
#define DITHER_CONTROL_MASK (3 << 8)
#define DITHER_CONTROL_DISABLE (0 << 8)
#define DITHER_CONTROL_ORDERED (2 << 8)
#define DITHER_CONTROL_ERRDIFF (3 << 8)
#define BASE_COLOR_SIZE_MASK (0xf << 0)
#define BASE_COLOR_SIZE_666 (0 << 0)
#define BASE_COLOR_SIZE_111 (1 << 0)
#define BASE_COLOR_SIZE_222 (2 << 0)
#define BASE_COLOR_SIZE_333 (3 << 0)
#define BASE_COLOR_SIZE_444 (4 << 0)
#define BASE_COLOR_SIZE_555 (5 << 0)
#define BASE_COLOR_SIZE_565 (6 << 0)
#define BASE_COLOR_SIZE_332 (7 << 0)
#define BASE_COLOR_SIZE_888 (8 << 0)
#define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431
#define SC1_H_QUALIFIER_NONE (1 << 16)
#define SC0_H_QUALIFIER_NONE (1 << 0)
#define DC_DISP_DATA_ENABLE_OPTIONS 0x432
#define DE_SELECT_ACTIVE_BLANK (0 << 0)
#define DE_SELECT_ACTIVE (1 << 0)
#define DE_SELECT_ACTIVE_IS (2 << 0)
#define DE_CONTROL_ONECLK (0 << 2)
#define DE_CONTROL_NORMAL (1 << 2)
#define DE_CONTROL_EARLY_EXT (2 << 2)
#define DE_CONTROL_EARLY (3 << 2)
#define DE_CONTROL_ACTIVE_BLANK (4 << 2)
#define DC_DISP_DC_MCCIF_FIFOCTRL 0x480
#define DC_DISP_BLEND_BACKGROUND_COLOR 0x4E4
#define DC_WIN_CSC_YOF 0x611
#define DC_WIN_CSC_KYRGB 0x612
#define DC_WIN_CSC_KUR 0x613
#define DC_WIN_CSC_KVR 0x614
#define DC_WIN_CSC_KUG 0x615
#define DC_WIN_CSC_KVG 0x616
#define DC_WIN_CSC_KUB 0x617
#define DC_WIN_CSC_KVB 0x618
#define DC_WIN_AD_WIN_OPTIONS 0xB80
#define DC_WIN_BD_WIN_OPTIONS 0xD80
#define DC_WIN_CD_WIN_OPTIONS 0xF80
/* The following registers are A/B/C shadows of the 0xB80/0xD80/0xF80 registers (see DISPLAY_WINDOW_HEADER). */
#define DC_WIN_WIN_OPTIONS 0x700
#define H_DIRECTION (1 << 0)
#define V_DIRECTION (1 << 2)
#define COLOR_EXPAND (1 << 6)
#define CSC_ENABLE (1 << 18)
#define WIN_ENABLE (1 << 30)
#define DC_WIN_COLOR_DEPTH 0x703
#define WIN_COLOR_DEPTH_P1 0x0
#define WIN_COLOR_DEPTH_P2 0x1
#define WIN_COLOR_DEPTH_P4 0x2
#define WIN_COLOR_DEPTH_P8 0x3
#define WIN_COLOR_DEPTH_B4G4R4A4 0x4
#define WIN_COLOR_DEPTH_B5G5R5A 0x5
#define WIN_COLOR_DEPTH_B5G6R5 0x6
#define WIN_COLOR_DEPTH_AB5G5R5 0x7
#define WIN_COLOR_DEPTH_B8G8R8A8 0xC
#define WIN_COLOR_DEPTH_R8G8B8A8 0xD
#define WIN_COLOR_DEPTH_B6x2G6x2R6x2A8 0xE
#define WIN_COLOR_DEPTH_R6x2G6x2B6x2A8 0xF
#define WIN_COLOR_DEPTH_YCbCr422 0x10
#define WIN_COLOR_DEPTH_YUV422 0x11
#define WIN_COLOR_DEPTH_YCbCr420P 0x12
#define WIN_COLOR_DEPTH_YUV420P 0x13
#define WIN_COLOR_DEPTH_YCbCr422P 0x14
#define WIN_COLOR_DEPTH_YUV422P 0x15
#define WIN_COLOR_DEPTH_YCbCr422R 0x16
#define WIN_COLOR_DEPTH_YUV422R 0x17
#define WIN_COLOR_DEPTH_YCbCr422RA 0x18
#define WIN_COLOR_DEPTH_YUV422RA 0x19
#define DC_WIN_BUFFER_CONTROL 0x702
#define DC_WIN_POSITION 0x704
#define DC_WIN_SIZE 0x705
#define H_SIZE(x) (((x) & 0x1fff) << 0)
#define V_SIZE(x) (((x) & 0x1fff) << 16)
#define DC_WIN_PRESCALED_SIZE 0x706
#define H_PRESCALED_SIZE(x) (((x) & 0x7fff) << 0)
#define V_PRESCALED_SIZE(x) (((x) & 0x1fff) << 16)
#define DC_WIN_H_INITIAL_DDA 0x707
#define DC_WIN_V_INITIAL_DDA 0x708
#define DC_WIN_DDA_INC 0x709
#define H_DDA_INC(x) (((x) & 0xffff) << 0)
#define V_DDA_INC(x) (((x) & 0xffff) << 16)
#define DC_WIN_LINE_STRIDE 0x70A
#define DC_WIN_DV_CONTROL 0x70E
/* The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). */
#define DC_WINBUF_START_ADDR 0x800
#define DC_WINBUF_ADDR_H_OFFSET 0x806
#define DC_WINBUF_ADDR_V_OFFSET 0x808
#define DC_WINBUF_SURFACE_KIND 0x80B
/* Display serial interface registers. */
#define DSI_RD_DATA 0x9
#define DSI_WR_DATA 0xA
#define DSI_POWER_CONTROL 0xB
#define DSI_POWER_CONTROL_ENABLE 1
#define DSI_INT_ENABLE 0xC
#define DSI_INT_STATUS 0xD
#define DSI_INT_MASK 0xE
#define DSI_HOST_CONTROL 0xF
#define DSI_HOST_CONTROL_FIFO_RESET (1 << 21)
#define DSI_HOST_CONTROL_CRC_RESET (1 << 20)
#define DSI_HOST_CONTROL_TX_TRIG_SOL (0 << 12)
#define DSI_HOST_CONTROL_TX_TRIG_FIFO (1 << 12)
#define DSI_HOST_CONTROL_TX_TRIG_HOST (2 << 12)
#define DSI_HOST_CONTROL_RAW (1 << 6)
#define DSI_HOST_CONTROL_HS (1 << 5)
#define DSI_HOST_CONTROL_FIFO_SEL (1 << 4)
#define DSI_HOST_CONTROL_IMM_BTA (1 << 3)
#define DSI_HOST_CONTROL_PKT_BTA (1 << 2)
#define DSI_HOST_CONTROL_CS (1 << 1)
#define DSI_HOST_CONTROL_ECC (1 << 0)
#define DSI_CONTROL 0x10
#define DSI_CONTROL_HS_CLK_CTRL (1 << 20)
#define DSI_CONTROL_CHANNEL(c) (((c) & 0x3) << 16)
#define DSI_CONTROL_FORMAT(f) (((f) & 0x3) << 12)
#define DSI_CONTROL_TX_TRIG(x) (((x) & 0x3) << 8)
#define DSI_CONTROL_LANES(n) (((n) & 0x3) << 4)
#define DSI_CONTROL_DCS_ENABLE (1 << 3)
#define DSI_CONTROL_SOURCE(s) (((s) & 0x1) << 2)
#define DSI_CONTROL_VIDEO_ENABLE (1 << 1)
#define DSI_CONTROL_HOST_ENABLE (1 << 0)
#define DSI_SOL_DELAY 0x11
#define DSI_MAX_THRESHOLD 0x12
#define DSI_TRIGGER 0x13
#define DSI_TRIGGER_HOST (1 << 1)
#define DSI_TRIGGER_VIDEO (1 << 0)
#define DSI_TX_CRC 0x14
#define DSI_STATUS 0x15
#define DSI_INIT_SEQ_CONTROL 0x1A
#define DSI_INIT_SEQ_DATA_0 0x1B
#define DSI_INIT_SEQ_DATA_1 0x1C
#define DSI_INIT_SEQ_DATA_2 0x1D
#define DSI_INIT_SEQ_DATA_3 0x1E
#define DSI_PKT_SEQ_0_LO 0x23
#define DSI_PKT_SEQ_0_HI 0x24
#define DSI_PKT_SEQ_1_LO 0x25
#define DSI_PKT_SEQ_1_HI 0x26
#define DSI_PKT_SEQ_2_LO 0x27
#define DSI_PKT_SEQ_2_HI 0x28
#define DSI_PKT_SEQ_3_LO 0x29
#define DSI_PKT_SEQ_3_HI 0x2A
#define DSI_PKT_SEQ_4_LO 0x2B
#define DSI_PKT_SEQ_4_HI 0x2C
#define DSI_PKT_SEQ_5_LO 0x2D
#define DSI_PKT_SEQ_5_HI 0x2E
#define DSI_DCS_CMDS 0x33
#define DSI_PKT_LEN_0_1 0x34
#define DSI_PKT_LEN_2_3 0x35
#define DSI_PKT_LEN_4_5 0x36
#define DSI_PKT_LEN_6_7 0x37
#define DSI_PHY_TIMING_0 0x3C
#define DSI_PHY_TIMING_1 0x3D
#define DSI_PHY_TIMING_2 0x3E
#define DSI_BTA_TIMING 0x3F
#define DSI_TIMEOUT_0 0x44
#define DSI_TIMEOUT_LRX(x) (((x) & 0xffff) << 16)
#define DSI_TIMEOUT_HTX(x) (((x) & 0xffff) << 0)
#define DSI_TIMEOUT_1 0x45
#define DSI_TIMEOUT_PR(x) (((x) & 0xffff) << 16)
#define DSI_TIMEOUT_TA(x) (((x) & 0xffff) << 0)
#define DSI_TO_TALLY 0x46
#define DSI_PAD_CONTROL_0 0x4B
#define DSI_PAD_CONTROL_VS1_PULLDN_CLK (1 << 24)
#define DSI_PAD_CONTROL_VS1_PULLDN(x) (((x) & 0xf) << 16)
#define DSI_PAD_CONTROL_VS1_PDIO_CLK (1 << 8)
#define DSI_PAD_CONTROL_VS1_PDIO(x) (((x) & 0xf) << 0)
#define DSI_PAD_CONTROL_CD 0x4c
#define DSI_VIDEO_MODE_CONTROL 0x4E
#define DSI_PAD_CONTROL_1 0x4F
#define DSI_PAD_CONTROL_2 0x50
#define DSI_PAD_CONTROL_3 0x51
#define DSI_PAD_PREEMP_PD_CLK(x) (((x) & 0x3) << 12)
#define DSI_PAD_PREEMP_PU_CLK(x) (((x) & 0x3) << 8)
#define DSI_PAD_PREEMP_PD(x) (((x) & 0x3) << 4)
#define DSI_PAD_PREEMP_PU(x) (((x) & 0x3) << 0)
#define DSI_PAD_CONTROL_4 0x52
#endif

View File

@ -1,346 +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 <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <vapours/ams_version.h>
#include "car.h"
#include "fuse.h"
#include "pmc.h"
#include "timers.h"
/* Initialize the fuse driver */
void fuse_init(void) {
/* Make all fuse registers visible, disable the private key and disable programming. */
clkrst_enable_fuse_regs(true);
/* fuse_disable_private_key(); */
/* fuse_disable_programming(); */
}
/* Disable access to the private key and set the TZ sticky bit. */
void fuse_disable_private_key(void) {
volatile tegra_fuse_t *fuse = fuse_get_regs();
fuse->FUSE_PRIVATEKEYDISABLE = 0x10;
}
/* Disable all fuse programming. */
void fuse_disable_programming(void) {
volatile tegra_fuse_t *fuse = fuse_get_regs();
fuse->FUSE_DISABLEREGPROGRAM = 1;
}
/* Enable power to the fuse hardware array. */
void fuse_enable_power(void) {
volatile tegra_pmc_t *pmc = pmc_get_regs();
pmc->fuse_control &= ~(0x200); /* Clear PMC_FUSE_CTRL_PS18_LATCH_CLEAR. */
mdelay(1);
pmc->fuse_control |= 0x100; /* Set PMC_FUSE_CTRL_PS18_LATCH_SET. */
mdelay(1);
}
/* Disable power to the fuse hardware array. */
void fuse_disable_power(void) {
volatile tegra_pmc_t *pmc = pmc_get_regs();
pmc->fuse_control &= ~(0x100); /* Clear PMC_FUSE_CTRL_PS18_LATCH_SET. */
mdelay(1);
pmc->fuse_control |= 0x200; /* Set PMC_FUSE_CTRL_PS18_LATCH_CLEAR. */
mdelay(1);
}
/* Wait for the fuse driver to go idle. */
static void fuse_wait_idle(void) {
volatile tegra_fuse_t *fuse = fuse_get_regs();
uint32_t ctrl_val = 0;
/* Wait for STATE_IDLE */
while ((ctrl_val & (0xF0000)) != 0x40000) {
ctrl_val = fuse->FUSE_FUSECTRL;
}
}
/* Read a fuse from the hardware array. */
uint32_t fuse_hw_read(uint32_t addr) {
volatile tegra_fuse_t *fuse = fuse_get_regs();
/* Wait for idle state. */
fuse_wait_idle();
/* Program the target address. */
fuse->FUSE_FUSEADDR = addr;
/* Enable read operation in control register. */
uint32_t ctrl_val = fuse->FUSE_FUSECTRL;
ctrl_val &= ~0x3;
ctrl_val |= 0x1; /* Set READ command. */
fuse->FUSE_FUSECTRL = ctrl_val;
/* Wait for idle state. */
fuse_wait_idle();
return fuse->FUSE_FUSERDATA;
}
/* Write a fuse in the hardware array. */
void fuse_hw_write(uint32_t value, uint32_t addr) {
volatile tegra_fuse_t *fuse = fuse_get_regs();
/* Wait for idle state. */
fuse_wait_idle();
/* Program the target address and value. */
fuse->FUSE_FUSEADDR = addr;
fuse->FUSE_FUSEWDATA = value;
/* Enable write operation in control register. */
uint32_t ctrl_val = fuse->FUSE_FUSECTRL;
ctrl_val &= ~0x3;
ctrl_val |= 0x2; /* Set WRITE command. */
fuse->FUSE_FUSECTRL = ctrl_val;
/* Wait for idle state. */
fuse_wait_idle();
}
/* Sense the fuse hardware array into the fuse cache. */
void fuse_hw_sense(void) {
volatile tegra_fuse_t *fuse = fuse_get_regs();
/* Wait for idle state. */
fuse_wait_idle();
/* Enable sense operation in control register */
uint32_t ctrl_val = fuse->FUSE_FUSECTRL;
ctrl_val &= ~0x3;
ctrl_val |= 0x3; /* Set SENSE_CTRL command */
fuse->FUSE_FUSECTRL = ctrl_val;
/* Wait for idle state. */
fuse_wait_idle();
}
/* Read the SKU info register. */
uint32_t fuse_get_sku_info(void) {
volatile tegra_fuse_chip_common_t *fuse_chip = fuse_chip_common_get_regs();
return fuse_chip->FUSE_SKU_INFO;
}
/* Read the bootrom patch version. */
uint32_t fuse_get_bootrom_patch_version(void) {
volatile tegra_fuse_chip_common_t *fuse_chip = fuse_chip_common_get_regs();
return fuse_chip->FUSE_SOC_SPEEDO_1_CALIB;
}
/* Read a spare bit register. */
uint32_t fuse_get_spare_bit(uint32_t index) {
uint32_t soc_type = fuse_get_soc_type();
if (soc_type == 0) {
if (index < 32) {
volatile tegra_fuse_chip_erista_t *fuse_chip = fuse_chip_erista_get_regs();
return fuse_chip->FUSE_SPARE_BIT[index];
}
} else if (soc_type == 1) {
if (index < 30) {
volatile tegra_fuse_chip_mariko_t *fuse_chip = fuse_chip_mariko_get_regs();
return fuse_chip->FUSE_SPARE_BIT[index];
}
}
return 0;
}
/* Read a reserved ODM register. */
uint32_t fuse_get_reserved_odm(uint32_t index) {
if (index < 8) {
volatile tegra_fuse_chip_common_t *fuse_chip = fuse_chip_common_get_regs();
return fuse_chip->FUSE_RESERVED_ODM0[index];
} else {
uint32_t soc_type = fuse_get_soc_type();
if (soc_type == 1) {
volatile tegra_fuse_chip_mariko_t *fuse_chip = fuse_chip_mariko_get_regs();
if (index < 22) {
return fuse_chip->FUSE_RESERVED_ODM8[index - 8];
} else if (index < 25) {
return fuse_chip->FUSE_RESERVED_ODM22[index - 22];
} else if (index < 26) {
return fuse_chip->FUSE_RESERVED_ODM25;
} else if (index < 29) {
return fuse_chip->FUSE_RESERVED_ODM26[index - 26];
} else if (index < 30) {
return fuse_chip->FUSE_RESERVED_ODM29;
}
}
}
return 0;
}
/* Get the DramId. */
uint32_t fuse_get_dram_id(void) {
return ((fuse_get_reserved_odm(4) >> 3) & 0x1F);
}
/* Derive the DeviceId. */
uint64_t fuse_get_device_id(void) {
volatile tegra_fuse_chip_common_t *fuse_chip = fuse_chip_common_get_regs();
uint64_t device_id = 0;
uint64_t y_coord = fuse_chip->FUSE_OPT_Y_COORDINATE & 0x1FF;
uint64_t x_coord = fuse_chip->FUSE_OPT_X_COORDINATE & 0x1FF;
uint64_t wafer_id = fuse_chip->FUSE_OPT_WAFER_ID & 0x3F;
uint32_t lot_code = fuse_chip->FUSE_OPT_LOT_CODE_0;
uint64_t fab_code = fuse_chip->FUSE_OPT_FAB_CODE & 0x3F;
uint64_t derived_lot_code = 0;
for (unsigned int i = 0; i < 5; i++) {
derived_lot_code = (derived_lot_code * 0x24) + ((lot_code >> (24 - 6*i)) & 0x3F);
}
derived_lot_code &= 0x03FFFFFF;
device_id |= y_coord << 0;
device_id |= x_coord << 9;
device_id |= wafer_id << 18;
device_id |= derived_lot_code << 24;
device_id |= fab_code << 50;
return device_id;
}
/* Derive the HardwareType with firmware specific checks. */
uint32_t fuse_get_hardware_type_with_firmware_check(uint32_t target_firmware) {
uint32_t fuse_reserved_odm4 = fuse_get_reserved_odm(4);
uint32_t hardware_type = (((fuse_reserved_odm4 >> 7) & 2) | ((fuse_reserved_odm4 >> 2) & 1));
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
volatile tegra_fuse_chip_common_t *fuse_chip = fuse_chip_common_get_regs();
uint32_t fuse_spare_bit9 = (fuse_chip->FUSE_SPARE_BIT[9] & 1);
switch (hardware_type) {
case 0x00: return (fuse_spare_bit9 == 0) ? 0 : 3;
case 0x01: return 0; /* HardwareType_Icosa */
case 0x02: return 1; /* HardwareType_Copper */
default: return 3; /* HardwareType_Undefined */
}
} else {
hardware_type |= ((fuse_reserved_odm4 >> 14) & 0x3C);
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_7_0_0) {
switch (hardware_type) {
case 0x01: return 0; /* HardwareType_Icosa */
case 0x02: return 1; /* HardwareType_Copper */
case 0x04: return 3; /* HardwareType_Iowa */
default: return 4; /* HardwareType_Undefined */
}
} else {
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_10_0_0) {
switch (hardware_type) {
case 0x01: return 0; /* HardwareType_Icosa */
case 0x02: return 4; /* HardwareType_Calcio */
case 0x04: return 3; /* HardwareType_Iowa */
case 0x08: return 2; /* HardwareType_Hoag */
default: return 0xF; /* HardwareType_Undefined */
}
} else {
switch (hardware_type) {
case 0x01: return 0; /* HardwareType_Icosa */
case 0x02: return 4; /* HardwareType_Calcio */
case 0x04: return 3; /* HardwareType_Iowa */
case 0x08: return 2; /* HardwareType_Hoag */
case 0x10: return 5; /* HardwareType_Five */
default: return 0xF; /* HardwareType_Undefined */
}
}
}
}
}
/* Derive the HardwareType. */
uint32_t fuse_get_hardware_type(void) {
return fuse_get_hardware_type_with_firmware_check(ATMOSPHERE_TARGET_FIRMWARE_CURRENT);
}
/* Derive the HardwareState. */
uint32_t fuse_get_hardware_state(void) {
uint32_t fuse_reserved_odm4 = fuse_get_reserved_odm(4);
uint32_t hardware_state = (((fuse_reserved_odm4 >> 7) & 4) | (fuse_reserved_odm4 & 3));
switch (hardware_state) {
case 0x03: return 0; /* HardwareState_Development */
case 0x04: return 1; /* HardwareState_Production */
default: return 2; /* HardwareState_Undefined */
}
}
/* Derive the 16-byte HardwareInfo and copy to output buffer. */
void fuse_get_hardware_info(void *dst) {
volatile tegra_fuse_chip_common_t *fuse_chip = fuse_chip_common_get_regs();
uint32_t hw_info[0x4];
uint32_t ops_reserved = fuse_chip->FUSE_OPT_OPS_RESERVED & 0x3F;
uint32_t y_coord = fuse_chip->FUSE_OPT_Y_COORDINATE & 0x1FF;
uint32_t x_coord = fuse_chip->FUSE_OPT_X_COORDINATE & 0x1FF;
uint32_t wafer_id = fuse_chip->FUSE_OPT_WAFER_ID & 0x3F;
uint32_t lot_code_0 = fuse_chip->FUSE_OPT_LOT_CODE_0;
uint32_t lot_code_1 = fuse_chip->FUSE_OPT_LOT_CODE_1 & 0x0FFFFFFF;
uint32_t fab_code = fuse_chip->FUSE_OPT_FAB_CODE & 0x3F;
uint32_t vendor_code = fuse_chip->FUSE_OPT_VENDOR_CODE & 0xF;
/* Hardware Info = OPS_RESERVED || Y_COORD || X_COORD || WAFER_ID || LOT_CODE || FAB_CODE || VENDOR_ID */
hw_info[0] = (uint32_t)((lot_code_1 << 30) | (wafer_id << 24) | (x_coord << 15) | (y_coord << 6) | (ops_reserved));
hw_info[1] = (uint32_t)((lot_code_0 << 26) | (lot_code_1 >> 2));
hw_info[2] = (uint32_t)((fab_code << 26) | (lot_code_0 >> 6));
hw_info[3] = (uint32_t)(vendor_code);
memcpy(dst, hw_info, 0x10);
}
/* Check if have a new ODM fuse format. */
bool fuse_is_new_format(void) {
return ((fuse_get_reserved_odm(4) & 0x800) && (fuse_get_reserved_odm(0) == 0x8E61ECAE) && (fuse_get_reserved_odm(1) == 0xF2BA3BB2));
}
/* Get the DeviceUniqueKeyGeneration. */
uint32_t fuse_get_device_unique_key_generation(void) {
if (fuse_is_new_format()) {
return (fuse_get_reserved_odm(2) & 0x1F);
} else {
return 0;
}
}
/* Get the SocType from the HardwareType. */
uint32_t fuse_get_soc_type(void) {
switch (fuse_get_hardware_type()) {
case 0:
case 1:
return 0; /* SocType_Erista */
case 3:
case 2:
case 4:
case 5:
return 1; /* SocType_Mariko */
default:
return 0xF; /* SocType_Undefined */
}
}
/* Get the Regulator type. */
uint32_t fuse_get_regulator(void) {
if (fuse_get_soc_type() == 1) {
return ((fuse_get_reserved_odm(28) & 1) + 1); /* Regulator_Mariko_Max77812_A or Regulator_Mariko_Max77812_B */
} else {
return 0; /* Regulator_Erista_Max77621 */
}
}

View File

@ -1,484 +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/>.
*/
#ifndef FUSEE_FUSE_H
#define FUSEE_FUSE_H
#define FUSE_BASE 0x7000F800
#define FUSE_CHIP_BASE (FUSE_BASE + 0x98)
#define MAKE_FUSE_REG(n) MAKE_REG32(FUSE_BASE + n)
#define MAKE_FUSE_CHIP_REG(n) MAKE_REG32(FUSE_CHIP_BASE + n)
typedef struct {
uint32_t FUSE_FUSECTRL;
uint32_t FUSE_FUSEADDR;
uint32_t FUSE_FUSERDATA;
uint32_t FUSE_FUSEWDATA;
uint32_t FUSE_FUSETIME_RD1;
uint32_t FUSE_FUSETIME_RD2;
uint32_t FUSE_FUSETIME_PGM1;
uint32_t FUSE_FUSETIME_PGM2;
uint32_t FUSE_PRIV2INTFC_START;
uint32_t FUSE_FUSEBYPASS;
uint32_t FUSE_PRIVATEKEYDISABLE;
uint32_t FUSE_DISABLEREGPROGRAM;
uint32_t FUSE_WRITE_ACCESS_SW;
uint32_t FUSE_PWR_GOOD_SW;
uint32_t _0x38;
uint32_t FUSE_PRIV2RESHIFT;
uint32_t _0x40[0x3];
uint32_t FUSE_FUSETIME_RD3;
uint32_t _0x50[0xC];
uint32_t FUSE_PRIVATE_KEY0_NONZERO;
uint32_t FUSE_PRIVATE_KEY1_NONZERO;
uint32_t FUSE_PRIVATE_KEY2_NONZERO;
uint32_t FUSE_PRIVATE_KEY3_NONZERO;
uint32_t FUSE_PRIVATE_KEY4_NONZERO;
uint32_t _0x94;
} tegra_fuse_t;
typedef struct {
uint32_t _0x98[0x1A];
uint32_t FUSE_PRODUCTION_MODE;
uint32_t FUSE_JTAG_SECUREID_VALID;
uint32_t FUSE_ODM_LOCK;
uint32_t FUSE_OPT_OPENGL_EN;
uint32_t FUSE_SKU_INFO;
uint32_t FUSE_CPU_SPEEDO_0_CALIB;
uint32_t FUSE_CPU_IDDQ_CALIB;
uint32_t _0x11C[0x3];
uint32_t FUSE_OPT_FT_REV;
uint32_t FUSE_CPU_SPEEDO_1_CALIB;
uint32_t FUSE_CPU_SPEEDO_2_CALIB;
uint32_t FUSE_SOC_SPEEDO_0_CALIB;
uint32_t FUSE_SOC_SPEEDO_1_CALIB;
uint32_t FUSE_SOC_SPEEDO_2_CALIB;
uint32_t FUSE_SOC_IDDQ_CALIB;
uint32_t _0x144;
uint32_t FUSE_FA;
uint32_t FUSE_RESERVED_PRODUCTION;
uint32_t FUSE_HDMI_LANE0_CALIB;
uint32_t FUSE_HDMI_LANE1_CALIB;
uint32_t FUSE_HDMI_LANE2_CALIB;
uint32_t FUSE_HDMI_LANE3_CALIB;
uint32_t FUSE_ENCRYPTION_RATE;
uint32_t FUSE_PUBLIC_KEY[0x8];
uint32_t FUSE_TSENSOR1_CALIB;
uint32_t FUSE_TSENSOR2_CALIB;
uint32_t _0x18C;
uint32_t FUSE_OPT_CP_REV;
uint32_t FUSE_OPT_PFG;
uint32_t FUSE_TSENSOR0_CALIB;
uint32_t FUSE_FIRST_BOOTROM_PATCH_SIZE;
uint32_t FUSE_SECURITY_MODE;
uint32_t FUSE_PRIVATE_KEY[0x5];
uint32_t FUSE_ARM_JTAG_DIS;
uint32_t FUSE_BOOT_DEVICE_INFO;
uint32_t FUSE_RESERVED_SW;
uint32_t FUSE_OPT_VP9_DISABLE;
uint32_t FUSE_RESERVED_ODM0[0x8];
uint32_t FUSE_OBS_DIS;
uint32_t _0x1EC;
uint32_t FUSE_USB_CALIB;
uint32_t FUSE_SKU_DIRECT_CONFIG;
uint32_t FUSE_KFUSE_PRIVKEY_CTRL;
uint32_t FUSE_PACKAGE_INFO;
uint32_t FUSE_OPT_VENDOR_CODE;
uint32_t FUSE_OPT_FAB_CODE;
uint32_t FUSE_OPT_LOT_CODE_0;
uint32_t FUSE_OPT_LOT_CODE_1;
uint32_t FUSE_OPT_WAFER_ID;
uint32_t FUSE_OPT_X_COORDINATE;
uint32_t FUSE_OPT_Y_COORDINATE;
uint32_t FUSE_OPT_SEC_DEBUG_EN;
uint32_t FUSE_OPT_OPS_RESERVED;
uint32_t _0x224;
uint32_t FUSE_GPU_IDDQ_CALIB;
uint32_t FUSE_TSENSOR3_CALIB;
uint32_t FUSE_CLOCK_BOUNDOUT0;
uint32_t FUSE_CLOCK_BOUNDOUT1;
uint32_t _0x238[0x3];
uint32_t FUSE_OPT_SAMPLE_TYPE;
uint32_t FUSE_OPT_SUBREVISION;
uint32_t FUSE_OPT_SW_RESERVED_0;
uint32_t FUSE_OPT_SW_RESERVED_1;
uint32_t FUSE_TSENSOR4_CALIB;
uint32_t FUSE_TSENSOR5_CALIB;
uint32_t FUSE_TSENSOR6_CALIB;
uint32_t FUSE_TSENSOR7_CALIB;
uint32_t FUSE_OPT_PRIV_SEC_EN;
uint32_t _0x268[0x5];
uint32_t FUSE_FUSE2TSEC_DEBUG_DISABLE;
uint32_t FUSE_TSENSOR_COMMON;
uint32_t FUSE_OPT_CP_BIN;
uint32_t FUSE_OPT_GPU_DISABLE;
uint32_t FUSE_OPT_FT_BIN;
uint32_t FUSE_OPT_DONE_MAP;
uint32_t _0x294;
uint32_t FUSE_APB2JTAG_DISABLE;
uint32_t FUSE_ODM_INFO;
uint32_t _0x2A0[0x2];
uint32_t FUSE_ARM_CRYPT_DE_FEATURE;
uint32_t _0x2AC[0x5];
uint32_t FUSE_WOA_SKU_FLAG;
uint32_t FUSE_ECO_RESERVE_1;
uint32_t FUSE_GCPLEX_CONFIG_FUSE;
uint32_t FUSE_PRODUCTION_MONTH;
uint32_t FUSE_RAM_REPAIR_INDICATOR;
uint32_t FUSE_TSENSOR9_CALIB;
uint32_t _0x2D8;
uint32_t FUSE_VMIN_CALIBRATION;
uint32_t FUSE_AGING_SENSOR_CALIBRATION;
uint32_t FUSE_DEBUG_AUTHENTICATION;
uint32_t FUSE_SECURE_PROVISION_INDEX;
uint32_t FUSE_SECURE_PROVISION_INFO;
uint32_t FUSE_OPT_GPU_DISABLE_CP1;
uint32_t FUSE_SPARE_ENDIS;
uint32_t FUSE_ECO_RESERVE_0;
uint32_t _0x2FC[0x2];
uint32_t FUSE_RESERVED_CALIB0;
uint32_t FUSE_RESERVED_CALIB1;
uint32_t FUSE_OPT_GPU_TPC0_DISABLE;
uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP1;
uint32_t FUSE_OPT_CPU_DISABLE;
uint32_t FUSE_OPT_CPU_DISABLE_CP1;
uint32_t FUSE_TSENSOR10_CALIB;
uint32_t FUSE_TSENSOR10_CALIB_AUX;
uint32_t _0x324[0x5];
uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP2;
uint32_t FUSE_OPT_GPU_TPC1_DISABLE;
uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP1;
uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP2;
uint32_t FUSE_OPT_CPU_DISABLE_CP2;
uint32_t FUSE_OPT_GPU_DISABLE_CP2;
uint32_t FUSE_USB_CALIB_EXT;
uint32_t FUSE_RESERVED_FIELD;
uint32_t _0x358[0x9];
uint32_t FUSE_SPARE_REALIGNMENT_REG;
uint32_t FUSE_SPARE_BIT[0x20];
} tegra_fuse_chip_common_t;
typedef struct {
uint32_t _0x98[0x1A];
uint32_t FUSE_PRODUCTION_MODE;
uint32_t FUSE_JTAG_SECUREID_VALID;
uint32_t FUSE_ODM_LOCK;
uint32_t FUSE_OPT_OPENGL_EN;
uint32_t FUSE_SKU_INFO;
uint32_t FUSE_CPU_SPEEDO_0_CALIB;
uint32_t FUSE_CPU_IDDQ_CALIB;
uint32_t _0x11C[0x3];
uint32_t FUSE_OPT_FT_REV;
uint32_t FUSE_CPU_SPEEDO_1_CALIB;
uint32_t FUSE_CPU_SPEEDO_2_CALIB;
uint32_t FUSE_SOC_SPEEDO_0_CALIB;
uint32_t FUSE_SOC_SPEEDO_1_CALIB;
uint32_t FUSE_SOC_SPEEDO_2_CALIB;
uint32_t FUSE_SOC_IDDQ_CALIB;
uint32_t _0x144;
uint32_t FUSE_FA;
uint32_t FUSE_RESERVED_PRODUCTION;
uint32_t FUSE_HDMI_LANE0_CALIB;
uint32_t FUSE_HDMI_LANE1_CALIB;
uint32_t FUSE_HDMI_LANE2_CALIB;
uint32_t FUSE_HDMI_LANE3_CALIB;
uint32_t FUSE_ENCRYPTION_RATE;
uint32_t FUSE_PUBLIC_KEY[0x8];
uint32_t FUSE_TSENSOR1_CALIB;
uint32_t FUSE_TSENSOR2_CALIB;
uint32_t _0x18C;
uint32_t FUSE_OPT_CP_REV;
uint32_t FUSE_OPT_PFG;
uint32_t FUSE_TSENSOR0_CALIB;
uint32_t FUSE_FIRST_BOOTROM_PATCH_SIZE;
uint32_t FUSE_SECURITY_MODE;
uint32_t FUSE_PRIVATE_KEY[0x5];
uint32_t FUSE_ARM_JTAG_DIS;
uint32_t FUSE_BOOT_DEVICE_INFO;
uint32_t FUSE_RESERVED_SW;
uint32_t FUSE_OPT_VP9_DISABLE;
uint32_t FUSE_RESERVED_ODM0[0x8];
uint32_t FUSE_OBS_DIS;
uint32_t _0x1EC;
uint32_t FUSE_USB_CALIB;
uint32_t FUSE_SKU_DIRECT_CONFIG;
uint32_t FUSE_KFUSE_PRIVKEY_CTRL;
uint32_t FUSE_PACKAGE_INFO;
uint32_t FUSE_OPT_VENDOR_CODE;
uint32_t FUSE_OPT_FAB_CODE;
uint32_t FUSE_OPT_LOT_CODE_0;
uint32_t FUSE_OPT_LOT_CODE_1;
uint32_t FUSE_OPT_WAFER_ID;
uint32_t FUSE_OPT_X_COORDINATE;
uint32_t FUSE_OPT_Y_COORDINATE;
uint32_t FUSE_OPT_SEC_DEBUG_EN;
uint32_t FUSE_OPT_OPS_RESERVED;
uint32_t FUSE_SATA_CALIB; /* Erista only. */
uint32_t FUSE_GPU_IDDQ_CALIB;
uint32_t FUSE_TSENSOR3_CALIB;
uint32_t FUSE_CLOCK_BOUNDOUT0;
uint32_t FUSE_CLOCK_BOUNDOUT1;
uint32_t _0x238[0x3];
uint32_t FUSE_OPT_SAMPLE_TYPE;
uint32_t FUSE_OPT_SUBREVISION;
uint32_t FUSE_OPT_SW_RESERVED_0;
uint32_t FUSE_OPT_SW_RESERVED_1;
uint32_t FUSE_TSENSOR4_CALIB;
uint32_t FUSE_TSENSOR5_CALIB;
uint32_t FUSE_TSENSOR6_CALIB;
uint32_t FUSE_TSENSOR7_CALIB;
uint32_t FUSE_OPT_PRIV_SEC_EN;
uint32_t FUSE_PKC_DISABLE; /* Erista only. */
uint32_t _0x26C[0x4];
uint32_t FUSE_FUSE2TSEC_DEBUG_DISABLE;
uint32_t FUSE_TSENSOR_COMMON;
uint32_t FUSE_OPT_CP_BIN;
uint32_t FUSE_OPT_GPU_DISABLE;
uint32_t FUSE_OPT_FT_BIN;
uint32_t FUSE_OPT_DONE_MAP;
uint32_t _0x294;
uint32_t FUSE_APB2JTAG_DISABLE;
uint32_t FUSE_ODM_INFO;
uint32_t _0x2A0[0x2];
uint32_t FUSE_ARM_CRYPT_DE_FEATURE;
uint32_t _0x2AC[0x5];
uint32_t FUSE_WOA_SKU_FLAG;
uint32_t FUSE_ECO_RESERVE_1;
uint32_t FUSE_GCPLEX_CONFIG_FUSE;
uint32_t FUSE_PRODUCTION_MONTH;
uint32_t FUSE_RAM_REPAIR_INDICATOR;
uint32_t FUSE_TSENSOR9_CALIB;
uint32_t _0x2D8;
uint32_t FUSE_VMIN_CALIBRATION;
uint32_t FUSE_AGING_SENSOR_CALIBRATION;
uint32_t FUSE_DEBUG_AUTHENTICATION;
uint32_t FUSE_SECURE_PROVISION_INDEX;
uint32_t FUSE_SECURE_PROVISION_INFO;
uint32_t FUSE_OPT_GPU_DISABLE_CP1;
uint32_t FUSE_SPARE_ENDIS;
uint32_t FUSE_ECO_RESERVE_0;
uint32_t _0x2FC[0x2];
uint32_t FUSE_RESERVED_CALIB0;
uint32_t FUSE_RESERVED_CALIB1;
uint32_t FUSE_OPT_GPU_TPC0_DISABLE;
uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP1;
uint32_t FUSE_OPT_CPU_DISABLE;
uint32_t FUSE_OPT_CPU_DISABLE_CP1;
uint32_t FUSE_TSENSOR10_CALIB;
uint32_t FUSE_TSENSOR10_CALIB_AUX;
uint32_t FUSE_OPT_RAM_SVOP_DP; /* Erista only. */
uint32_t FUSE_OPT_RAM_SVOP_PDP; /* Erista only. */
uint32_t FUSE_OPT_RAM_SVOP_REG; /* Erista only. */
uint32_t FUSE_OPT_RAM_SVOP_SP; /* Erista only. */
uint32_t FUSE_OPT_RAM_SVOP_SMPDP; /* Erista only. */
uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP2;
uint32_t FUSE_OPT_GPU_TPC1_DISABLE;
uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP1;
uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP2;
uint32_t FUSE_OPT_CPU_DISABLE_CP2;
uint32_t FUSE_OPT_GPU_DISABLE_CP2;
uint32_t FUSE_USB_CALIB_EXT;
uint32_t FUSE_RESERVED_FIELD;
uint32_t _0x358[0x9];
uint32_t FUSE_SPARE_REALIGNMENT_REG;
uint32_t FUSE_SPARE_BIT[0x20];
} tegra_fuse_chip_erista_t;
typedef struct {
uint32_t FUSE_RESERVED_ODM8[0xE]; /* Mariko only. */
uint32_t FUSE_KEK[0x4]; /* Mariko only. */
uint32_t FUSE_BEK[0x4]; /* Mariko only. */
uint32_t _0xF0; /* Mariko only. */
uint32_t _0xF4; /* Mariko only. */
uint32_t _0xF8; /* Mariko only. */
uint32_t _0xFC; /* Mariko only. */
uint32_t FUSE_PRODUCTION_MODE;
uint32_t FUSE_JTAG_SECUREID_VALID;
uint32_t FUSE_ODM_LOCK;
uint32_t FUSE_OPT_OPENGL_EN;
uint32_t FUSE_SKU_INFO;
uint32_t FUSE_CPU_SPEEDO_0_CALIB;
uint32_t FUSE_CPU_IDDQ_CALIB;
uint32_t FUSE_RESERVED_ODM22[0x3]; /* Mariko only. */
uint32_t FUSE_OPT_FT_REV;
uint32_t FUSE_CPU_SPEEDO_1_CALIB;
uint32_t FUSE_CPU_SPEEDO_2_CALIB;
uint32_t FUSE_SOC_SPEEDO_0_CALIB;
uint32_t FUSE_SOC_SPEEDO_1_CALIB;
uint32_t FUSE_SOC_SPEEDO_2_CALIB;
uint32_t FUSE_SOC_IDDQ_CALIB;
uint32_t FUSE_RESERVED_ODM25; /* Mariko only. */
uint32_t FUSE_FA;
uint32_t FUSE_RESERVED_PRODUCTION;
uint32_t FUSE_HDMI_LANE0_CALIB;
uint32_t FUSE_HDMI_LANE1_CALIB;
uint32_t FUSE_HDMI_LANE2_CALIB;
uint32_t FUSE_HDMI_LANE3_CALIB;
uint32_t FUSE_ENCRYPTION_RATE;
uint32_t FUSE_PUBLIC_KEY[0x8];
uint32_t FUSE_TSENSOR1_CALIB;
uint32_t FUSE_TSENSOR2_CALIB;
uint32_t FUSE_OPT_SECURE_SCC_DIS; /* Mariko only. */
uint32_t FUSE_OPT_CP_REV;
uint32_t FUSE_OPT_PFG;
uint32_t FUSE_TSENSOR0_CALIB;
uint32_t FUSE_FIRST_BOOTROM_PATCH_SIZE;
uint32_t FUSE_SECURITY_MODE;
uint32_t FUSE_PRIVATE_KEY[0x5];
uint32_t FUSE_ARM_JTAG_DIS;
uint32_t FUSE_BOOT_DEVICE_INFO;
uint32_t FUSE_RESERVED_SW;
uint32_t FUSE_OPT_VP9_DISABLE;
uint32_t FUSE_RESERVED_ODM0[0x8];
uint32_t FUSE_OBS_DIS;
uint32_t _0x1EC; /* Mariko only. */
uint32_t FUSE_USB_CALIB;
uint32_t FUSE_SKU_DIRECT_CONFIG;
uint32_t FUSE_KFUSE_PRIVKEY_CTRL;
uint32_t FUSE_PACKAGE_INFO;
uint32_t FUSE_OPT_VENDOR_CODE;
uint32_t FUSE_OPT_FAB_CODE;
uint32_t FUSE_OPT_LOT_CODE_0;
uint32_t FUSE_OPT_LOT_CODE_1;
uint32_t FUSE_OPT_WAFER_ID;
uint32_t FUSE_OPT_X_COORDINATE;
uint32_t FUSE_OPT_Y_COORDINATE;
uint32_t FUSE_OPT_SEC_DEBUG_EN;
uint32_t FUSE_OPT_OPS_RESERVED;
uint32_t _0x224; /* Mariko only. */
uint32_t FUSE_GPU_IDDQ_CALIB;
uint32_t FUSE_TSENSOR3_CALIB;
uint32_t FUSE_CLOCK_BOUNDOUT0;
uint32_t FUSE_CLOCK_BOUNDOUT1;
uint32_t FUSE_RESERVED_ODM26[0x3]; /* Mariko only. */
uint32_t FUSE_OPT_SAMPLE_TYPE;
uint32_t FUSE_OPT_SUBREVISION;
uint32_t FUSE_OPT_SW_RESERVED_0;
uint32_t FUSE_OPT_SW_RESERVED_1;
uint32_t FUSE_TSENSOR4_CALIB;
uint32_t FUSE_TSENSOR5_CALIB;
uint32_t FUSE_TSENSOR6_CALIB;
uint32_t FUSE_TSENSOR7_CALIB;
uint32_t FUSE_OPT_PRIV_SEC_EN;
uint32_t FUSE_BOOT_SECURITY_INFO; /* Mariko only. */
uint32_t _0x26C; /* Mariko only. */
uint32_t _0x270; /* Mariko only. */
uint32_t _0x274; /* Mariko only. */
uint32_t _0x278; /* Mariko only. */
uint32_t FUSE_FUSE2TSEC_DEBUG_DISABLE;
uint32_t FUSE_TSENSOR_COMMON;
uint32_t FUSE_OPT_CP_BIN;
uint32_t FUSE_OPT_GPU_DISABLE;
uint32_t FUSE_OPT_FT_BIN;
uint32_t FUSE_OPT_DONE_MAP;
uint32_t FUSE_RESERVED_ODM29; /* Mariko only. */
uint32_t FUSE_APB2JTAG_DISABLE;
uint32_t FUSE_ODM_INFO;
uint32_t _0x2A0[0x2];
uint32_t FUSE_ARM_CRYPT_DE_FEATURE;
uint32_t _0x2AC;
uint32_t _0x2B0; /* Mariko only. */
uint32_t _0x2B4; /* Mariko only. */
uint32_t _0x2B8; /* Mariko only. */
uint32_t _0x2BC; /* Mariko only. */
uint32_t FUSE_WOA_SKU_FLAG;
uint32_t FUSE_ECO_RESERVE_1;
uint32_t FUSE_GCPLEX_CONFIG_FUSE;
uint32_t FUSE_PRODUCTION_MONTH;
uint32_t FUSE_RAM_REPAIR_INDICATOR;
uint32_t FUSE_TSENSOR9_CALIB;
uint32_t _0x2D8;
uint32_t FUSE_VMIN_CALIBRATION;
uint32_t FUSE_AGING_SENSOR_CALIBRATION;
uint32_t FUSE_DEBUG_AUTHENTICATION;
uint32_t FUSE_SECURE_PROVISION_INDEX;
uint32_t FUSE_SECURE_PROVISION_INFO;
uint32_t FUSE_OPT_GPU_DISABLE_CP1;
uint32_t FUSE_SPARE_ENDIS;
uint32_t FUSE_ECO_RESERVE_0;
uint32_t _0x2FC[0x2];
uint32_t FUSE_RESERVED_CALIB0;
uint32_t FUSE_RESERVED_CALIB1;
uint32_t FUSE_OPT_GPU_TPC0_DISABLE;
uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP1;
uint32_t FUSE_OPT_CPU_DISABLE;
uint32_t FUSE_OPT_CPU_DISABLE_CP1;
uint32_t FUSE_TSENSOR10_CALIB;
uint32_t FUSE_TSENSOR10_CALIB_AUX;
uint32_t _0x324; /* Mariko only. */
uint32_t _0x328; /* Mariko only. */
uint32_t _0x32C; /* Mariko only. */
uint32_t _0x330; /* Mariko only. */
uint32_t _0x334; /* Mariko only. */
uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP2;
uint32_t FUSE_OPT_GPU_TPC1_DISABLE;
uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP1;
uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP2;
uint32_t FUSE_OPT_CPU_DISABLE_CP2;
uint32_t FUSE_OPT_GPU_DISABLE_CP2;
uint32_t FUSE_USB_CALIB_EXT;
uint32_t FUSE_RESERVED_FIELD;
uint32_t _0x358[0x9];
uint32_t FUSE_SPARE_REALIGNMENT_REG;
uint32_t FUSE_SPARE_BIT[0x1E];
} tegra_fuse_chip_mariko_t;
static inline volatile tegra_fuse_t *fuse_get_regs(void)
{
return (volatile tegra_fuse_t *)FUSE_BASE;
}
static inline volatile tegra_fuse_chip_common_t *fuse_chip_common_get_regs(void)
{
return (volatile tegra_fuse_chip_common_t *)FUSE_CHIP_BASE;
}
static inline volatile tegra_fuse_chip_erista_t *fuse_chip_erista_get_regs(void)
{
return (volatile tegra_fuse_chip_erista_t *)FUSE_CHIP_BASE;
}
static inline volatile tegra_fuse_chip_mariko_t *fuse_chip_mariko_get_regs(void)
{
return (volatile tegra_fuse_chip_mariko_t *)FUSE_CHIP_BASE;
}
void fuse_init(void);
void fuse_disable_programming(void);
void fuse_disable_private_key(void);
void fuse_enable_power(void);
void fuse_disable_power(void);
uint32_t fuse_get_sku_info(void);
uint32_t fuse_get_spare_bit(uint32_t index);
uint32_t fuse_get_reserved_odm(uint32_t index);
uint32_t fuse_get_bootrom_patch_version(void);
uint64_t fuse_get_device_id(void);
uint32_t fuse_get_dram_id(void);
uint32_t fuse_get_hardware_type_with_firmware_check(uint32_t target_firmware);
uint32_t fuse_get_hardware_type(void);
uint32_t fuse_get_retail_type(void);
void fuse_get_hardware_info(void *dst);
bool fuse_is_new_format(void);
uint32_t fuse_get_device_unique_key_generation(void);
uint32_t fuse_get_soc_type(void);
uint32_t fuse_get_regulator(void);
uint32_t fuse_hw_read(uint32_t addr);
void fuse_hw_write(uint32_t value, uint32_t addr);
void fuse_hw_sense(void);
#endif

View File

@ -1,78 +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 <string.h>
#include <stdint.h>
#include <errno.h>
#include "gpio.h"
#include "utils.h"
/* Set GPIO's value. */
static void gpio_register_set(uint32_t pin, bool do_set, uint32_t offset) {
volatile tegra_gpio_t *gpio = gpio_get_regs();
/* Retrieve the register set that corresponds to the given pin and offset. */
volatile uint32_t *cluster = (uint32_t *)((uintptr_t)&gpio->bank[(pin >> GPIO_BANK_SHIFT)] + offset);
/* Figure out the offset into the cluster, and the mask to be used. */
uint32_t port = ((pin >> GPIO_PORT_SHIFT) & GPIO_PORT_MASK);
uint32_t mask = (1 << (pin & GPIO_PIN_MASK));
/* Set or clear the bit, as appropriate. */
if (do_set)
cluster[port] |= mask;
else
cluster[port] &= ~mask;
/* Dummy read. */
cluster[port];
}
/* Get GPIO's value. */
static bool gpio_register_get(uint32_t pin, uint32_t offset) {
volatile tegra_gpio_t *gpio = gpio_get_regs();
/* Retrieve the register set that corresponds to the given pin and offset. */
volatile uint32_t *cluster = (uint32_t *)((uintptr_t)&gpio->bank[(pin >> GPIO_BANK_SHIFT)] + offset);
/* Figure out the offset into the cluster, and the mask to be used. */
uint32_t port = ((pin >> GPIO_PORT_SHIFT) & GPIO_PORT_MASK);
uint32_t mask = (1 << (pin & GPIO_PIN_MASK));
/* Convert the given value to a boolean. */
return !!(cluster[port] & mask);
}
/* Configure GPIO's mode. */
void gpio_configure_mode(uint32_t pin, uint32_t mode) {
gpio_register_set(pin, mode == GPIO_MODE_GPIO, offsetof(tegra_gpio_bank_t, config));
}
/* Configure GPIO's direction. */
void gpio_configure_direction(uint32_t pin, uint32_t dir) {
gpio_register_set(pin, dir == GPIO_DIRECTION_OUTPUT, offsetof(tegra_gpio_bank_t, direction));
}
/* Write to GPIO. */
void gpio_write(uint32_t pin, uint32_t value) {
gpio_register_set(pin, value == GPIO_LEVEL_HIGH, offsetof(tegra_gpio_bank_t, out));
}
/* Read from GPIO. */
uint32_t gpio_read(uint32_t pin) {
return gpio_register_get(pin, offsetof(tegra_gpio_bank_t, in));
}

View File

@ -1,127 +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/>.
*/
#ifndef FUSEE_GPIO_H
#define FUSEE_GPIO_H
#include <stdint.h>
#define GPIO_BASE 0x6000D000
#define MAKE_GPIO_REG(n) MAKE_REG32(GPIO_BASE + n)
#define TEGRA_GPIO_PORTS 4
#define TEGRA_GPIO_BANKS 8
#define GPIO_BANK_SHIFT 5
#define GPIO_PORT_SHIFT 3
#define GPIO_PORT_MASK 0x03
#define GPIO_PIN_MASK 0x07
typedef enum {
TEGRA_GPIO_PORT_A = 0,
TEGRA_GPIO_PORT_B = 1,
TEGRA_GPIO_PORT_C = 2,
TEGRA_GPIO_PORT_D = 3,
TEGRA_GPIO_PORT_E = 4,
TEGRA_GPIO_PORT_F = 5,
TEGRA_GPIO_PORT_G = 6,
TEGRA_GPIO_PORT_H = 7,
TEGRA_GPIO_PORT_I = 8,
TEGRA_GPIO_PORT_J = 9,
TEGRA_GPIO_PORT_K = 10,
TEGRA_GPIO_PORT_L = 11,
TEGRA_GPIO_PORT_M = 12,
TEGRA_GPIO_PORT_N = 13,
TEGRA_GPIO_PORT_O = 14,
TEGRA_GPIO_PORT_P = 15,
TEGRA_GPIO_PORT_Q = 16,
TEGRA_GPIO_PORT_R = 17,
TEGRA_GPIO_PORT_S = 18,
TEGRA_GPIO_PORT_T = 19,
TEGRA_GPIO_PORT_U = 20,
TEGRA_GPIO_PORT_V = 21,
TEGRA_GPIO_PORT_W = 22,
TEGRA_GPIO_PORT_X = 23,
TEGRA_GPIO_PORT_Y = 24,
TEGRA_GPIO_PORT_Z = 25,
TEGRA_GPIO_PORT_AA = 26,
TEGRA_GPIO_PORT_BB = 27,
TEGRA_GPIO_PORT_CC = 28,
TEGRA_GPIO_PORT_DD = 29,
TEGRA_GPIO_PORT_EE = 30,
TEGRA_GPIO_PORT_FF = 31,
} tegra_gpio_port;
typedef struct {
uint32_t config[TEGRA_GPIO_PORTS];
uint32_t direction[TEGRA_GPIO_PORTS];
uint32_t out[TEGRA_GPIO_PORTS];
uint32_t in[TEGRA_GPIO_PORTS];
uint32_t int_status[TEGRA_GPIO_PORTS];
uint32_t int_enable[TEGRA_GPIO_PORTS];
uint32_t int_level[TEGRA_GPIO_PORTS];
uint32_t int_clear[TEGRA_GPIO_PORTS];
uint32_t masked_config[TEGRA_GPIO_PORTS];
uint32_t masked_dir_out[TEGRA_GPIO_PORTS];
uint32_t masked_out[TEGRA_GPIO_PORTS];
uint32_t masked_in[TEGRA_GPIO_PORTS];
uint32_t masked_int_status[TEGRA_GPIO_PORTS];
uint32_t masked_int_enable[TEGRA_GPIO_PORTS];
uint32_t masked_int_level[TEGRA_GPIO_PORTS];
uint32_t masked_int_clear[TEGRA_GPIO_PORTS];
} tegra_gpio_bank_t;
typedef struct {
tegra_gpio_bank_t bank[TEGRA_GPIO_BANKS];
} tegra_gpio_t;
static inline volatile tegra_gpio_t *gpio_get_regs(void)
{
return (volatile tegra_gpio_t *)GPIO_BASE;
}
#define TEGRA_GPIO(port, offset) \
((TEGRA_GPIO_PORT_##port * 8) + offset)
/* Mode select */
#define GPIO_MODE_SFIO 0
#define GPIO_MODE_GPIO 1
/* Direction */
#define GPIO_DIRECTION_INPUT 0
#define GPIO_DIRECTION_OUTPUT 1
/* Level */
#define GPIO_LEVEL_LOW 0
#define GPIO_LEVEL_HIGH 1
/* Named GPIOs */
#define GPIO_BUTTON_VOL_DOWN TEGRA_GPIO(X, 7)
#define GPIO_BUTTON_VOL_UP TEGRA_GPIO(X, 6)
#define GPIO_MICROSD_CARD_DETECT TEGRA_GPIO(Z, 1)
#define GPIO_MICROSD_WRITE_PROTECT TEGRA_GPIO(Z, 4)
#define GPIO_MICROSD_SUPPLY_ENABLE TEGRA_GPIO(E, 4)
#define GPIO_LCD_BL_P5V TEGRA_GPIO(I, 0)
#define GPIO_LCD_BL_N5V TEGRA_GPIO(I, 1)
#define GPIO_LCD_BL_PWM TEGRA_GPIO(V, 0)
#define GPIO_LCD_BL_EN TEGRA_GPIO(V, 1)
#define GPIO_LCD_BL_RST TEGRA_GPIO(V, 2)
void gpio_configure_mode(uint32_t pin, uint32_t mode);
void gpio_configure_direction(uint32_t pin, uint32_t dir);
void gpio_write(uint32_t pin, uint32_t value);
uint32_t gpio_read(uint32_t pin);
#endif

View File

@ -1,252 +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 "i2c.h"
#include "utils.h"
#include "timers.h"
#include "pinmux.h"
/* Prototypes for internal commands. */
volatile tegra_i2c_t *i2c_get_registers_from_id(I2CDevice id);
void i2c_load_config(volatile tegra_i2c_t *regs);
bool i2c_query(I2CDevice id, uint8_t device, uint8_t r, void *dst, size_t dst_size);
bool i2c_send(I2CDevice id, uint8_t device, uint8_t r, void *src, size_t src_size);
bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src_size);
bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_size);
/* Configure I2C pinmux. */
void i2c_config(I2CDevice id) {
volatile tegra_pinmux_t *pinmux = pinmux_get_regs();
switch (id) {
case I2C_1:
pinmux->gen1_i2c_scl = PINMUX_INPUT;
pinmux->gen1_i2c_sda = PINMUX_INPUT;
break;
case I2C_2:
pinmux->gen2_i2c_scl = PINMUX_INPUT;
pinmux->gen2_i2c_sda = PINMUX_INPUT;
break;
case I2C_3:
pinmux->gen3_i2c_scl = PINMUX_INPUT;
pinmux->gen3_i2c_sda = PINMUX_INPUT;
break;
case I2C_4:
pinmux->cam_i2c_scl = PINMUX_INPUT;
pinmux->cam_i2c_sda = PINMUX_INPUT;
break;
case I2C_5:
pinmux->pwr_i2c_scl = PINMUX_INPUT;
pinmux->pwr_i2c_sda = PINMUX_INPUT;
break;
case I2C_6:
/* Unused. */
break;
default: break;
}
}
/* Initialize I2C based on registers. */
void i2c_init(I2CDevice id) {
volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id);
/* Setup divisor, and clear the bus. */
regs->I2C_I2C_CLK_DIVISOR_REGISTER_0 = 0x50001;
regs->I2C_I2C_BUS_CLEAR_CONFIG_0 = 0x90003;
/* Load hardware configuration. */
i2c_load_config(regs);
/* Wait a while until BUS_CLEAR_DONE is set. */
for (unsigned int i = 0; i < 10; i++) {
udelay(20000);
if (regs->I2C_INTERRUPT_STATUS_REGISTER_0 & 0x800) {
break;
}
}
/* Read the BUS_CLEAR_STATUS. Result doesn't matter. */
regs->I2C_I2C_BUS_CLEAR_STATUS_0;
/* Read and set the Interrupt Status. */
uint32_t int_status = regs->I2C_INTERRUPT_STATUS_REGISTER_0;
regs->I2C_INTERRUPT_STATUS_REGISTER_0 = int_status;
}
/* Sets a bit in a PMIC register over I2C during CPU shutdown. */
void i2c_send_pmic_cpu_shutdown_cmd(void) {
uint32_t val = 0;
/* PMIC == Device 4:3C. */
i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1);
val |= 4;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1);
}
/* Queries the value of TI charger bit over I2C. */
bool i2c_query_ti_charger_bit_7(void) {
uint32_t val = 0;
/* TI Charger = Device 0:6B. */
i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
return (val & 0x80) != 0;
}
/* Clears TI charger bit over I2C. */
void i2c_clear_ti_charger_bit_7(void) {
uint32_t val = 0;
/* TI Charger = Device 0:6B. */
i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
val &= 0x7F;
i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
}
/* Sets TI charger bit over I2C. */
void i2c_set_ti_charger_bit_7(void) {
uint32_t val = 0;
/* TI Charger = Device 0:6B. */
i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
val |= 0x80;
i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
}
/* Get registers pointer based on I2C ID. */
volatile tegra_i2c_t *i2c_get_registers_from_id(I2CDevice id) {
switch (id) {
case I2C_1:
return I2C1_REGS;
case I2C_2:
return I2C2_REGS;
case I2C_3:
return I2C3_REGS;
case I2C_4:
return I2C4_REGS;
case I2C_5:
return I2C5_REGS;
case I2C_6:
return I2C6_REGS;
default:
generic_panic();
}
return NULL;
}
/* Load hardware config for I2C4. */
void i2c_load_config(volatile tegra_i2c_t *regs) {
/* Set MSTR_CONFIG_LOAD, TIMEOUT_CONFIG_LOAD, undocumented bit. */
regs->I2C_I2C_CONFIG_LOAD_0 = 0x25;
/* Wait a bit for master config to be loaded. */
for (unsigned int i = 0; i < 20; i++) {
udelay(1);
if (!(regs->I2C_I2C_CONFIG_LOAD_0 & 1)) {
break;
}
}
}
/* Reads a register from a device over I2C, writes result to output. */
bool i2c_query(I2CDevice id, uint8_t device, uint8_t r, void *dst, size_t dst_size) {
volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id);
uint32_t val = r;
/* Write single byte register ID to device. */
if (!i2c_write(regs, device, &val, 1)) {
return false;
}
/* Limit output size to 32-bits. */
if (dst_size > 4) {
return false;
}
return i2c_read(regs, device, dst, dst_size);
}
/* Writes a value to a register over I2C. */
bool i2c_send(I2CDevice id, uint8_t device, uint8_t r, void *src, size_t src_size) {
uint32_t val = r;
if (src_size == 0) {
return true;
} else if (src_size <= 3) {
memcpy(((uint8_t *)&val) + 1, src, src_size);
return i2c_write(i2c_get_registers_from_id(id), device, &val, src_size + 1);
} else {
return false;
}
}
/* Writes bytes to device over I2C. */
bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src_size) {
if (src_size > 4) {
return false;
} else if (src_size == 0) {
return true;
}
/* Set device for 7-bit write mode. */
regs->I2C_I2C_CMD_ADDR0_0 = device << 1;
/* Load in data to write. */
regs->I2C_I2C_CMD_DATA1_0 = read32le(src, 0);
/* Set config with LENGTH = src_size, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */
regs->I2C_I2C_CNFG_0 = ((src_size << 1) - 2) | 0x2800;
i2c_load_config(regs);
/* Config |= SEND; */
regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200);
while (regs->I2C_I2C_STATUS_0 & 0x100) {
/* Wait until not busy. */
}
/* Return CMD1_STAT == SL1_XFER_SUCCESSFUL. */
return (regs->I2C_I2C_STATUS_0 & 0xF) == 0;
}
/* Reads bytes from device over I2C. */
bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_size) {
if (dst_size > 4) {
return false;
} else if (dst_size == 0) {
return true;
}
/* Set device for 7-bit read mode. */
regs->I2C_I2C_CMD_ADDR0_0 = (device << 1) | 1;
/* Set config with LENGTH = dst_size, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */
regs->I2C_I2C_CNFG_0 = ((dst_size << 1) - 2) | 0x2840;
i2c_load_config(regs);
/* Config |= SEND; */
regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200);
while (regs->I2C_I2C_STATUS_0 & 0x100) {
/* Wait until not busy. */
}
/* Ensure success. */
if ((regs->I2C_I2C_STATUS_0 & 0xF) != 0) {
return false;
}
uint32_t val = regs->I2C_I2C_CMD_DATA1_0;
memcpy(dst, &val, dst_size);
return true;
}

View File

@ -1,107 +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/>.
*/
#ifndef FUSEE_I2C_H
#define FUSEE_I2C_H
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#define I2C1234_BASE 0x7000C000
#define I2C56_BASE 0x7000D000
#define MAX77621_CPU_I2C_ADDR 0x1B
#define MAX77621_GPU_I2C_ADDR 0x1C
#define MAX77812_PHASE31_CPU_I2C_ADDR 0x31
#define MAX77812_PHASE211_CPU_I2C_ADDR 0x33
#define MAX17050_I2C_ADDR 0x36
#define MAX77620_PWR_I2C_ADDR 0x3C
#define MAX77620_RTC_I2C_ADDR 0x68
#define BQ24193_I2C_ADDR 0x6B
typedef enum {
I2C_1 = 0,
I2C_2 = 1,
I2C_3 = 2,
I2C_4 = 3,
I2C_5 = 4,
I2C_6 = 5,
} I2CDevice;
typedef struct {
uint32_t I2C_I2C_CNFG_0;
uint32_t I2C_I2C_CMD_ADDR0_0;
uint32_t I2C_I2C_CMD_ADDR1_0;
uint32_t I2C_I2C_CMD_DATA1_0;
uint32_t I2C_I2C_CMD_DATA2_0;
uint32_t _0x14;
uint32_t _0x18;
uint32_t I2C_I2C_STATUS_0;
uint32_t I2C_I2C_SL_CNFG_0;
uint32_t I2C_I2C_SL_RCVD_0;
uint32_t I2C_I2C_SL_STATUS_0;
uint32_t I2C_I2C_SL_ADDR1_0;
uint32_t I2C_I2C_SL_ADDR2_0;
uint32_t I2C_I2C_TLOW_SEXT_0;
uint32_t _0x38;
uint32_t I2C_I2C_SL_DELAY_COUNT_0;
uint32_t I2C_I2C_SL_INT_MASK_0;
uint32_t I2C_I2C_SL_INT_SOURCE_0;
uint32_t I2C_I2C_SL_INT_SET_0;
uint32_t _0x4C;
uint32_t I2C_I2C_TX_PACKET_FIFO_0;
uint32_t I2C_I2C_RX_FIFO_0;
uint32_t I2C_PACKET_TRANSFER_STATUS_0;
uint32_t I2C_FIFO_CONTROL_0;
uint32_t I2C_FIFO_STATUS_0;
uint32_t I2C_INTERRUPT_MASK_REGISTER_0;
uint32_t I2C_INTERRUPT_STATUS_REGISTER_0;
uint32_t I2C_I2C_CLK_DIVISOR_REGISTER_0;
uint32_t I2C_I2C_INTERRUPT_SOURCE_REGISTER_0;
uint32_t I2C_I2C_INTERRUPT_SET_REGISTER_0;
uint32_t I2C_I2C_SLV_TX_PACKET_FIFO_0;
uint32_t I2C_I2C_SLV_RX_FIFO_0;
uint32_t I2C_I2C_SLV_PACKET_STATUS_0;
uint32_t I2C_I2C_BUS_CLEAR_CONFIG_0;
uint32_t I2C_I2C_BUS_CLEAR_STATUS_0;
uint32_t I2C_I2C_CONFIG_LOAD_0;
uint32_t _0x90;
uint32_t I2C_I2C_INTERFACE_TIMING_0_0;
uint32_t I2C_I2C_INTERFACE_TIMING_1_0;
uint32_t I2C_I2C_HS_INTERFACE_TIMING_0_0;
uint32_t I2C_I2C_HS_INTERFACE_TIMING_1_0;
} tegra_i2c_t;
#define I2C1_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x000))
#define I2C2_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x400))
#define I2C3_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x500))
#define I2C4_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x700))
#define I2C5_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x000))
#define I2C6_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x100))
void i2c_config(I2CDevice id);
void i2c_init(I2CDevice id);
bool i2c_query(I2CDevice id, uint8_t device, uint8_t r, void *dst, size_t dst_size);
bool i2c_send(I2CDevice id, uint8_t device, uint8_t r, void *src, size_t src_size);
void i2c_send_pmic_cpu_shutdown_cmd(void);
bool i2c_query_ti_charger_bit_7(void);
void i2c_clear_ti_charger_bit_7(void);
void i2c_set_ti_charger_bit_7(void);
#endif

View File

@ -1,257 +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 <stdint.h>
#include "utils.h"
#include "car.h"
#include "timers.h"
#include "di.h"
#include "se.h"
#include "fuse.h"
#include "pmc.h"
#include "mc.h"
#include "sysreg.h"
#include "tsec.h"
#define I2S_BASE 0x702D1000
#define MAKE_I2S_REG(n) MAKE_REG32(I2S_BASE + n)
static void setup_exception_vectors(void) {
for (unsigned int i = 0; i < 0x20; i += 4) {
MAKE_REG32(0x6000F200u + i) = (uint32_t)generic_panic;
}
}
static void mbist_workaround(void)
{
volatile tegra_car_t *car = car_get_regs();
car->clk_source_sor1 = ((car->clk_source_sor1 | 0x8000) & 0xFFFFBFFF);
car->plld_base |= 0x40800000u;
car->rst_dev_y_clr = 0x40;
car->rst_dev_x_clr = 0x40000;
car->rst_dev_l_clr = 0x18000000;
udelay(3);
/* Setup I2S. */
MAKE_I2S_REG(0x0A0) |= 0x400;
MAKE_I2S_REG(0x088) &= 0xFFFFFFFE;
MAKE_I2S_REG(0x1A0) |= 0x400;
MAKE_I2S_REG(0x188) &= 0xFFFFFFFE;
MAKE_I2S_REG(0x2A0) |= 0x400;
MAKE_I2S_REG(0x288) &= 0xFFFFFFFE;
MAKE_I2S_REG(0x3A0) |= 0x400;
MAKE_I2S_REG(0x388) &= 0xFFFFFFFE;
MAKE_I2S_REG(0x4A0) |= 0x400;
MAKE_I2S_REG(0x488) &= 0xFFFFFFFE;
MAKE_DI_REG(DC_COM_DSC_TOP_CTL) |= 4;
MAKE_VIC_REG(0x8C) = 0xFFFFFFFF;
udelay(3);
/* Set devices in reset. */
car->rst_dev_y_set = 0x40;
car->rst_dev_l_set = 0x18000000;
car->rst_dev_x_set = 0x40000;
/* Clock out enables. */
car->clk_out_enb_h = 0xC0;
car->clk_out_enb_l = 0x80000130;
car->clk_out_enb_u = 0x1F00200;
car->clk_out_enb_v = 0x80400808;
car->clk_out_enb_w = 0x402000FC;
car->clk_out_enb_x = 0x23000780;
car->clk_out_enb_y = 0x300;
/* LVL2 clock gate overrides. */
car->lvl2_clk_gate_ovra = 0;
car->lvl2_clk_gate_ovrb = 0;
car->lvl2_clk_gate_ovrc = 0;
car->lvl2_clk_gate_ovrd = 0;
car->lvl2_clk_gate_ovre = 0;
/* Configure clock sources. */
car->plld_base &= 0x1F7FFFFF;
car->clk_source_sor1 &= 0xFFFF3FFF;
car->clk_source_vi = ((car->clk_source_vi & 0x1FFFFFFF) | 0x80000000);
car->clk_source_host1x = ((car->clk_source_host1x & 0x1FFFFFFF) | 0x80000000);
car->clk_source_nvenc = ((car->clk_source_nvenc & 0x1FFFFFFF) | 0x80000000);
}
static int tsec_dma_wait_idle()
{
volatile tegra_tsec_t *tsec = tsec_get_regs();
uint32_t timeout = (get_time_ms() + 10000);
while (!(tsec->TSEC_FALCON_DMATRFCMD & 2))
{
if (get_time_ms() > timeout)
return 0;
}
return 1;
}
static int tsec_dma_phys_to_flcn(bool is_imem, uint32_t flcn_offset, uint32_t phys_offset)
{
volatile tegra_tsec_t *tsec = tsec_get_regs();
uint32_t cmd = 0;
if (!is_imem)
cmd = 0x600;
else
cmd = 0x10;
tsec->TSEC_FALCON_DMATRFMOFFS = flcn_offset;
tsec->TSEC_FALCON_DMATRFFBOFFS = phys_offset;
tsec->TSEC_FALCON_DMATRFCMD = cmd;
return tsec_dma_wait_idle();
}
static int tsec_kfuse_wait_ready()
{
uint32_t timeout = (get_time_ms() + 10000);
/* Wait for STATE_DONE. */
while (!(KFUSE_STATE & 0x10000))
{
if (get_time_ms() > timeout)
return 0;
}
/* Check for STATE_CRCPASS. */
if (!(KFUSE_STATE & 0x20000))
return 0;
return 1;
}
int load_tsec_fw(void) {
volatile uint32_t* tsec_fw = (volatile uint32_t*)0x40010F00;
const uint32_t tsec_fw_length = MAKE_REG32(0x40010EFC);
volatile tegra_tsec_t *tsec = tsec_get_regs();
/* Enable clocks. */
clkrst_reboot(CARDEVICE_HOST1X);
clkrst_reboot(CARDEVICE_TSEC);
clkrst_reboot(CARDEVICE_SOR_SAFE);
clkrst_reboot(CARDEVICE_SOR0);
clkrst_reboot(CARDEVICE_SOR1);
clkrst_reboot(CARDEVICE_KFUSE);
/* Make sure KFUSE is ready. */
if (!tsec_kfuse_wait_ready())
{
/* Disable clocks. */
clkrst_disable(CARDEVICE_KFUSE);
clkrst_disable(CARDEVICE_SOR1);
clkrst_disable(CARDEVICE_SOR0);
clkrst_disable(CARDEVICE_SOR_SAFE);
clkrst_disable(CARDEVICE_TSEC);
clkrst_disable(CARDEVICE_HOST1X);
return -1;
}
/* Configure Falcon. */
tsec->TSEC_FALCON_DMACTL = 0;
tsec->TSEC_FALCON_IRQMSET = 0xFFF2;
tsec->TSEC_FALCON_IRQDEST = 0xFFF0;
tsec->TSEC_FALCON_ITFEN = 3;
/* Make sure the DMA block is idle. */
if (!tsec_dma_wait_idle())
{
/* Disable clocks. */
clkrst_disable(CARDEVICE_KFUSE);
clkrst_disable(CARDEVICE_SOR1);
clkrst_disable(CARDEVICE_SOR0);
clkrst_disable(CARDEVICE_SOR_SAFE);
clkrst_disable(CARDEVICE_TSEC);
clkrst_disable(CARDEVICE_HOST1X);
return -2;
}
/* Load firmware. */
tsec->TSEC_FALCON_DMATRFBASE = (uint32_t)tsec_fw >> 8;
for (uint32_t addr = 0; addr < tsec_fw_length; addr += 0x100)
{
if (!tsec_dma_phys_to_flcn(true, addr, addr))
{
/* Disable clocks. */
clkrst_disable(CARDEVICE_KFUSE);
clkrst_disable(CARDEVICE_SOR1);
clkrst_disable(CARDEVICE_SOR0);
clkrst_disable(CARDEVICE_SOR_SAFE);
clkrst_disable(CARDEVICE_TSEC);
clkrst_disable(CARDEVICE_HOST1X);
return -3;
}
}
/* Write magic value to HOST1X scratch register. */
MAKE_HOST1X_REG(0x3300) = 0x34C2E1DA;
/* Execute firmware. */
tsec->TSEC_FALCON_MAILBOX1 = 0;
tsec->TSEC_FALCON_MAILBOX0 = 1;
tsec->TSEC_FALCON_BOOTVEC = 0;
tsec->TSEC_FALCON_CPUCTL = 2;
while (true) {
/* Yield to Nintendo's TSEC firmware. */
}
}
int main(void) {
/* Setup vectors */
setup_exception_vectors();
volatile tegra_pmc_t *pmc = pmc_get_regs();
volatile tegra_car_t *car = car_get_regs();
/* Clear the boot reason to avoid problems later */
pmc->scratch200 = 0;
pmc->rst_status = 0;
//AHB_AHB_SPARE_REG_0 &= 0xFFFFFF9F;
//pmc->scratch49 = (((pmc->scratch49 >> 1) << 1) & 0xFFFFFFFD);
/* Apply the memory built-in self test workaround. */
mbist_workaround();
/* Reboot SE. */
clkrst_reboot(CARDEVICE_SE);
/* Initialize the fuse driver. */
fuse_init();
/* Don't bother checking SKU, fuses, or bootloader version. */
mc_enable_for_tsec();
/* 7.0.0 package1ldr holds I2C5 in reset, clears SYS clock. */
car->clk_source_sys = 0;
rst_enable(CARDEVICE_I2C5);
load_tsec_fw();
while (true) { }
return 0;
}

View File

@ -1,50 +0,0 @@
/*
* Copyright (c) 2018 naehrwert
* 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 "mc.h"
#include "car.h"
#include "timers.h"
void mc_enable_for_tsec()
{
volatile tegra_car_t *car = car_get_regs();
/* Set EMC clock source. */
car->clk_source_emc = ((car->clk_source_emc & 0x1FFFFFFF) | 0x40000000);
/* Enable MIPI CAL clock. */
car->clk_enb_h_set = ((car->clk_enb_h_set & 0xFDFFFFFF) | 0x2000000);
/* Enable MC clock. */
car->clk_enb_h_set = ((car->clk_enb_h_set & 0xFFFFFFFE) | 1);
/* Enable EMC DLL clock. */
car->clk_enb_x_set = ((car->clk_enb_x_set & 0xFFFFBFFF) | 0x4000);
/* Clear EMC and MC reset. */
/* NOTE: [4.0.0+] This was changed to use the right register. */
/* car->rst_dev_h_set = 0x2000001; */
car->rst_dev_h_clr = 0x2000001;
udelay(5);
/* Enable AHB redirect, weird boundaries for new TSEC firmware. */
car->lvl2_clk_gate_ovrd = ((car->lvl2_clk_gate_ovrd & 0xFFF7FFFF) | 0x80000);
MAKE_MC_REG(MC_IRAM_REG_CTRL) &= 0xFFFFFFFE;
MAKE_MC_REG(MC_IRAM_BOM) = 0x40000000;
MAKE_MC_REG(MC_IRAM_TOM) = 0x80000000;
}

View File

@ -1,601 +0,0 @@
/*
* Copyright (c) 2014, NVIDIA Corporation. All rights reserved.
* Copyright (c) 2018 naehrwert
* 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/>.
*/
#ifndef FUSEE_MC_H_
#define FUSEE_MC_H_
#include <stdint.h>
#include <stdbool.h>
#define MC_BASE 0x70019000
#define MAKE_MC_REG(n) MAKE_REG32(MC_BASE + n)
#define MC_INTSTATUS 0x0
#define MC_INTMASK 0x4
#define MC_ERR_STATUS 0x8
#define MC_ERR_ADR 0xc
#define MC_SMMU_CONFIG 0x10
#define MC_SMMU_TLB_CONFIG 0x14
#define MC_SMMU_PTC_CONFIG 0x18
#define MC_SMMU_PTB_ASID 0x1c
#define MC_SMMU_PTB_DATA 0x20
#define MC_SMMU_TLB_FLUSH 0x30
#define MC_SMMU_PTC_FLUSH 0x34
#define MC_SMMU_ASID_SECURITY 0x38
#define MC_SMMU_ASID_SECURITY_1 0x3c
#define MC_SMMU_ASID_SECURITY_2 0x9e0
#define MC_SMMU_ASID_SECURITY_3 0x9e4
#define MC_SMMU_ASID_SECURITY_4 0x9e8
#define MC_SMMU_ASID_SECURITY_5 0x9ec
#define MC_SMMU_ASID_SECURITY_6 0x9f0
#define MC_SMMU_ASID_SECURITY_7 0x9f4
#define MC_SMMU_AFI_ASID 0x238
#define MC_SMMU_AVPC_ASID 0x23c
#define MC_SMMU_TSEC_ASID 0x294
#define MC_SMMU_PPCS1_ASID 0x298
#define MC_SMMU_TRANSLATION_ENABLE_0 0x228
#define MC_SMMU_TRANSLATION_ENABLE_1 0x22c
#define MC_SMMU_TRANSLATION_ENABLE_2 0x230
#define MC_SMMU_TRANSLATION_ENABLE_3 0x234
#define MC_SMMU_TRANSLATION_ENABLE_4 0xb98
#define MC_PCFIFO_CLIENT_CONFIG0 0xdd0
#define MC_PCFIFO_CLIENT_CONFIG1 0xdd4
#define MC_PCFIFO_CLIENT_CONFIG2 0xdd8
#define MC_PCFIFO_CLIENT_CONFIG3 0xddc
#define MC_PCFIFO_CLIENT_CONFIG4 0xde0
#define MC_EMEM_CFG 0x50
#define MC_EMEM_ADR_CFG 0x54
#define MC_EMEM_ADR_CFG_DEV0 0x58
#define MC_EMEM_ADR_CFG_DEV1 0x5c
#define MC_EMEM_ADR_CFG_CHANNEL_MASK 0x60
#define MC_EMEM_ADR_CFG_BANK_MASK_0 0x64
#define MC_EMEM_ADR_CFG_BANK_MASK_1 0x68
#define MC_EMEM_ADR_CFG_BANK_MASK_2 0x6c
#define MC_SECURITY_CFG0 0x70
#define MC_SECURITY_CFG1 0x74
#define MC_SECURITY_CFG3 0x9bc
#define MC_SECURITY_RSV 0x7c
#define MC_EMEM_ARB_CFG 0x90
#define MC_EMEM_ARB_OUTSTANDING_REQ 0x94
#define MC_EMEM_ARB_TIMING_RCD 0x98
#define MC_EMEM_ARB_TIMING_RP 0x9c
#define MC_EMEM_ARB_TIMING_RC 0xa0
#define MC_EMEM_ARB_TIMING_RAS 0xa4
#define MC_EMEM_ARB_TIMING_FAW 0xa8
#define MC_EMEM_ARB_TIMING_RRD 0xac
#define MC_EMEM_ARB_TIMING_RAP2PRE 0xb0
#define MC_EMEM_ARB_TIMING_WAP2PRE 0xb4
#define MC_EMEM_ARB_TIMING_R2R 0xb8
#define MC_EMEM_ARB_TIMING_W2W 0xbc
#define MC_EMEM_ARB_TIMING_R2W 0xc0
#define MC_EMEM_ARB_TIMING_W2R 0xc4
#define MC_EMEM_ARB_TIMING_RFCPB 0x6c0
#define MC_EMEM_ARB_TIMING_CCDMW 0x6c4
#define MC_EMEM_ARB_REFPB_HP_CTRL 0x6f0
#define MC_EMEM_ARB_REFPB_BANK_CTRL 0x6f4
#define MC_EMEM_ARB_DA_TURNS 0xd0
#define MC_EMEM_ARB_DA_COVERS 0xd4
#define MC_EMEM_ARB_MISC0 0xd8
#define MC_EMEM_ARB_MISC1 0xdc
#define MC_EMEM_ARB_MISC2 0xc8
#define MC_EMEM_ARB_RING1_THROTTLE 0xe0
#define MC_EMEM_ARB_RING3_THROTTLE 0xe4
#define MC_EMEM_ARB_NISO_THROTTLE 0x6b0
#define MC_EMEM_ARB_OVERRIDE 0xe8
#define MC_EMEM_ARB_RSV 0xec
#define MC_CLKEN_OVERRIDE 0xf4
#define MC_TIMING_CONTROL_DBG 0xf8
#define MC_TIMING_CONTROL 0xfc
#define MC_STAT_CONTROL 0x100
#define MC_STAT_STATUS 0x104
#define MC_STAT_EMC_CLOCK_LIMIT 0x108
#define MC_STAT_EMC_CLOCK_LIMIT_MSBS 0x10c
#define MC_STAT_EMC_CLOCKS 0x110
#define MC_STAT_EMC_CLOCKS_MSBS 0x114
#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_LO 0x118
#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_LO 0x158
#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_HI 0x11c
#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_HI 0x15c
#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_UPPER 0xa20
#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_UPPER 0xa24
#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_LO 0x198
#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_LO 0x1a8
#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_HI 0x19c
#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_HI 0x1ac
#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_UPPER 0xa28
#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_UPPER 0xa2c
#define MC_STAT_EMC_FILTER_SET0_ASID 0x1a0
#define MC_STAT_EMC_FILTER_SET1_ASID 0x1b0
#define MC_STAT_EMC_FILTER_SET0_SLACK_LIMIT 0x120
#define MC_STAT_EMC_FILTER_SET1_SLACK_LIMIT 0x160
#define MC_STAT_EMC_FILTER_SET0_CLIENT_0 0x128
#define MC_STAT_EMC_FILTER_SET1_CLIENT_0 0x168
#define MC_STAT_EMC_FILTER_SET0_CLIENT_1 0x12c
#define MC_STAT_EMC_FILTER_SET1_CLIENT_1 0x16c
#define MC_STAT_EMC_FILTER_SET0_CLIENT_2 0x130
#define MC_STAT_EMC_FILTER_SET1_CLIENT_2 0x170
#define MC_STAT_EMC_FILTER_SET0_CLIENT_3 0x134
#define MC_STAT_EMC_FILTER_SET0_CLIENT_4 0xb88
#define MC_STAT_EMC_FILTER_SET1_CLIENT_3 0x174
#define MC_STAT_EMC_FILTER_SET1_CLIENT_4 0xb8c
#define MC_STAT_EMC_SET0_COUNT 0x138
#define MC_STAT_EMC_SET0_COUNT_MSBS 0x13c
#define MC_STAT_EMC_SET1_COUNT 0x178
#define MC_STAT_EMC_SET1_COUNT_MSBS 0x17c
#define MC_STAT_EMC_SET0_SLACK_ACCUM 0x140
#define MC_STAT_EMC_SET0_SLACK_ACCUM_MSBS 0x144
#define MC_STAT_EMC_SET1_SLACK_ACCUM 0x180
#define MC_STAT_EMC_SET1_SLACK_ACCUM_MSBS 0x184
#define MC_STAT_EMC_SET0_HISTO_COUNT 0x148
#define MC_STAT_EMC_SET0_HISTO_COUNT_MSBS 0x14c
#define MC_STAT_EMC_SET1_HISTO_COUNT 0x188
#define MC_STAT_EMC_SET1_HISTO_COUNT_MSBS 0x18c
#define MC_STAT_EMC_SET0_MINIMUM_SLACK_OBSERVED 0x150
#define MC_STAT_EMC_SET1_MINIMUM_SLACK_OBSERVED 0x190
#define MC_STAT_EMC_SET0_IDLE_CYCLE_COUNT 0x1b8
#define MC_STAT_EMC_SET0_IDLE_CYCL_COUNT_MSBS 0x1bc
#define MC_STAT_EMC_SET1_IDLE_CYCLE_COUNT 0x1c8
#define MC_STAT_EMC_SET1_IDLE_CYCL_COUNT_MSBS 0x1cc
#define MC_STAT_EMC_SET0_IDLE_CYCLE_PARTITION_SELECT 0x1c0
#define MC_STAT_EMC_SET1_IDLE_CYCLE_PARTITION_SELECT 0x1d0
#define MC_CLIENT_HOTRESET_CTRL 0x200
#define MC_CLIENT_HOTRESET_CTRL_1 0x970
#define MC_CLIENT_HOTRESET_STATUS 0x204
#define MC_CLIENT_HOTRESET_STATUS_1 0x974
#define MC_EMEM_ARB_ISOCHRONOUS_0 0x208
#define MC_EMEM_ARB_ISOCHRONOUS_1 0x20c
#define MC_EMEM_ARB_ISOCHRONOUS_2 0x210
#define MC_EMEM_ARB_ISOCHRONOUS_3 0x214
#define MC_EMEM_ARB_ISOCHRONOUS_4 0xb94
#define MC_EMEM_ARB_HYSTERESIS_0 0x218
#define MC_EMEM_ARB_HYSTERESIS_1 0x21c
#define MC_EMEM_ARB_HYSTERESIS_2 0x220
#define MC_EMEM_ARB_HYSTERESIS_3 0x224
#define MC_EMEM_ARB_HYSTERESIS_4 0xb84
#define MC_EMEM_ARB_DHYSTERESIS_0 0xbb0
#define MC_EMEM_ARB_DHYSTERESIS_1 0xbb4
#define MC_EMEM_ARB_DHYSTERESIS_2 0xbb8
#define MC_EMEM_ARB_DHYSTERESIS_3 0xbbc
#define MC_EMEM_ARB_DHYSTERESIS_4 0xbc0
#define MC_EMEM_ARB_DHYST_CTRL 0xbcc
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_0 0xbd0
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_1 0xbd4
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_2 0xbd8
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_3 0xbdc
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_4 0xbe0
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_5 0xbe4
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_6 0xbe8
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_7 0xbec
#define MC_RESERVED_RSV 0x3fc
#define MC_DISB_EXTRA_SNAP_LEVELS 0x408
#define MC_APB_EXTRA_SNAP_LEVELS 0x2a4
#define MC_AHB_EXTRA_SNAP_LEVELS 0x2a0
#define MC_USBD_EXTRA_SNAP_LEVELS 0xa18
#define MC_ISP_EXTRA_SNAP_LEVELS 0xa08
#define MC_AUD_EXTRA_SNAP_LEVELS 0xa10
#define MC_MSE_EXTRA_SNAP_LEVELS 0x40c
#define MC_GK2_EXTRA_SNAP_LEVELS 0xa40
#define MC_A9AVPPC_EXTRA_SNAP_LEVELS 0x414
#define MC_FTOP_EXTRA_SNAP_LEVELS 0x2bc
#define MC_JPG_EXTRA_SNAP_LEVELS 0xa3c
#define MC_HOST_EXTRA_SNAP_LEVELS 0xa14
#define MC_SAX_EXTRA_SNAP_LEVELS 0x2c0
#define MC_DIS_EXTRA_SNAP_LEVELS 0x2ac
#define MC_VICPC_EXTRA_SNAP_LEVELS 0xa1c
#define MC_HDAPC_EXTRA_SNAP_LEVELS 0xa48
#define MC_AVP_EXTRA_SNAP_LEVELS 0x2a8
#define MC_USBX_EXTRA_SNAP_LEVELS 0x404
#define MC_PCX_EXTRA_SNAP_LEVELS 0x2b8
#define MC_SD_EXTRA_SNAP_LEVELS 0xa04
#define MC_DFD_EXTRA_SNAP_LEVELS 0xa4c
#define MC_VE_EXTRA_SNAP_LEVELS 0x2d8
#define MC_GK_EXTRA_SNAP_LEVELS 0xa00
#define MC_VE2_EXTRA_SNAP_LEVELS 0x410
#define MC_SDM_EXTRA_SNAP_LEVELS 0xa44
#define MC_VIDEO_PROTECT_BOM 0x648
#define MC_VIDEO_PROTECT_SIZE_MB 0x64c
#define MC_VIDEO_PROTECT_BOM_ADR_HI 0x978
#define MC_VIDEO_PROTECT_REG_CTRL 0x650
#define MC_ERR_VPR_STATUS 0x654
#define MC_ERR_VPR_ADR 0x658
#define MC_VIDEO_PROTECT_VPR_OVERRIDE 0x418
#define MC_VIDEO_PROTECT_VPR_OVERRIDE1 0x590
#define MC_IRAM_BOM 0x65c
#define MC_IRAM_TOM 0x660
#define MC_IRAM_ADR_HI 0x980
#define MC_IRAM_REG_CTRL 0x964
#define MC_EMEM_CFG_ACCESS_CTRL 0x664
#define MC_TZ_SECURITY_CTRL 0x668
#define MC_EMEM_ARB_OUTSTANDING_REQ_RING3 0x66c
#define MC_EMEM_ARB_OUTSTANDING_REQ_NISO 0x6b4
#define MC_EMEM_ARB_RING0_THROTTLE_MASK 0x6bc
#define MC_EMEM_ARB_NISO_THROTTLE_MASK 0x6b8
#define MC_EMEM_ARB_NISO_THROTTLE_MASK_1 0xb80
#define MC_SEC_CARVEOUT_BOM 0x670
#define MC_SEC_CARVEOUT_SIZE_MB 0x674
#define MC_SEC_CARVEOUT_ADR_HI 0x9d4
#define MC_SEC_CARVEOUT_REG_CTRL 0x678
#define MC_ERR_SEC_STATUS 0x67c
#define MC_ERR_SEC_ADR 0x680
#define MC_PC_IDLE_CLOCK_GATE_CONFIG 0x684
#define MC_STUTTER_CONTROL 0x688
#define MC_RESERVED_RSV_1 0x958
#define MC_DVFS_PIPE_SELECT 0x95c
#define MC_AHB_PTSA_MIN 0x4e0
#define MC_AUD_PTSA_MIN 0x54c
#define MC_MLL_MPCORER_PTSA_RATE 0x44c
#define MC_RING2_PTSA_RATE 0x440
#define MC_USBD_PTSA_RATE 0x530
#define MC_USBX_PTSA_MIN 0x528
#define MC_USBD_PTSA_MIN 0x534
#define MC_APB_PTSA_MAX 0x4f0
#define MC_JPG_PTSA_RATE 0x584
#define MC_DIS_PTSA_MIN 0x420
#define MC_AVP_PTSA_MAX 0x4fc
#define MC_AVP_PTSA_RATE 0x4f4
#define MC_RING1_PTSA_MIN 0x480
#define MC_DIS_PTSA_MAX 0x424
#define MC_SD_PTSA_MAX 0x4d8
#define MC_MSE_PTSA_RATE 0x4c4
#define MC_VICPC_PTSA_MIN 0x558
#define MC_PCX_PTSA_MAX 0x4b4
#define MC_ISP_PTSA_RATE 0x4a0
#define MC_A9AVPPC_PTSA_MIN 0x48c
#define MC_RING2_PTSA_MAX 0x448
#define MC_AUD_PTSA_RATE 0x548
#define MC_HOST_PTSA_MIN 0x51c
#define MC_MLL_MPCORER_PTSA_MAX 0x454
#define MC_SD_PTSA_MIN 0x4d4
#define MC_RING1_PTSA_RATE 0x47c
#define MC_JPG_PTSA_MIN 0x588
#define MC_HDAPC_PTSA_MIN 0x62c
#define MC_AVP_PTSA_MIN 0x4f8
#define MC_JPG_PTSA_MAX 0x58c
#define MC_VE_PTSA_MAX 0x43c
#define MC_DFD_PTSA_MAX 0x63c
#define MC_VICPC_PTSA_RATE 0x554
#define MC_GK_PTSA_MAX 0x544
#define MC_VICPC_PTSA_MAX 0x55c
#define MC_SDM_PTSA_MAX 0x624
#define MC_SAX_PTSA_RATE 0x4b8
#define MC_PCX_PTSA_MIN 0x4b0
#define MC_APB_PTSA_MIN 0x4ec
#define MC_GK2_PTSA_MIN 0x614
#define MC_PCX_PTSA_RATE 0x4ac
#define MC_RING1_PTSA_MAX 0x484
#define MC_HDAPC_PTSA_RATE 0x628
#define MC_MLL_MPCORER_PTSA_MIN 0x450
#define MC_GK2_PTSA_MAX 0x618
#define MC_AUD_PTSA_MAX 0x550
#define MC_GK2_PTSA_RATE 0x610
#define MC_ISP_PTSA_MAX 0x4a8
#define MC_DISB_PTSA_RATE 0x428
#define MC_VE2_PTSA_MAX 0x49c
#define MC_DFD_PTSA_MIN 0x638
#define MC_FTOP_PTSA_RATE 0x50c
#define MC_A9AVPPC_PTSA_RATE 0x488
#define MC_VE2_PTSA_MIN 0x498
#define MC_USBX_PTSA_MAX 0x52c
#define MC_DIS_PTSA_RATE 0x41c
#define MC_USBD_PTSA_MAX 0x538
#define MC_A9AVPPC_PTSA_MAX 0x490
#define MC_USBX_PTSA_RATE 0x524
#define MC_FTOP_PTSA_MAX 0x514
#define MC_HDAPC_PTSA_MAX 0x630
#define MC_SD_PTSA_RATE 0x4d0
#define MC_DFD_PTSA_RATE 0x634
#define MC_FTOP_PTSA_MIN 0x510
#define MC_SDM_PTSA_RATE 0x61c
#define MC_AHB_PTSA_RATE 0x4dc
#define MC_SMMU_SMMU_PTSA_MAX 0x460
#define MC_RING2_PTSA_MIN 0x444
#define MC_SDM_PTSA_MIN 0x620
#define MC_APB_PTSA_RATE 0x4e8
#define MC_MSE_PTSA_MIN 0x4c8
#define MC_HOST_PTSA_RATE 0x518
#define MC_VE_PTSA_RATE 0x434
#define MC_AHB_PTSA_MAX 0x4e4
#define MC_SAX_PTSA_MIN 0x4bc
#define MC_SMMU_SMMU_PTSA_MIN 0x45c
#define MC_ISP_PTSA_MIN 0x4a4
#define MC_HOST_PTSA_MAX 0x520
#define MC_SAX_PTSA_MAX 0x4c0
#define MC_VE_PTSA_MIN 0x438
#define MC_GK_PTSA_MIN 0x540
#define MC_MSE_PTSA_MAX 0x4cc
#define MC_DISB_PTSA_MAX 0x430
#define MC_DISB_PTSA_MIN 0x42c
#define MC_SMMU_SMMU_PTSA_RATE 0x458
#define MC_VE2_PTSA_RATE 0x494
#define MC_GK_PTSA_RATE 0x53c
#define MC_PTSA_GRANT_DECREMENT 0x960
#define MC_LATENCY_ALLOWANCE_AVPC_0 0x2e4
#define MC_LATENCY_ALLOWANCE_AXIAP_0 0x3a0
#define MC_LATENCY_ALLOWANCE_XUSB_1 0x380
#define MC_LATENCY_ALLOWANCE_ISP2B_0 0x384
#define MC_LATENCY_ALLOWANCE_SDMMCAA_0 0x3bc
#define MC_LATENCY_ALLOWANCE_SDMMCA_0 0x3b8
#define MC_LATENCY_ALLOWANCE_ISP2_0 0x370
#define MC_LATENCY_ALLOWANCE_SE_0 0x3e0
#define MC_LATENCY_ALLOWANCE_ISP2_1 0x374
#define MC_LATENCY_ALLOWANCE_DC_0 0x2e8
#define MC_LATENCY_ALLOWANCE_VIC_0 0x394
#define MC_LATENCY_ALLOWANCE_DCB_1 0x2f8
#define MC_LATENCY_ALLOWANCE_NVDEC_0 0x3d8
#define MC_LATENCY_ALLOWANCE_DCB_2 0x2fc
#define MC_LATENCY_ALLOWANCE_TSEC_0 0x390
#define MC_LATENCY_ALLOWANCE_DC_2 0x2f0
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0AB 0x694
#define MC_LATENCY_ALLOWANCE_PPCS_1 0x348
#define MC_LATENCY_ALLOWANCE_XUSB_0 0x37c
#define MC_LATENCY_ALLOWANCE_PPCS_0 0x344
#define MC_LATENCY_ALLOWANCE_TSECB_0 0x3f0
#define MC_LATENCY_ALLOWANCE_AFI_0 0x2e0
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0B 0x698
#define MC_LATENCY_ALLOWANCE_DC_1 0x2ec
#define MC_LATENCY_ALLOWANCE_APE_0 0x3dc
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0C 0x6a0
#define MC_LATENCY_ALLOWANCE_A9AVP_0 0x3a4
#define MC_LATENCY_ALLOWANCE_GPU2_0 0x3e8
#define MC_LATENCY_ALLOWANCE_DCB_0 0x2f4
#define MC_LATENCY_ALLOWANCE_HC_1 0x314
#define MC_LATENCY_ALLOWANCE_SDMMC_0 0x3c0
#define MC_LATENCY_ALLOWANCE_NVJPG_0 0x3e4
#define MC_LATENCY_ALLOWANCE_PTC_0 0x34c
#define MC_LATENCY_ALLOWANCE_ETR_0 0x3ec
#define MC_LATENCY_ALLOWANCE_MPCORE_0 0x320
#define MC_LATENCY_ALLOWANCE_VI2_0 0x398
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0BB 0x69c
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0CB 0x6a4
#define MC_LATENCY_ALLOWANCE_SATA_0 0x350
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0A 0x690
#define MC_LATENCY_ALLOWANCE_HC_0 0x310
#define MC_LATENCY_ALLOWANCE_DC_3 0x3c8
#define MC_LATENCY_ALLOWANCE_GPU_0 0x3ac
#define MC_LATENCY_ALLOWANCE_SDMMCAB_0 0x3c4
#define MC_LATENCY_ALLOWANCE_ISP2B_1 0x388
#define MC_LATENCY_ALLOWANCE_NVENC_0 0x328
#define MC_LATENCY_ALLOWANCE_HDA_0 0x318
#define MC_MIN_LENGTH_APE_0 0xb34
#define MC_MIN_LENGTH_DCB_2 0x8a8
#define MC_MIN_LENGTH_A9AVP_0 0x950
#define MC_MIN_LENGTH_TSEC_0 0x93c
#define MC_MIN_LENGTH_DC_1 0x898
#define MC_MIN_LENGTH_AXIAP_0 0x94c
#define MC_MIN_LENGTH_ISP2B_0 0x930
#define MC_MIN_LENGTH_VI2_0 0x944
#define MC_MIN_LENGTH_DCB_0 0x8a0
#define MC_MIN_LENGTH_DCB_1 0x8a4
#define MC_MIN_LENGTH_PPCS_1 0x8f4
#define MC_MIN_LENGTH_NVJPG_0 0xb3c
#define MC_MIN_LENGTH_HDA_0 0x8c4
#define MC_MIN_LENGTH_NVENC_0 0x8d4
#define MC_MIN_LENGTH_SDMMC_0 0xb18
#define MC_MIN_LENGTH_ISP2B_1 0x934
#define MC_MIN_LENGTH_HC_1 0x8c0
#define MC_MIN_LENGTH_DC_3 0xb20
#define MC_MIN_LENGTH_AVPC_0 0x890
#define MC_MIN_LENGTH_VIC_0 0x940
#define MC_MIN_LENGTH_ISP2_0 0x91c
#define MC_MIN_LENGTH_HC_0 0x8bc
#define MC_MIN_LENGTH_SE_0 0xb38
#define MC_MIN_LENGTH_NVDEC_0 0xb30
#define MC_MIN_LENGTH_SATA_0 0x8fc
#define MC_MIN_LENGTH_DC_0 0x894
#define MC_MIN_LENGTH_XUSB_1 0x92c
#define MC_MIN_LENGTH_DC_2 0x89c
#define MC_MIN_LENGTH_SDMMCAA_0 0xb14
#define MC_MIN_LENGTH_GPU_0 0xb04
#define MC_MIN_LENGTH_ETR_0 0xb44
#define MC_MIN_LENGTH_AFI_0 0x88c
#define MC_MIN_LENGTH_PPCS_0 0x8f0
#define MC_MIN_LENGTH_ISP2_1 0x920
#define MC_MIN_LENGTH_XUSB_0 0x928
#define MC_MIN_LENGTH_MPCORE_0 0x8cc
#define MC_MIN_LENGTH_TSECB_0 0xb48
#define MC_MIN_LENGTH_SDMMCA_0 0xb10
#define MC_MIN_LENGTH_GPU2_0 0xb40
#define MC_MIN_LENGTH_SDMMCAB_0 0xb1c
#define MC_MIN_LENGTH_PTC_0 0x8f8
#define MC_EMEM_ARB_OVERRIDE_1 0x968
#define MC_VIDEO_PROTECT_GPU_OVERRIDE_0 0x984
#define MC_VIDEO_PROTECT_GPU_OVERRIDE_1 0x988
#define MC_EMEM_ARB_STATS_0 0x990
#define MC_EMEM_ARB_STATS_1 0x994
#define MC_MTS_CARVEOUT_BOM 0x9a0
#define MC_MTS_CARVEOUT_SIZE_MB 0x9a4
#define MC_MTS_CARVEOUT_ADR_HI 0x9a8
#define MC_MTS_CARVEOUT_REG_CTRL 0x9ac
#define MC_ERR_MTS_STATUS 0x9b0
#define MC_ERR_MTS_ADR 0x9b4
#define MC_ERR_GENERALIZED_CARVEOUT_STATUS 0xc00
#define MC_ERR_GENERALIZED_CARVEOUT_ADR 0xc04
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS2 0xd74
#define MC_SECURITY_CARVEOUT4_CFG0 0xcf8
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2 0xd10
#define MC_SECURITY_CARVEOUT4_SIZE_128KB 0xd04
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4 0xc28
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS1 0xc30
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4 0xc8c
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS0 0xd1c
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS1 0xd70
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS0 0xc2c
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS4 0xd7c
#define MC_SECURITY_CARVEOUT3_SIZE_128KB 0xcb4
#define MC_SECURITY_CARVEOUT2_CFG0 0xc58
#define MC_SECURITY_CARVEOUT1_CFG0 0xc08
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2 0xc84
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0 0xc68
#define MC_SECURITY_CARVEOUT3_BOM 0xcac
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2 0xc70
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS3 0xd78
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0 0xc7c
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4 0xd18
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1 0xcbc
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3 0xc38
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2 0xc34
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2 0xcc0
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2 0xd60
#define MC_SECURITY_CARVEOUT3_CFG0 0xca8
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0 0xcb8
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3 0xc88
#define MC_SECURITY_CARVEOUT2_SIZE_128KB 0xc64
#define MC_SECURITY_CARVEOUT5_BOM_HI 0xd50
#define MC_SECURITY_CARVEOUT1_SIZE_128KB 0xc14
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS3 0xd14
#define MC_SECURITY_CARVEOUT1_BOM 0xc0c
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4 0xd2c
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS4 0xd68
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4 0xcc8
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS0 0xd58
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS2 0xd24
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3 0xcc4
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4 0xc78
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1 0xc1c
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0 0xc18
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3 0xd28
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS1 0xd5c
#define MC_SECURITY_CARVEOUT3_BOM_HI 0xcb0
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3 0xcd8
#define MC_SECURITY_CARVEOUT2_BOM_HI 0xc60
#define MC_SECURITY_CARVEOUT4_BOM_HI 0xd00
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS3 0xd64
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4 0xcdc
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1 0xc80
#define MC_SECURITY_CARVEOUT5_SIZE_128KB 0xd54
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS1 0xd20
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2 0xcd4
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS1 0xd0c
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3 0xc74
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0 0xccc
#define MC_SECURITY_CARVEOUT4_BOM 0xcfc
#define MC_SECURITY_CARVEOUT5_CFG0 0xd48
#define MC_SECURITY_CARVEOUT2_BOM 0xc5c
#define MC_SECURITY_CARVEOUT5_BOM 0xd4c
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3 0xc24
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS0 0xd6c
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1 0xcd0
#define MC_SECURITY_CARVEOUT1_BOM_HI 0xc10
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2 0xc20
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4 0xc3c
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1 0xc6c
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0 0xd08
#define MC_ERR_APB_ASID_UPDATE_STATUS 0x9d0
#define MC_DA_CONFIG0 0x9dc
#define MC_UNTRANSLATED_REGION_CHECK 0x948
/* Memory Controller clients */
#define CLIENT_ACCESS_NUM_CLIENTS 32
typedef enum {
/* _ACCESS0 */
CSR_PTCR = (0 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_DISPLAY0A = (1 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_DISPLAY0AB = (2 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_DISPLAY0B = (3 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_DISPLAY0BB = (4 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_DISPLAY0C = (5 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_DISPLAY0CB = (6 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_AFIR = (14 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_AVPCARM7R = (15 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_DISPLAYHC = (16 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_DISPLAYHCB = (17 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_HDAR = (21 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_HOST1XDMAR = (22 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_HOST1XR = (23 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_NVENCSRD = (28 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_PPCSAHBDMAR = (29 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_PPCSAHBSLVR = (30 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
CSR_SATAR = (31 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
/* _ACCESS1 */
CSR_VDEBSEVR = (34 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSR_VDEMBER = (35 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSR_VDEMCER = (36 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSR_VDETPER = (37 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSR_MPCORELPR = (38 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSR_MPCORER = (39 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSW_NVENCSWR = (43 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSW_AFIW = (49 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSW_AVPCARM7W = (50 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSW_HDAW = (53 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSW_HOST1XW = (54 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSW_MPCORELPW = (56 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSW_MPCOREW = (57 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSW_PPCSAHBDMAW = (59 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSW_PPCSAHBSLVW = (60 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSW_SATAW = (61 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSW_VDEBSEVW = (62 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
CSW_VDEDBGW = (63 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
/* _ACCESS2 */
CSW_VDEMBEW = (64 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSW_VDETPMW = (65 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSR_ISPRA = (68 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSW_ISPWA = (70 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSW_ISPWB = (71 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSR_XUSB_HOSTR = (74 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSW_XUSB_HOSTW = (75 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSR_XUSB_DEVR = (76 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSW_XUSB_DEVW = (77 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSR_ISPRAB = (78 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSW_ISPWAB = (80 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSW_ISPWBB = (81 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSR_TSECSRD = (84 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSW_TSECSWR = (85 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSR_A9AVPSCR = (86 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSW_A9AVPSCW = (87 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSR_GPUSRD = (88 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSW_GPUSWR = (89 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
CSR_DISPLAYT = (90 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
/* _ACCESS3 */
CSR_SDMMCRA = (96 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSR_SDMMCRAA = (97 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSR_SDMMCR = (98 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSR_SDMMCRAB = (99 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSW_SDMMCWA = (100 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSW_SDMMCWAA = (101 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSW_SDMMCW = (102 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSW_SDMMCWAB = (103 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSR_VICSRD = (108 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSW_VICSWR = (109 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSW_VIW = (114 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSR_DISPLAYD = (115 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSR_NVDECSRD = (120 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSW_NVDECSWR = (121 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSR_APER = (122 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSW_APEW = (123 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSR_NVJPGSRD = (126 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
CSW_NVJPGSWR = (127 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
/* _ACCESS4 */
CSR_SESRD = (128 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
CSW_SESWR = (129 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
CSR_AXIAPR = (130 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
CSW_AXIAPW = (131 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
CSR_ETRR = (132 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
CSW_ETRW = (133 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
CSR_TSECSRDB = (134 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
CSW_TSECSWRB = (135 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
CSR_GPUSRD2 = (136 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
CSW_GPUSWR2 = (137 - (CLIENT_ACCESS_NUM_CLIENTS * 4))
} McClient;
void mc_enable_for_tsec();
#endif

View File

@ -1,93 +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 "panic.h"
#include "di.h"
#include "pmc.h"
#include "fuse.h"
#include "utils.h"
static uint32_t g_panic_code = 0;
void check_panic(void) {
/* We also handle our own panics. */
/* In the case of our own panics, we assume that the display has already been initialized. */
bool has_panic = APBDEV_PMC_RST_STATUS_0 != 0 || g_panic_code != 0;
uint32_t code = g_panic_code == 0 ? APBDEV_PMC_SCRATCH200_0 : g_panic_code;
has_panic = has_panic && !(APBDEV_PMC_RST_STATUS_0 != 1 && code == PANIC_CODE_SAFEMODE);
if (has_panic) {
uint32_t color;
/* Check for predefined codes: */
switch (code & MASK(20)) {
case 0x01: /* Package2 signature verification failed. */
case 0x02: /* Package2 meta verification failed. */
case 0x03: /* Package2 version check failed. */
case 0x04: /* Package2 payload verification failed. */
color = PANIC_COLOR_KERNEL;
break;
case 0x05: /* Unknown SMC. */
case 0x06: /* Unknown Abort. */
color = PANIC_COLOR_SECMON_GENERIC;
break;
case 0x07: /* Invalid CPU context. */
case 0x08: /* Invalid SE state. */
case 0x09: /* CPU is already awake (2.0.0+). */
color = PANIC_COLOR_SECMON_DEEPSLEEP;
break;
case 0x10: /* Unknown exception. */
color = PANIC_COLOR_SECMON_EXCEPTION;
break;
case 0x30: /* General bootloader error. */
case 0x31: /* Invalid DRAM ID. */
case 0x32: /* Invalid size. */
case 0x33: /* Invalid arguement. */
case 0x34: /* Bad GPT. */
case 0x35: /* Failed to boot SafeMode. */
case 0x36: /* Activity monitor fired (4.0.0+). */
color = PANIC_COLOR_BOOTLOADER_GENERIC;
break;
case 0x40: /* Kernel panic. */
color = PANIC_COLOR_KERNEL;
break;
default:
color = code >> 20;
color |= color << 4;
break;
}
wait_for_button_and_reboot();
} else {
g_panic_code = 0;
APBDEV_PMC_SCRATCH200_0 = 0;
}
}
__attribute__ ((noreturn)) void panic(uint32_t code) {
/* Set panic code. */
if (g_panic_code == 0) {
g_panic_code = code;
APBDEV_PMC_SCRATCH200_0 = code;
}
fuse_disable_programming();
APBDEV_PMC_CRYPTO_OP_0 = 1; /* Disable all SE operations. */
check_panic();
while(true);
}

View File

@ -1,34 +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/>.
*/
#ifndef FUSEE_PANIC_H
#define FUSEE_PANIC_H
#include <stdint.h>
#define PANIC_COLOR_KERNEL 0x0000FF
#define PANIC_COLOR_SECMON_EXCEPTION 0xFF7700
#define PANIC_COLOR_SECMON_GENERIC 0x00FFFF
#define PANIC_COLOR_SECMON_DEEPSLEEP 0xFF77FF /* 4.0+ color */
#define PANIC_COLOR_BOOTLOADER_GENERIC 0xAA00FF
#define PANIC_COLOR_BOOTLOADER_SAFEMODE 0xFFFFAA /* Removed */
#define PANIC_CODE_SAFEMODE 0x00000020
void check_and_display_panic(void);
__attribute__ ((noreturn)) void panic(uint32_t code);
#endif

View File

@ -1,211 +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/>.
*/
#ifndef FUSEE_PINMUX_H
#define FUSEE_PINMUX_H
#define PINMUX_BASE 0x70003000
#define MAKE_PINMUX_REG(n) MAKE_REG32(PINMUX_BASE + n)
#define PINMUX_TRISTATE (1 << 4)
#define PINMUX_PARKED (1 << 5)
#define PINMUX_INPUT (1 << 6)
#define PINMUX_PULL_NONE (0 << 2)
#define PINMUX_PULL_DOWN (1 << 2)
#define PINMUX_PULL_UP (2 << 2)
#define PINMUX_SELECT_FUNCTION0 0
#define PINMUX_SELECT_FUNCTION1 1
#define PINMUX_SELECT_FUNCTION2 2
#define PINMUX_SELECT_FUNCTION3 3
#define PINMUX_DRIVE_1X (0 << 13)
#define PINMUX_DRIVE_2X (1 << 13)
#define PINMUX_DRIVE_3X (2 << 13)
#define PINMUX_DRIVE_4X (3 << 13)
typedef struct {
uint32_t sdmmc1_clk;
uint32_t sdmmc1_cmd;
uint32_t sdmmc1_dat3;
uint32_t sdmmc1_dat2;
uint32_t sdmmc1_dat1;
uint32_t sdmmc1_dat0;
uint32_t _r18;
uint32_t sdmmc3_clk;
uint32_t sdmmc3_cmd;
uint32_t sdmmc3_dat0;
uint32_t sdmmc3_dat1;
uint32_t sdmmc3_dat2;
uint32_t sdmmc3_dat3;
uint32_t _r34;
uint32_t pex_l0_rst_n;
uint32_t pex_l0_clkreq_n;
uint32_t pex_wake_n;
uint32_t pex_l1_rst_n;
uint32_t pex_l1_clkreq_n;
uint32_t sata_led_active;
uint32_t spi1_mosi;
uint32_t spi1_miso;
uint32_t spi1_sck;
uint32_t spi1_cs0;
uint32_t spi1_cs1;
uint32_t spi2_mosi;
uint32_t spi2_miso;
uint32_t spi2_sck;
uint32_t spi2_cs0;
uint32_t spi2_cs1;
uint32_t spi4_mosi;
uint32_t spi4_miso;
uint32_t spi4_sck;
uint32_t spi4_cs0;
uint32_t qspi_sck;
uint32_t qspi_cs_n;
uint32_t qspi_io0;
uint32_t qspi_io1;
uint32_t qspi_io2;
uint32_t qspi_io3;
uint32_t _ra0;
uint32_t dmic1_clk;
uint32_t dmic1_dat;
uint32_t dmic2_clk;
uint32_t dmic2_dat;
uint32_t dmic3_clk;
uint32_t dmic3_dat;
uint32_t gen1_i2c_scl;
uint32_t gen1_i2c_sda;
uint32_t gen2_i2c_scl;
uint32_t gen2_i2c_sda;
uint32_t gen3_i2c_scl;
uint32_t gen3_i2c_sda;
uint32_t cam_i2c_scl;
uint32_t cam_i2c_sda;
uint32_t pwr_i2c_scl;
uint32_t pwr_i2c_sda;
uint32_t uart1_tx;
uint32_t uart1_rx;
uint32_t uart1_rts;
uint32_t uart1_cts;
uint32_t uart2_tx;
uint32_t uart2_rx;
uint32_t uart2_rts;
uint32_t uart2_cts;
uint32_t uart3_tx;
uint32_t uart3_rx;
uint32_t uart3_rts;
uint32_t uart3_cts;
uint32_t uart4_tx;
uint32_t uart4_rx;
uint32_t uart4_rts;
uint32_t uart4_cts;
uint32_t dap1_fs;
uint32_t dap1_din;
uint32_t dap1_dout;
uint32_t dap1_sclk;
uint32_t dap2_fs;
uint32_t dap2_din;
uint32_t dap2_dout;
uint32_t dap2_sclk;
uint32_t dap4_fs;
uint32_t dap4_din;
uint32_t dap4_dout;
uint32_t dap4_sclk;
uint32_t cam1_mclk;
uint32_t cam2_mclk;
uint32_t jtag_rtck;
uint32_t clk_32k_in;
uint32_t clk_32k_out;
uint32_t batt_bcl;
uint32_t clk_req;
uint32_t cpu_pwr_req;
uint32_t pwr_int_n;
uint32_t shutdown;
uint32_t core_pwr_req;
uint32_t aud_mclk;
uint32_t dvfs_pwm;
uint32_t dvfs_clk;
uint32_t gpio_x1_aud;
uint32_t gpio_x3_aud;
uint32_t pcc7;
uint32_t hdmi_cec;
uint32_t hdmi_int_dp_hpd;
uint32_t spdif_out;
uint32_t spdif_in;
uint32_t usb_vbus_en0;
uint32_t usb_vbus_en1;
uint32_t dp_hpd0;
uint32_t wifi_en;
uint32_t wifi_rst;
uint32_t wifi_wake_ap;
uint32_t ap_wake_bt;
uint32_t bt_rst;
uint32_t bt_wake_ap;
uint32_t ap_wake_nfc;
uint32_t nfc_en;
uint32_t nfc_int;
uint32_t gps_en;
uint32_t gps_rst;
uint32_t cam_rst;
uint32_t cam_af_en;
uint32_t cam_flash_en;
uint32_t cam1_pwdn;
uint32_t cam2_pwdn;
uint32_t cam1_strobe;
uint32_t lcd_te;
uint32_t lcd_bl_pwm;
uint32_t lcd_bl_en;
uint32_t lcd_rst;
uint32_t lcd_gpio1;
uint32_t lcd_gpio2;
uint32_t ap_ready;
uint32_t touch_rst;
uint32_t touch_clk;
uint32_t modem_wake_ap;
uint32_t touch_int;
uint32_t motion_int;
uint32_t als_prox_int;
uint32_t temp_alert;
uint32_t button_power_on;
uint32_t button_vol_up;
uint32_t button_vol_down;
uint32_t button_slide_sw;
uint32_t button_home;
uint32_t pa6;
uint32_t pe6;
uint32_t pe7;
uint32_t ph6;
uint32_t pk0;
uint32_t pk1;
uint32_t pk2;
uint32_t pk3;
uint32_t pk4;
uint32_t pk5;
uint32_t pk6;
uint32_t pk7;
uint32_t pl0;
uint32_t pl1;
uint32_t pz0;
uint32_t pz1;
uint32_t pz2;
uint32_t pz3;
uint32_t pz4;
uint32_t pz5;
} tegra_pinmux_t;
static inline volatile tegra_pinmux_t *pinmux_get_regs(void)
{
return (volatile tegra_pinmux_t *)PINMUX_BASE;
}
#endif

View File

@ -1,713 +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/>.
*/
#ifndef FUSEE_PMC_H
#define FUSEE_PMC_H
#include <stdint.h>
#define PMC_BASE 0x7000E400
#define MAKE_PMC_REG(n) MAKE_REG32(PMC_BASE + n)
#define PMC_CONTROL_SDMMC1 (1 << 12)
#define PMC_CONTROL_SDMMC3 (1 << 13)
#define PMC_CONTROL_SDMMC4 (1 << 14)
#define APBDEV_PMC_CONTROL MAKE_PMC_REG(0x00)
#define APBDEV_PM_0 MAKE_PMC_REG(0x14)
#define APBDEV_PMC_DPD_ENABLE_0 MAKE_PMC_REG(0x24)
#define APBDEV_PMC_PWRGATE_TOGGLE_0 MAKE_PMC_REG(0x30)
#define APBDEV_PMC_PWRGATE_STATUS_0 MAKE_PMC_REG(0x38)
#define APBDEV_PMC_NO_IOPOWER_0 MAKE_PMC_REG(0x44)
#define APBDEV_PMC_SCRATCH0_0 MAKE_PMC_REG(0x50)
#define APBDEV_PMC_SCRATCH1_0 MAKE_PMC_REG(0x54)
#define APBDEV_PMC_SCRATCH20_0 MAKE_PMC_REG(0xA0)
#define APBDEV_PMC_PWR_DET_VAL_0 MAKE_PMC_REG(0xE4)
#define APBDEV_PMC_DDR_PWR_0 MAKE_PMC_REG(0xE8)
#define APBDEV_PMC_CRYPTO_OP_0 MAKE_PMC_REG(0xF4)
#define APBDEV_PMC_WAKE2_STATUS_0 MAKE_PMC_REG(0x168)
#define APBDEV_PMC_OSC_EDPD_OVER_0 MAKE_PMC_REG(0x1A4)
#define APBDEV_PMC_RST_STATUS_0 MAKE_PMC_REG(0x1B4)
#define APBDEV_PMC_IO_DPD_REQ_0 MAKE_PMC_REG(0x1B8)
#define APBDEV_PMC_IO_DPD2_REQ_0 MAKE_PMC_REG(0x1C0)
#define APBDEV_PMC_VDDP_SEL_0 MAKE_PMC_REG(0x1CC)
#define APBDEV_PMC_SCRATCH49_0 MAKE_PMC_REG(0x244)
#define APBDEV_PMC_TSC_MULT_0 MAKE_PMC_REG(0x2B4)
#define APBDEV_PMC_REG_SHORT_0 MAKE_PMC_REG(0x2CC)
#define APBDEV_PMC_WEAK_BIAS_0 MAKE_PMC_REG(0x2C8)
#define APBDEV_PMC_SECURE_SCRATCH21_0 MAKE_PMC_REG(0x334)
#define APBDEV_PMC_SECURE_SCRATCH32_0 MAKE_PMC_REG(0x360)
#define APBDEV_PMC_SECURE_SCRATCH49_0 MAKE_PMC_REG(0x3A4)
#define APBDEV_PMC_CNTRL2_0 MAKE_PMC_REG(0x440)
#define APBDEV_PMC_IO_DPD4_REQ_0 MAKE_PMC_REG(0x464)
#define APBDEV_PMC_UTMIP_PAD_CFG1_0 MAKE_PMC_REG(0x4C4)
#define APBDEV_PMC_UTMIP_PAD_CFG3_0 MAKE_PMC_REG(0x4CC)
#define APBDEV_PMC_DDR_CNTRL_0 MAKE_PMC_REG(0x4E4)
#define APBDEV_PMC_SCRATCH43_0 MAKE_PMC_REG(0x22C)
#define APBDEV_PMC_SCRATCH188_0 MAKE_PMC_REG(0x810)
#define APBDEV_PMC_SCRATCH190_0 MAKE_PMC_REG(0x818)
#define APBDEV_PMC_SCRATCH200_0 MAKE_PMC_REG(0x840)
#define APBDEV_PMC_SCRATCH45_0 MAKE_PMC_REG(0x234)
#define APBDEV_PMC_SCRATCH46_0 MAKE_PMC_REG(0x238)
#define APBDEV_PMC_SCRATCH33_0 MAKE_PMC_REG(0x120)
#define APBDEV_PMC_SCRATCH40_0 MAKE_PMC_REG(0x13C)
/* Power Management Controller (APBDEV_PMC_) regs */
typedef struct {
uint32_t cntrl; /* _CNTRL_0, 0x00 */
uint32_t sec_disable; /* _SEC_DISABLE_0, 0x04 */
uint32_t pmc_swrst; /* _PMC_SWRST_0, 0x08 */
uint32_t wake_mask; /* _WAKE_MASK_0, 0x0c */
uint32_t wake_lvl; /* _WAKE_LVL_0, 0x10 */
uint32_t wake_status; /* _WAKE_STATUS_0, 0x14 */
uint32_t sw_wake_status; /* _SW_WAKE_STATUS_0, 0x18 */
uint32_t dpd_pads_oride; /* _DPD_PADS_ORIDE_0, 0x1c */
uint32_t dpd_sample; /* _DPD_SAMPLE_0, 0x20 */
uint32_t dpd_enable; /* _DPD_ENABLE_0, 0x24 */
uint32_t pwrgate_timer_off; /* _PWRGATE_TIMER_OFF_0, 0x28 */
uint32_t clamp_status; /* _CLAMP_STATUS_0, 0x2c */
uint32_t pwrgate_toggle; /* _PWRGATE_TOGGLE_0, 0x30 */
uint32_t remove_clamping; /* _REMOVE_CLAMPING_0, 0x34 */
uint32_t pwrgate_status; /* _PWRGATE_STATUS_0, 0x38 */
uint32_t pwrgood_timer; /* _PWRGOOD_TIMER_0, 0x3c */
uint32_t blink_timer; /* _BLINK_TIMER_0, 0x40 */
uint32_t no_iopower; /* _NO_IOPOWER_0, 0x44 */
uint32_t pwr_det; /* _PWR_DET_0, 0x48 */
uint32_t pwr_det_latch; /* _PWR_DET_LATCH_0, 0x4c */
uint32_t scratch0; /* _SCRATCH0_0, 0x50 */
uint32_t scratch1; /* _SCRATCH1_0, 0x54 */
uint32_t scratch2; /* _SCRATCH2_0, 0x58 */
uint32_t scratch3; /* _SCRATCH3_0, 0x5c */
uint32_t scratch4; /* _SCRATCH4_0, 0x60 */
uint32_t scratch5; /* _SCRATCH5_0, 0x64 */
uint32_t scratch6; /* _SCRATCH6_0, 0x68 */
uint32_t scratch7; /* _SCRATCH7_0, 0x6c */
uint32_t scratch8; /* _SCRATCH8_0, 0x70 */
uint32_t scratch9; /* _SCRATCH9_0, 0x74 */
uint32_t scratch10; /* _SCRATCH10_0, 0x78 */
uint32_t scratch11; /* _SCRATCH11_0, 0x7c */
uint32_t scratch12; /* _SCRATCH12_0, 0x80 */
uint32_t scratch13; /* _SCRATCH13_0, 0x84 */
uint32_t scratch14; /* _SCRATCH14_0, 0x88 */
uint32_t scratch15; /* _SCRATCH15_0, 0x8c */
uint32_t scratch16; /* _SCRATCH16_0, 0x90 */
uint32_t scratch17; /* _SCRATCH17_0, 0x94 */
uint32_t scratch18; /* _SCRATCH18_0, 0x98 */
uint32_t scratch19; /* _SCRATCH19_0, 0x9c */
uint32_t scratch20; /* _SCRATCH20_0, 0xa0 */
uint32_t scratch21; /* _SCRATCH21_0, 0xa4 */
uint32_t scratch22; /* _SCRATCH22_0, 0xa8 */
uint32_t scratch23; /* _SCRATCH23_0, 0xac */
uint32_t secure_scratch0; /* _SECURE_SCRATCH0_0, 0xb0 */
uint32_t secure_scratch1; /* _SECURE_SCRATCH1_0, 0xb4 */
uint32_t secure_scratch2; /* _SECURE_SCRATCH2_0, 0xb8 */
uint32_t secure_scratch3; /* _SECURE_SCRATCH3_0, 0xbc */
uint32_t secure_scratch4; /* _SECURE_SCRATCH4_0, 0xc0 */
uint32_t secure_scratch5; /* _SECURE_SCRATCH5_0, 0xc4 */
uint32_t cpupwrgood_timer; /* _CPUPWRGOOD_TIMER_0, 0xc8 */
uint32_t cpupwroff_timer; /* _CPUPWROFF_TIMER_0, 0xcc */
uint32_t pg_mask; /* _PG_MASK_0, 0xd0 */
uint32_t pg_mask_1; /* _PG_MASK_1_0, 0xd4 */
uint32_t auto_wake_lvl; /* _AUTO_WAKE_LVL_0, 0xd8 */
uint32_t auto_wake_lvl_mask; /* _AUTO_WAKE_LVL_MASK_0, 0xdc */
uint32_t wake_delay; /* _WAKE_DELAY_0, 0xe0 */
uint32_t pwr_det_val; /* _PWR_DET_VAL_0, 0xe4 */
uint32_t ddr_pwr; /* _DDR_PWR_0, 0xe8 */
uint32_t usb_debounce_del; /* _USB_DEBOUNCE_DEL_0, 0xec */
uint32_t usb_ao; /* _USB_AO_0, 0xf0 */
uint32_t crypto_op; /* _CRYPTO_OP_0, 0xf4 */
uint32_t pllp_wb0_override; /* _PLLP_WB0_OVERRIDE_0, 0xf8 */
uint32_t scratch24; /* _SCRATCH24_0, 0xfc */
uint32_t scratch25; /* _SCRATCH25_0, 0x100 */
uint32_t scratch26; /* _SCRATCH26_0, 0x104 */
uint32_t scratch27; /* _SCRATCH27_0, 0x108 */
uint32_t scratch28; /* _SCRATCH28_0, 0x10c */
uint32_t scratch29; /* _SCRATCH29_0, 0x110 */
uint32_t scratch30; /* _SCRATCH30_0, 0x114 */
uint32_t scratch31; /* _SCRATCH31_0, 0x118 */
uint32_t scratch32; /* _SCRATCH32_0, 0x11c */
uint32_t scratch33; /* _SCRATCH33_0, 0x120 */
uint32_t scratch34; /* _SCRATCH34_0, 0x124 */
uint32_t scratch35; /* _SCRATCH35_0, 0x128 */
uint32_t scratch36; /* _SCRATCH36_0, 0x12c */
uint32_t scratch37; /* _SCRATCH37_0, 0x130 */
uint32_t scratch38; /* _SCRATCH38_0, 0x134 */
uint32_t scratch39; /* _SCRATCH39_0, 0x138 */
uint32_t scratch40; /* _SCRATCH40_0, 0x13c */
uint32_t scratch41; /* _SCRATCH41_0, 0x140 */
uint32_t scratch42; /* _SCRATCH42_0, 0x144 */
uint32_t bondout_mirror0; /* _BONDOUT_MIRROR0_0, 0x148 */
uint32_t bondout_mirror1; /* _BONDOUT_MIRROR1_0, 0x14c */
uint32_t bondout_mirror2; /* _BONDOUT_MIRROR2_0, 0x150 */
uint32_t sys_33v_en; /* _SYS_33V_EN_0, 0x154 */
uint32_t bondout_mirror_access; /* _BONDOUT_MIRROR_ACCESS_0, 0x158 */
uint32_t gate; /* _GATE_0, 0x15c */
uint32_t wake2_mask; /* _WAKE2_MASK_0, 0x160 */
uint32_t wake2_lvl; /* _WAKE2_LVL_0, 0x164 */
uint32_t wake2_status; /* _WAKE2_STATUS_0, 0x168 */
uint32_t sw_wake2_status; /* _SW_WAKE2_STATUS_0, 0x16c */
uint32_t auto_wake2_lvl_mask; /* _AUTO_WAKE2_LVL_MASK_0, 0x170 */
uint32_t pg_mask_2; /* _PG_MASK_2_0, 0x174 */
uint32_t pg_mask_ce1; /* _PG_MASK_CE1_0, 0x178 */
uint32_t pg_mask_ce2; /* _PG_MASK_CE2_0, 0x17c */
uint32_t pg_mask_ce3; /* _PG_MASK_CE3_0, 0x180 */
uint32_t pwrgate_timer_ce_0; /* _PWRGATE_TIMER_CE_0_0, 0x184 */
uint32_t pwrgate_timer_ce_1; /* _PWRGATE_TIMER_CE_1_0, 0x188 */
uint32_t pwrgate_timer_ce_2; /* _PWRGATE_TIMER_CE_2_0, 0x18c */
uint32_t pwrgate_timer_ce_3; /* _PWRGATE_TIMER_CE_3_0, 0x190 */
uint32_t pwrgate_timer_ce_4; /* _PWRGATE_TIMER_CE_4_0, 0x194 */
uint32_t pwrgate_timer_ce_5; /* _PWRGATE_TIMER_CE_5_0, 0x198 */
uint32_t pwrgate_timer_ce_6; /* _PWRGATE_TIMER_CE_6_0, 0x19c */
uint32_t pcx_edpd_cntrl; /* _PCX_EDPD_CNTRL_0, 0x1a0 */
uint32_t osc_edpd_over; /* _OSC_EDPD_OVER_0, 0x1a4 */
uint32_t clk_out_cntrl; /* _CLK_OUT_CNTRL_0, 0x1a8 */
uint32_t sata_pwrgt; /* _SATA_PWRGT_0, 0x1ac */
uint32_t sensor_ctrl; /* _SENSOR_CTRL_0, 0x1b0 */
uint32_t rst_status; /* _RST_STATUS_0, 0x1b4 */
uint32_t io_dpd_req; /* _IO_DPD_REQ_0, 0x1b8 */
uint32_t io_dpd_status; /* _IO_DPD_STATUS_0, 0x1bc */
uint32_t io_dpd2_req; /* _IO_DPD2_REQ_0, 0x1c0 */
uint32_t io_dpd2_status; /* _IO_DPD2_STATUS_0, 0x1c4 */
uint32_t sel_dpd_tim; /* _SEL_DPD_TIM_0, 0x1c8 */
uint32_t vddp_sel; /* _VDDP_SEL_0, 0x1cc */
uint32_t ddr_cfg; /* _DDR_CFG_0, 0x1d0 */
uint32_t _0x1d4[2];
uint32_t pllm_wb0_override_freq; /* _PLLM_WB0_OVERRIDE_FREQ_0, 0x1dc */
uint32_t _0x1e0;
uint32_t pwrgate_timer_mult; /* _PWRGATE_TIMER_MULT_0, 0x1e4 */
uint32_t dsi_sel_dpd; /* _DSI_SEL_DPD_0, 0x1e8 */
uint32_t utmip_uhsic_triggers; /* _UTMIP_UHSIC_TRIGGERS_0, 0x1ec */
uint32_t utmip_uhsic_saved_state; /* _UTMIP_UHSIC_SAVED_STATE_0, 0x1f0 */
uint32_t _0x1f4;
uint32_t utmip_term_pad_cfg; /* _UTMIP_TERM_PAD_CFG_0, 0x1f8 */
uint32_t utmip_uhsic_sleep_cfg; /* _UTMIP_UHSIC_SLEEP_CFG_0, 0x1fc */
uint32_t utmip_uhsic_sleepwalk_cfg; /* _UTMIP_UHSIC_SLEEPWALK_CFG_0, 0x200 */
uint32_t utmip_sleepwalk_p0; /* _UTMIP_SLEEPWALK_P0_0, 0x204 */
uint32_t utmip_sleepwalk_p1; /* _UTMIP_SLEEPWALK_P1_0, 0x208 */
uint32_t utmip_sleepwalk_p2; /* _UTMIP_SLEEPWALK_P2_0, 0x20c */
uint32_t uhsic_sleepwalk_p0; /* _UHSIC_SLEEPWALK_P0_0, 0x210 */
uint32_t utmip_uhsic_status; /* _UTMIP_UHSIC_STATUS_0, 0x214 */
uint32_t utmip_uhsic_fake; /* _UTMIP_UHSIC_FAKE_0, 0x218 */
uint32_t bondout_mirror3; /* _BONDOUT_MIRROR3_0, 0x21c */
uint32_t bondout_mirror4; /* _BONDOUT_MIRROR4_0, 0x220 */
uint32_t secure_scratch6; /* _SECURE_SCRATCH6_0, 0x224 */
uint32_t secure_scratch7; /* _SECURE_SCRATCH7_0, 0x228 */
uint32_t scratch43; /* _SCRATCH43_0, 0x22c */
uint32_t scratch44; /* _SCRATCH44_0, 0x230 */
uint32_t scratch45; /* _SCRATCH45_0, 0x234 */
uint32_t scratch46; /* _SCRATCH46_0, 0x238 */
uint32_t scratch47; /* _SCRATCH47_0, 0x23c */
uint32_t scratch48; /* _SCRATCH48_0, 0x240 */
uint32_t scratch49; /* _SCRATCH49_0, 0x244 */
uint32_t scratch50; /* _SCRATCH50_0, 0x248 */
uint32_t scratch51; /* _SCRATCH51_0, 0x24c */
uint32_t scratch52; /* _SCRATCH52_0, 0x250 */
uint32_t scratch53; /* _SCRATCH53_0, 0x254 */
uint32_t scratch54; /* _SCRATCH54_0, 0x258 */
uint32_t scratch55; /* _SCRATCH55_0, 0x25c */
uint32_t scratch0_eco; /* _SCRATCH0_ECO_0, 0x260 */
uint32_t por_dpd_ctrl; /* _POR_DPD_CTRL_0, 0x264 */
uint32_t scratch2_eco; /* _SCRATCH2_ECO_0, 0x268 */
uint32_t utmip_uhsic_line_wakeup; /* _UTMIP_UHSIC_LINE_WAKEUP_0, 0x26c */
uint32_t utmip_bias_master_cntrl; /* _UTMIP_BIAS_MASTER_CNTRL_0, 0x270 */
uint32_t utmip_master_config; /* _UTMIP_MASTER_CONFIG_0, 0x274 */
uint32_t td_pwrgate_inter_part_timer; /* _TD_PWRGATE_INTER_PART_TIMER_0, 0x278 */
uint32_t utmip_uhsic2_triggers; /* _UTMIP_UHSIC2_TRIGGERS_0, 0x27c */
uint32_t utmip_uhsic2_saved_state; /* _UTMIP_UHSIC2_SAVED_STATE_0, 0x280 */
uint32_t utmip_uhsic2_sleep_cfg; /* _UTMIP_UHSIC2_SLEEP_CFG_0, 0x284 */
uint32_t utmip_uhsic2_sleepwalk_cfg; /* _UTMIP_UHSIC2_SLEEPWALK_CFG_0, 0x288 */
uint32_t uhsic2_sleepwalk_p1; /* _UHSIC2_SLEEPWALK_P1_0, 0x28c */
uint32_t utmip_uhsic2_status; /* _UTMIP_UHSIC2_STATUS_0, 0x290 */
uint32_t utmip_uhsic2_fake; /* _UTMIP_UHSIC2_FAKE_0, 0x294 */
uint32_t utmip_uhsic2_line_wakeup; /* _UTMIP_UHSIC2_LINE_WAKEUP_0, 0x298 */
uint32_t utmip_master2_config; /* _UTMIP_MASTER2_CONFIG_0, 0x29c */
uint32_t utmip_uhsic_rpd_cfg; /* _UTMIP_UHSIC_RPD_CFG_0, 0x2a0 */
uint32_t pg_mask_ce0; /* _PG_MASK_CE0_0, 0x2a4 */
uint32_t pg_mask_3; /* _PG_MASK_3_0, 0x2a8 */
uint32_t pg_mask_4; /* _PG_MASK_4_0, 0x2ac */
uint32_t pllm_wb0_override2; /* _PLLM_WB0_OVERRIDE2_0, 0x2b0 */
uint32_t tsc_mult; /* _TSC_MULT_0, 0x2b4 */
uint32_t cpu_vsense_override; /* _CPU_VSENSE_OVERRIDE_0, 0x2b8 */
uint32_t glb_amap_cfg; /* _GLB_AMAP_CFG_0, 0x2bc */
uint32_t sticky_bits; /* _STICKY_BITS_0, 0x2c0 */
uint32_t sec_disable2; /* _SEC_DISABLE2_0, 0x2c4 */
uint32_t weak_bias; /* _WEAK_BIAS_0, 0x2c8 */
uint32_t reg_short; /* _REG_SHORT_0, 0x2cc */
uint32_t pg_mask_andor; /* _PG_MASK_ANDOR_0, 0x2d0 */
uint32_t gpu_rg_cntrl; /* _GPU_RG_CNTRL_0, 0x2d4 */
uint32_t sec_disable3; /* _SEC_DISABLE3_0, 0x2d8 */
uint32_t pg_mask_5; /* _PG_MASK_5_0, 0x2dc */
uint32_t pg_mask_6; /* _PG_MASK_6_0, 0x2e0 */
uint32_t _0x2e4[7];
uint32_t secure_scratch8; /* _SECURE_SCRATCH8_0, 0x300 */
uint32_t secure_scratch9; /* _SECURE_SCRATCH9_0, 0x304 */
uint32_t secure_scratch10; /* _SECURE_SCRATCH10_0, 0x308 */
uint32_t secure_scratch11; /* _SECURE_SCRATCH11_0, 0x30c */
uint32_t secure_scratch12; /* _SECURE_SCRATCH12_0, 0x310 */
uint32_t secure_scratch13; /* _SECURE_SCRATCH13_0, 0x314 */
uint32_t secure_scratch14; /* _SECURE_SCRATCH14_0, 0x318 */
uint32_t secure_scratch15; /* _SECURE_SCRATCH15_0, 0x31c */
uint32_t secure_scratch16; /* _SECURE_SCRATCH16_0, 0x320 */
uint32_t secure_scratch17; /* _SECURE_SCRATCH17_0, 0x324 */
uint32_t secure_scratch18; /* _SECURE_SCRATCH18_0, 0x328 */
uint32_t secure_scratch19; /* _SECURE_SCRATCH19_0, 0x32c */
uint32_t secure_scratch20; /* _SECURE_SCRATCH20_0, 0x330 */
uint32_t secure_scratch21; /* _SECURE_SCRATCH21_0, 0x334 */
uint32_t secure_scratch22; /* _SECURE_SCRATCH22_0, 0x338 */
uint32_t secure_scratch23; /* _SECURE_SCRATCH23_0, 0x33c */
uint32_t secure_scratch24; /* _SECURE_SCRATCH24_0, 0x340 */
uint32_t secure_scratch25; /* _SECURE_SCRATCH25_0, 0x344 */
uint32_t secure_scratch26; /* _SECURE_SCRATCH26_0, 0x348 */
uint32_t secure_scratch27; /* _SECURE_SCRATCH27_0, 0x34c */
uint32_t secure_scratch28; /* _SECURE_SCRATCH28_0, 0x350 */
uint32_t secure_scratch29; /* _SECURE_SCRATCH29_0, 0x354 */
uint32_t secure_scratch30; /* _SECURE_SCRATCH30_0, 0x358 */
uint32_t secure_scratch31; /* _SECURE_SCRATCH31_0, 0x35c */
uint32_t secure_scratch32; /* _SECURE_SCRATCH32_0, 0x360 */
uint32_t secure_scratch33; /* _SECURE_SCRATCH33_0, 0x364 */
uint32_t secure_scratch34; /* _SECURE_SCRATCH34_0, 0x368 */
uint32_t secure_scratch35; /* _SECURE_SCRATCH35_0, 0x36c */
uint32_t secure_scratch36; /* _SECURE_SCRATCH36_0, 0x370 */
uint32_t secure_scratch37; /* _SECURE_SCRATCH37_0, 0x374 */
uint32_t secure_scratch38; /* _SECURE_SCRATCH38_0, 0x378 */
uint32_t secure_scratch39; /* _SECURE_SCRATCH39_0, 0x37c */
uint32_t secure_scratch40; /* _SECURE_SCRATCH40_0, 0x380 */
uint32_t secure_scratch41; /* _SECURE_SCRATCH41_0, 0x384 */
uint32_t secure_scratch42; /* _SECURE_SCRATCH42_0, 0x388 */
uint32_t secure_scratch43; /* _SECURE_SCRATCH43_0, 0x38c */
uint32_t secure_scratch44; /* _SECURE_SCRATCH44_0, 0x390 */
uint32_t secure_scratch45; /* _SECURE_SCRATCH45_0, 0x394 */
uint32_t secure_scratch46; /* _SECURE_SCRATCH46_0, 0x398 */
uint32_t secure_scratch47; /* _SECURE_SCRATCH47_0, 0x39c */
uint32_t secure_scratch48; /* _SECURE_SCRATCH48_0, 0x3a0 */
uint32_t secure_scratch49; /* _SECURE_SCRATCH49_0, 0x3a4 */
uint32_t secure_scratch50; /* _SECURE_SCRATCH50_0, 0x3a8 */
uint32_t secure_scratch51; /* _SECURE_SCRATCH51_0, 0x3ac */
uint32_t secure_scratch52; /* _SECURE_SCRATCH52_0, 0x3b0 */
uint32_t secure_scratch53; /* _SECURE_SCRATCH53_0, 0x3b4 */
uint32_t secure_scratch54; /* _SECURE_SCRATCH54_0, 0x3b8 */
uint32_t secure_scratch55; /* _SECURE_SCRATCH55_0, 0x3bc */
uint32_t secure_scratch56; /* _SECURE_SCRATCH56_0, 0x3c0 */
uint32_t secure_scratch57; /* _SECURE_SCRATCH57_0, 0x3c4 */
uint32_t secure_scratch58; /* _SECURE_SCRATCH58_0, 0x3c8 */
uint32_t secure_scratch59; /* _SECURE_SCRATCH59_0, 0x3cc */
uint32_t secure_scratch60; /* _SECURE_SCRATCH60_0, 0x3d0 */
uint32_t secure_scratch61; /* _SECURE_SCRATCH61_0, 0x3d4 */
uint32_t secure_scratch62; /* _SECURE_SCRATCH62_0, 0x3d8 */
uint32_t secure_scratch63; /* _SECURE_SCRATCH63_0, 0x3dc */
uint32_t secure_scratch64; /* _SECURE_SCRATCH64_0, 0x3e0 */
uint32_t secure_scratch65; /* _SECURE_SCRATCH65_0, 0x3e4 */
uint32_t secure_scratch66; /* _SECURE_SCRATCH66_0, 0x3e8 */
uint32_t secure_scratch67; /* _SECURE_SCRATCH67_0, 0x3ec */
uint32_t secure_scratch68; /* _SECURE_SCRATCH68_0, 0x3f0 */
uint32_t secure_scratch69; /* _SECURE_SCRATCH69_0, 0x3f4 */
uint32_t secure_scratch70; /* _SECURE_SCRATCH70_0, 0x3f8 */
uint32_t secure_scratch71; /* _SECURE_SCRATCH71_0, 0x3fc */
uint32_t secure_scratch72; /* _SECURE_SCRATCH72_0, 0x400 */
uint32_t secure_scratch73; /* _SECURE_SCRATCH73_0, 0x404 */
uint32_t secure_scratch74; /* _SECURE_SCRATCH74_0, 0x408 */
uint32_t secure_scratch75; /* _SECURE_SCRATCH75_0, 0x40c */
uint32_t secure_scratch76; /* _SECURE_SCRATCH76_0, 0x410 */
uint32_t secure_scratch77; /* _SECURE_SCRATCH77_0, 0x414 */
uint32_t secure_scratch78; /* _SECURE_SCRATCH78_0, 0x418 */
uint32_t secure_scratch79; /* _SECURE_SCRATCH79_0, 0x41c */
uint32_t _0x420[8];
uint32_t cntrl2; /* _CNTRL2_0, 0x440 */
uint32_t io_dpd_off_mask; /* _IO_DPD_OFF_MASK_0, 0x444 */
uint32_t io_dpd2_off_mask; /* _IO_DPD2_OFF_MASK_0, 0x448 */
uint32_t event_counter; /* _EVENT_COUNTER_0, 0x44c */
uint32_t fuse_control; /* _FUSE_CONTROL_0, 0x450 */
uint32_t scratch1_eco; /* _SCRATCH1_ECO_0, 0x454 */
uint32_t _0x458;
uint32_t io_dpd3_req; /* _IO_DPD3_REQ_0, 0x45c */
uint32_t io_dpd3_status; /* _IO_DPD3_STATUS_0, 0x460 */
uint32_t io_dpd4_req; /* _IO_DPD4_REQ_0, 0x464 */
uint32_t io_dpd4_status; /* _IO_DPD4_STATUS_0, 0x468 */
uint32_t _0x46c[2];
uint32_t direct_thermtrip_cfg; /* _DIRECT_THERMTRIP_CFG_0, 0x474 */
uint32_t tsosc_delay; /* _TSOSC_DELAY_0, 0x478 */
uint32_t set_sw_clamp; /* _SET_SW_CLAMP_0, 0x47c */
uint32_t debug_authentication; /* _DEBUG_AUTHENTICATION_0, 0x480 */
uint32_t aotag_cfg; /* _AOTAG_CFG_0, 0x484 */
uint32_t aotag_thresh1_cfg; /* _AOTAG_THRESH1_CFG_0, 0x488 */
uint32_t aotag_thresh2_cfg; /* _AOTAG_THRESH2_CFG_0, 0x48c */
uint32_t aotag_thresh3_cfg; /* _AOTAG_THRESH3_CFG_0, 0x490 */
uint32_t aotag_status; /* _AOTAG_STATUS_0, 0x494 */
uint32_t aotag_security; /* _AOTAG_SECURITY_0, 0x498 */
uint32_t tsensor_config0; /* _TSENSOR_CONFIG0_0, 0x49c */
uint32_t tsensor_config1; /* _TSENSOR_CONFIG1_0, 0x4a0 */
uint32_t tsensor_config2; /* _TSENSOR_CONFIG2_0, 0x4a4 */
uint32_t tsensor_status0; /* _TSENSOR_STATUS0_0, 0x4a8 */
uint32_t tsensor_status1; /* _TSENSOR_STATUS1_0, 0x4ac */
uint32_t tsensor_status2; /* _TSENSOR_STATUS2_0, 0x4b0 */
uint32_t tsensor_pdiv; /* _TSENSOR_PDIV_0, 0x4b4 */
uint32_t aotag_intr_en; /* _AOTAG_INTR_EN_0, 0x4b8 */
uint32_t aotag_intr_dis; /* _AOTAG_INTR_DIS_0, 0x4bc */
uint32_t utmip_pad_cfg0; /* _UTMIP_PAD_CFG0_0, 0x4c0 */
uint32_t utmip_pad_cfg1; /* _UTMIP_PAD_CFG1_0, 0x4c4 */
uint32_t utmip_pad_cfg2; /* _UTMIP_PAD_CFG2_0, 0x4c8 */
uint32_t utmip_pad_cfg3; /* _UTMIP_PAD_CFG3_0, 0x4cc */
uint32_t utmip_uhsic_sleep_cfg1; /* _UTMIP_UHSIC_SLEEP_CFG1_0, 0x4d0 */
uint32_t cc4_hvc_control; /* _CC4_HVC_CONTROL_0, 0x4d4 */
uint32_t wake_debounce_en; /* _WAKE_DEBOUNCE_EN_0, 0x4d8 */
uint32_t ramdump_ctl_status; /* _RAMDUMP_CTL_STATUS_0, 0x4dc */
uint32_t utmip_sleepwalk_p3; /* _UTMIP_SLEEPWALK_P3_0, 0x4e0 */
uint32_t ddr_cntrl; /* _DDR_CNTRL_0, 0x4e4 */
uint32_t _0x4e8[50];
uint32_t sec_disable4; /* _SEC_DISABLE4_0, 0x5b0 */
uint32_t sec_disable5; /* _SEC_DISABLE5_0, 0x5b4 */
uint32_t sec_disable6; /* _SEC_DISABLE6_0, 0x5b8 */
uint32_t sec_disable7; /* _SEC_DISABLE7_0, 0x5bc */
uint32_t sec_disable8; /* _SEC_DISABLE8_0, 0x5c0 */
uint32_t sec_disable9; /* _SEC_DISABLE9_0, 0x5c4 */
uint32_t sec_disable10; /* _SEC_DISABLE10_0, 0x5c8 */
uint32_t _0x5cc[13];
uint32_t scratch56; /* _SCRATCH56_0, 0x600 */
uint32_t scratch57; /* _SCRATCH57_0, 0x604 */
uint32_t scratch58; /* _SCRATCH58_0, 0x608 */
uint32_t scratch59; /* _SCRATCH59_0, 0x60c */
uint32_t scratch60; /* _SCRATCH60_0, 0x610 */
uint32_t scratch61; /* _SCRATCH61_0, 0x614 */
uint32_t scratch62; /* _SCRATCH62_0, 0x618 */
uint32_t scratch63; /* _SCRATCH63_0, 0x61c */
uint32_t scratch64; /* _SCRATCH64_0, 0x620 */
uint32_t scratch65; /* _SCRATCH65_0, 0x624 */
uint32_t scratch66; /* _SCRATCH66_0, 0x628 */
uint32_t scratch67; /* _SCRATCH67_0, 0x62c */
uint32_t scratch68; /* _SCRATCH68_0, 0x630 */
uint32_t scratch69; /* _SCRATCH69_0, 0x634 */
uint32_t scratch70; /* _SCRATCH70_0, 0x638 */
uint32_t scratch71; /* _SCRATCH71_0, 0x63c */
uint32_t scratch72; /* _SCRATCH72_0, 0x640 */
uint32_t scratch73; /* _SCRATCH73_0, 0x644 */
uint32_t scratch74; /* _SCRATCH74_0, 0x648 */
uint32_t scratch75; /* _SCRATCH75_0, 0x64c */
uint32_t scratch76; /* _SCRATCH76_0, 0x650 */
uint32_t scratch77; /* _SCRATCH77_0, 0x654 */
uint32_t scratch78; /* _SCRATCH78_0, 0x658 */
uint32_t scratch79; /* _SCRATCH79_0, 0x65c */
uint32_t scratch80; /* _SCRATCH80_0, 0x660 */
uint32_t scratch81; /* _SCRATCH81_0, 0x664 */
uint32_t scratch82; /* _SCRATCH82_0, 0x668 */
uint32_t scratch83; /* _SCRATCH83_0, 0x66c */
uint32_t scratch84; /* _SCRATCH84_0, 0x670 */
uint32_t scratch85; /* _SCRATCH85_0, 0x674 */
uint32_t scratch86; /* _SCRATCH86_0, 0x678 */
uint32_t scratch87; /* _SCRATCH87_0, 0x67c */
uint32_t scratch88; /* _SCRATCH88_0, 0x680 */
uint32_t scratch89; /* _SCRATCH89_0, 0x684 */
uint32_t scratch90; /* _SCRATCH90_0, 0x688 */
uint32_t scratch91; /* _SCRATCH91_0, 0x68c */
uint32_t scratch92; /* _SCRATCH92_0, 0x690 */
uint32_t scratch93; /* _SCRATCH93_0, 0x694 */
uint32_t scratch94; /* _SCRATCH94_0, 0x698 */
uint32_t scratch95; /* _SCRATCH95_0, 0x69c */
uint32_t scratch96; /* _SCRATCH96_0, 0x6a0 */
uint32_t scratch97; /* _SCRATCH97_0, 0x6a4 */
uint32_t scratch98; /* _SCRATCH98_0, 0x6a8 */
uint32_t scratch99; /* _SCRATCH99_0, 0x6ac */
uint32_t scratch100; /* _SCRATCH100_0, 0x6b0 */
uint32_t scratch101; /* _SCRATCH101_0, 0x6b4 */
uint32_t scratch102; /* _SCRATCH102_0, 0x6b8 */
uint32_t scratch103; /* _SCRATCH103_0, 0x6bc */
uint32_t scratch104; /* _SCRATCH104_0, 0x6c0 */
uint32_t scratch105; /* _SCRATCH105_0, 0x6c4 */
uint32_t scratch106; /* _SCRATCH106_0, 0x6c8 */
uint32_t scratch107; /* _SCRATCH107_0, 0x6cc */
uint32_t scratch108; /* _SCRATCH108_0, 0x6d0 */
uint32_t scratch109; /* _SCRATCH109_0, 0x6d4 */
uint32_t scratch110; /* _SCRATCH110_0, 0x6d8 */
uint32_t scratch111; /* _SCRATCH111_0, 0x6dc */
uint32_t scratch112; /* _SCRATCH112_0, 0x6e0 */
uint32_t scratch113; /* _SCRATCH113_0, 0x6e4 */
uint32_t scratch114; /* _SCRATCH114_0, 0x6e8 */
uint32_t scratch115; /* _SCRATCH115_0, 0x6ec */
uint32_t scratch116; /* _SCRATCH116_0, 0x6f0 */
uint32_t scratch117; /* _SCRATCH117_0, 0x6f4 */
uint32_t scratch118; /* _SCRATCH118_0, 0x6f8 */
uint32_t scratch119; /* _SCRATCH119_0, 0x6fc */
uint32_t scratch120; /* _SCRATCH120_0, 0x700 */
uint32_t scratch121; /* _SCRATCH121_0, 0x704 */
uint32_t scratch122; /* _SCRATCH122_0, 0x708 */
uint32_t scratch123; /* _SCRATCH123_0, 0x70c */
uint32_t scratch124; /* _SCRATCH124_0, 0x710 */
uint32_t scratch125; /* _SCRATCH125_0, 0x714 */
uint32_t scratch126; /* _SCRATCH126_0, 0x718 */
uint32_t scratch127; /* _SCRATCH127_0, 0x71c */
uint32_t scratch128; /* _SCRATCH128_0, 0x720 */
uint32_t scratch129; /* _SCRATCH129_0, 0x724 */
uint32_t scratch130; /* _SCRATCH130_0, 0x728 */
uint32_t scratch131; /* _SCRATCH131_0, 0x72c */
uint32_t scratch132; /* _SCRATCH132_0, 0x730 */
uint32_t scratch133; /* _SCRATCH133_0, 0x734 */
uint32_t scratch134; /* _SCRATCH134_0, 0x738 */
uint32_t scratch135; /* _SCRATCH135_0, 0x73c */
uint32_t scratch136; /* _SCRATCH136_0, 0x740 */
uint32_t scratch137; /* _SCRATCH137_0, 0x744 */
uint32_t scratch138; /* _SCRATCH138_0, 0x748 */
uint32_t scratch139; /* _SCRATCH139_0, 0x74c */
uint32_t scratch140; /* _SCRATCH140_0, 0x750 */
uint32_t scratch141; /* _SCRATCH141_0, 0x754 */
uint32_t scratch142; /* _SCRATCH142_0, 0x758 */
uint32_t scratch143; /* _SCRATCH143_0, 0x75c */
uint32_t scratch144; /* _SCRATCH144_0, 0x760 */
uint32_t scratch145; /* _SCRATCH145_0, 0x764 */
uint32_t scratch146; /* _SCRATCH146_0, 0x768 */
uint32_t scratch147; /* _SCRATCH147_0, 0x76c */
uint32_t scratch148; /* _SCRATCH148_0, 0x770 */
uint32_t scratch149; /* _SCRATCH149_0, 0x774 */
uint32_t scratch150; /* _SCRATCH150_0, 0x778 */
uint32_t scratch151; /* _SCRATCH151_0, 0x77c */
uint32_t scratch152; /* _SCRATCH152_0, 0x780 */
uint32_t scratch153; /* _SCRATCH153_0, 0x784 */
uint32_t scratch154; /* _SCRATCH154_0, 0x788 */
uint32_t scratch155; /* _SCRATCH155_0, 0x78c */
uint32_t scratch156; /* _SCRATCH156_0, 0x790 */
uint32_t scratch157; /* _SCRATCH157_0, 0x794 */
uint32_t scratch158; /* _SCRATCH158_0, 0x798 */
uint32_t scratch159; /* _SCRATCH159_0, 0x79c */
uint32_t scratch160; /* _SCRATCH160_0, 0x7a0 */
uint32_t scratch161; /* _SCRATCH161_0, 0x7a4 */
uint32_t scratch162; /* _SCRATCH162_0, 0x7a8 */
uint32_t scratch163; /* _SCRATCH163_0, 0x7ac */
uint32_t scratch164; /* _SCRATCH164_0, 0x7b0 */
uint32_t scratch165; /* _SCRATCH165_0, 0x7b4 */
uint32_t scratch166; /* _SCRATCH166_0, 0x7b8 */
uint32_t scratch167; /* _SCRATCH167_0, 0x7bc */
uint32_t scratch168; /* _SCRATCH168_0, 0x7c0 */
uint32_t scratch169; /* _SCRATCH169_0, 0x7c4 */
uint32_t scratch170; /* _SCRATCH170_0, 0x7c8 */
uint32_t scratch171; /* _SCRATCH171_0, 0x7cc */
uint32_t scratch172; /* _SCRATCH172_0, 0x7d0 */
uint32_t scratch173; /* _SCRATCH173_0, 0x7d4 */
uint32_t scratch174; /* _SCRATCH174_0, 0x7d8 */
uint32_t scratch175; /* _SCRATCH175_0, 0x7dc */
uint32_t scratch176; /* _SCRATCH176_0, 0x7e0 */
uint32_t scratch177; /* _SCRATCH177_0, 0x7e4 */
uint32_t scratch178; /* _SCRATCH178_0, 0x7e8 */
uint32_t scratch179; /* _SCRATCH179_0, 0x7ec */
uint32_t scratch180; /* _SCRATCH180_0, 0x7f0 */
uint32_t scratch181; /* _SCRATCH181_0, 0x7f4 */
uint32_t scratch182; /* _SCRATCH182_0, 0x7f8 */
uint32_t scratch183; /* _SCRATCH183_0, 0x7fc */
uint32_t scratch184; /* _SCRATCH184_0, 0x800 */
uint32_t scratch185; /* _SCRATCH185_0, 0x804 */
uint32_t scratch186; /* _SCRATCH186_0, 0x808 */
uint32_t scratch187; /* _SCRATCH187_0, 0x80c */
uint32_t scratch188; /* _SCRATCH188_0, 0x810 */
uint32_t scratch189; /* _SCRATCH189_0, 0x814 */
uint32_t scratch190; /* _SCRATCH190_0, 0x818 */
uint32_t scratch191; /* _SCRATCH191_0, 0x81c */
uint32_t scratch192; /* _SCRATCH192_0, 0x820 */
uint32_t scratch193; /* _SCRATCH193_0, 0x824 */
uint32_t scratch194; /* _SCRATCH194_0, 0x828 */
uint32_t scratch195; /* _SCRATCH195_0, 0x82c */
uint32_t scratch196; /* _SCRATCH196_0, 0x830 */
uint32_t scratch197; /* _SCRATCH197_0, 0x834 */
uint32_t scratch198; /* _SCRATCH198_0, 0x838 */
uint32_t scratch199; /* _SCRATCH199_0, 0x83c */
uint32_t scratch200; /* _SCRATCH200_0, 0x840 */
uint32_t scratch201; /* _SCRATCH201_0, 0x844 */
uint32_t scratch202; /* _SCRATCH202_0, 0x848 */
uint32_t scratch203; /* _SCRATCH203_0, 0x84c */
uint32_t scratch204; /* _SCRATCH204_0, 0x850 */
uint32_t scratch205; /* _SCRATCH205_0, 0x854 */
uint32_t scratch206; /* _SCRATCH206_0, 0x858 */
uint32_t scratch207; /* _SCRATCH207_0, 0x85c */
uint32_t scratch208; /* _SCRATCH208_0, 0x860 */
uint32_t scratch209; /* _SCRATCH209_0, 0x864 */
uint32_t scratch210; /* _SCRATCH210_0, 0x868 */
uint32_t scratch211; /* _SCRATCH211_0, 0x86c */
uint32_t scratch212; /* _SCRATCH212_0, 0x870 */
uint32_t scratch213; /* _SCRATCH213_0, 0x874 */
uint32_t scratch214; /* _SCRATCH214_0, 0x878 */
uint32_t scratch215; /* _SCRATCH215_0, 0x87c */
uint32_t scratch216; /* _SCRATCH216_0, 0x880 */
uint32_t scratch217; /* _SCRATCH217_0, 0x884 */
uint32_t scratch218; /* _SCRATCH218_0, 0x888 */
uint32_t scratch219; /* _SCRATCH219_0, 0x88c */
uint32_t scratch220; /* _SCRATCH220_0, 0x890 */
uint32_t scratch221; /* _SCRATCH221_0, 0x894 */
uint32_t scratch222; /* _SCRATCH222_0, 0x898 */
uint32_t scratch223; /* _SCRATCH223_0, 0x89c */
uint32_t scratch224; /* _SCRATCH224_0, 0x8a0 */
uint32_t scratch225; /* _SCRATCH225_0, 0x8a4 */
uint32_t scratch226; /* _SCRATCH226_0, 0x8a8 */
uint32_t scratch227; /* _SCRATCH227_0, 0x8ac */
uint32_t scratch228; /* _SCRATCH228_0, 0x8b0 */
uint32_t scratch229; /* _SCRATCH229_0, 0x8b4 */
uint32_t scratch230; /* _SCRATCH230_0, 0x8b8 */
uint32_t scratch231; /* _SCRATCH231_0, 0x8bc */
uint32_t scratch232; /* _SCRATCH232_0, 0x8c0 */
uint32_t scratch233; /* _SCRATCH233_0, 0x8c4 */
uint32_t scratch234; /* _SCRATCH234_0, 0x8c8 */
uint32_t scratch235; /* _SCRATCH235_0, 0x8cc */
uint32_t scratch236; /* _SCRATCH236_0, 0x8d0 */
uint32_t scratch237; /* _SCRATCH237_0, 0x8d4 */
uint32_t scratch238; /* _SCRATCH238_0, 0x8d8 */
uint32_t scratch239; /* _SCRATCH239_0, 0x8dc */
uint32_t scratch240; /* _SCRATCH240_0, 0x8e0 */
uint32_t scratch241; /* _SCRATCH241_0, 0x8e4 */
uint32_t scratch242; /* _SCRATCH242_0, 0x8e8 */
uint32_t scratch243; /* _SCRATCH243_0, 0x8ec */
uint32_t scratch244; /* _SCRATCH244_0, 0x8f0 */
uint32_t scratch245; /* _SCRATCH245_0, 0x8f4 */
uint32_t scratch246; /* _SCRATCH246_0, 0x8f8 */
uint32_t scratch247; /* _SCRATCH247_0, 0x8fc */
uint32_t scratch248; /* _SCRATCH248_0, 0x900 */
uint32_t scratch249; /* _SCRATCH249_0, 0x904 */
uint32_t scratch250; /* _SCRATCH250_0, 0x908 */
uint32_t scratch251; /* _SCRATCH251_0, 0x90c */
uint32_t scratch252; /* _SCRATCH252_0, 0x910 */
uint32_t scratch253; /* _SCRATCH253_0, 0x914 */
uint32_t scratch254; /* _SCRATCH254_0, 0x918 */
uint32_t scratch255; /* _SCRATCH255_0, 0x91c */
uint32_t scratch256; /* _SCRATCH256_0, 0x920 */
uint32_t scratch257; /* _SCRATCH257_0, 0x924 */
uint32_t scratch258; /* _SCRATCH258_0, 0x928 */
uint32_t scratch259; /* _SCRATCH259_0, 0x92c */
uint32_t scratch260; /* _SCRATCH260_0, 0x930 */
uint32_t scratch261; /* _SCRATCH261_0, 0x934 */
uint32_t scratch262; /* _SCRATCH262_0, 0x938 */
uint32_t scratch263; /* _SCRATCH263_0, 0x93c */
uint32_t scratch264; /* _SCRATCH264_0, 0x940 */
uint32_t scratch265; /* _SCRATCH265_0, 0x944 */
uint32_t scratch266; /* _SCRATCH266_0, 0x948 */
uint32_t scratch267; /* _SCRATCH267_0, 0x94c */
uint32_t scratch268; /* _SCRATCH268_0, 0x950 */
uint32_t scratch269; /* _SCRATCH269_0, 0x954 */
uint32_t scratch270; /* _SCRATCH270_0, 0x958 */
uint32_t scratch271; /* _SCRATCH271_0, 0x95c */
uint32_t scratch272; /* _SCRATCH272_0, 0x960 */
uint32_t scratch273; /* _SCRATCH273_0, 0x964 */
uint32_t scratch274; /* _SCRATCH274_0, 0x968 */
uint32_t scratch275; /* _SCRATCH275_0, 0x96c */
uint32_t scratch276; /* _SCRATCH276_0, 0x970 */
uint32_t scratch277; /* _SCRATCH277_0, 0x974 */
uint32_t scratch278; /* _SCRATCH278_0, 0x978 */
uint32_t scratch279; /* _SCRATCH279_0, 0x97c */
uint32_t scratch280; /* _SCRATCH280_0, 0x980 */
uint32_t scratch281; /* _SCRATCH281_0, 0x984 */
uint32_t scratch282; /* _SCRATCH282_0, 0x988 */
uint32_t scratch283; /* _SCRATCH283_0, 0x98c */
uint32_t scratch284; /* _SCRATCH284_0, 0x990 */
uint32_t scratch285; /* _SCRATCH285_0, 0x994 */
uint32_t scratch286; /* _SCRATCH286_0, 0x998 */
uint32_t scratch287; /* _SCRATCH287_0, 0x99c */
uint32_t scratch288; /* _SCRATCH288_0, 0x9a0 */
uint32_t scratch289; /* _SCRATCH289_0, 0x9a4 */
uint32_t scratch290; /* _SCRATCH290_0, 0x9a8 */
uint32_t scratch291; /* _SCRATCH291_0, 0x9ac */
uint32_t scratch292; /* _SCRATCH292_0, 0x9b0 */
uint32_t scratch293; /* _SCRATCH293_0, 0x9b4 */
uint32_t scratch294; /* _SCRATCH294_0, 0x9b8 */
uint32_t scratch295; /* _SCRATCH295_0, 0x9bc */
uint32_t scratch296; /* _SCRATCH296_0, 0x9c0 */
uint32_t scratch297; /* _SCRATCH297_0, 0x9c4 */
uint32_t scratch298; /* _SCRATCH298_0, 0x9c8 */
uint32_t scratch299; /* _SCRATCH299_0, 0x9cc */
uint32_t _0x9d0[50];
uint32_t secure_scratch80; /* _SECURE_SCRATCH80_0, 0xa98 */
uint32_t secure_scratch81; /* _SECURE_SCRATCH81_0, 0xa9c */
uint32_t secure_scratch82; /* _SECURE_SCRATCH82_0, 0xaa0 */
uint32_t secure_scratch83; /* _SECURE_SCRATCH83_0, 0xaa4 */
uint32_t secure_scratch84; /* _SECURE_SCRATCH84_0, 0xaa8 */
uint32_t secure_scratch85; /* _SECURE_SCRATCH85_0, 0xaac */
uint32_t secure_scratch86; /* _SECURE_SCRATCH86_0, 0xab0 */
uint32_t secure_scratch87; /* _SECURE_SCRATCH87_0, 0xab4 */
uint32_t secure_scratch88; /* _SECURE_SCRATCH88_0, 0xab8 */
uint32_t secure_scratch89; /* _SECURE_SCRATCH89_0, 0xabc */
uint32_t secure_scratch90; /* _SECURE_SCRATCH90_0, 0xac0 */
uint32_t secure_scratch91; /* _SECURE_SCRATCH91_0, 0xac4 */
uint32_t secure_scratch92; /* _SECURE_SCRATCH92_0, 0xac8 */
uint32_t secure_scratch93; /* _SECURE_SCRATCH93_0, 0xacc */
uint32_t secure_scratch94; /* _SECURE_SCRATCH94_0, 0xad0 */
uint32_t secure_scratch95; /* _SECURE_SCRATCH95_0, 0xad4 */
uint32_t secure_scratch96; /* _SECURE_SCRATCH96_0, 0xad8 */
uint32_t secure_scratch97; /* _SECURE_SCRATCH97_0, 0xadc */
uint32_t secure_scratch98; /* _SECURE_SCRATCH98_0, 0xae0 */
uint32_t secure_scratch99; /* _SECURE_SCRATCH99_0, 0xae4 */
uint32_t secure_scratch100; /* _SECURE_SCRATCH100_0, 0xae8 */
uint32_t secure_scratch101; /* _SECURE_SCRATCH101_0, 0xaec */
uint32_t secure_scratch102; /* _SECURE_SCRATCH102_0, 0xaf0 */
uint32_t secure_scratch103; /* _SECURE_SCRATCH103_0, 0xaf4 */
uint32_t secure_scratch104; /* _SECURE_SCRATCH104_0, 0xaf8 */
uint32_t secure_scratch105; /* _SECURE_SCRATCH105_0, 0xafc */
uint32_t secure_scratch106; /* _SECURE_SCRATCH106_0, 0xb00 */
uint32_t secure_scratch107; /* _SECURE_SCRATCH107_0, 0xb04 */
uint32_t secure_scratch108; /* _SECURE_SCRATCH108_0, 0xb08 */
uint32_t secure_scratch109; /* _SECURE_SCRATCH109_0, 0xb0c */
uint32_t secure_scratch110; /* _SECURE_SCRATCH110_0, 0xb10 */
uint32_t secure_scratch111; /* _SECURE_SCRATCH111_0, 0xb14 */
uint32_t secure_scratch112; /* _SECURE_SCRATCH112_0, 0xb18 */
uint32_t secure_scratch113; /* _SECURE_SCRATCH113_0, 0xb1c */
uint32_t secure_scratch114; /* _SECURE_SCRATCH114_0, 0xb20 */
uint32_t secure_scratch115; /* _SECURE_SCRATCH115_0, 0xb24 */
uint32_t secure_scratch116; /* _SECURE_SCRATCH116_0, 0xb28 */
uint32_t secure_scratch117; /* _SECURE_SCRATCH117_0, 0xb2c */
uint32_t secure_scratch118; /* _SECURE_SCRATCH118_0, 0xb30 */
uint32_t secure_scratch119; /* _SECURE_SCRATCH119_0, 0xb34 */
uint32_t secure_scratch120; /* _SECURE_SCRATCH120_0, 0xb38 */
uint32_t secure_scratch121; /* _SECURE_SCRATCH121_0, 0xb3c */
uint32_t secure_scratch122; /* _SECURE_SCRATCH122_0, 0xb40 */
uint32_t secure_scratch123; /* _SECURE_SCRATCH123_0, 0xb44 */
uint32_t led_breathing_ctrl; /* _LED_BREATHING_CTRL_0, 0xb48 */
uint32_t led_breathing_counter0; /* _LED_BREATHING_COUNTER0_0, 0xb4c */
uint32_t led_breathing_counter1; /* _LED_BREATHING_COUNTER1_0, 0xb50 */
uint32_t led_breathing_counter2; /* _LED_BREATHING_COUNTER2_0, 0xb54 */
uint32_t led_breathing_counter3; /* _LED_BREATHING_COUNTER3_0, 0xb58 */
uint32_t led_breathing_status; /* _LED_BREATHING_STATUS_0, 0xb5c */
uint32_t _0xb60[2];
uint32_t secure_scratch124; /* _SECURE_SCRATCH124_0, 0xb68 */
uint32_t secure_scratch125; /* _SECURE_SCRATCH125_0, 0xb6c */
uint32_t secure_scratch126; /* _SECURE_SCRATCH126_0, 0xb70 */
uint32_t secure_scratch127; /* _SECURE_SCRATCH127_0, 0xb74 */
uint32_t secure_scratch128; /* _SECURE_SCRATCH128_0, 0xb78 */
uint32_t secure_scratch129; /* _SECURE_SCRATCH129_0, 0xb7c */
uint32_t secure_scratch130; /* _SECURE_SCRATCH130_0, 0xb80 */
uint32_t secure_scratch131; /* _SECURE_SCRATCH131_0, 0xb84 */
uint32_t secure_scratch132; /* _SECURE_SCRATCH132_0, 0xb88 */
uint32_t secure_scratch133; /* _SECURE_SCRATCH133_0, 0xb8c */
uint32_t secure_scratch134; /* _SECURE_SCRATCH134_0, 0xb90 */
uint32_t secure_scratch135; /* _SECURE_SCRATCH135_0, 0xb94 */
uint32_t secure_scratch136; /* _SECURE_SCRATCH136_0, 0xb98 */
uint32_t secure_scratch137; /* _SECURE_SCRATCH137_0, 0xb9c */
uint32_t secure_scratch138; /* _SECURE_SCRATCH138_0, 0xba0 */
uint32_t secure_scratch139; /* _SECURE_SCRATCH139_0, 0xba4 */
uint32_t _0xba8[2];
uint32_t sec_disable_ns; /* _SEC_DISABLE_NS_0, 0xbb0 */
uint32_t sec_disable2_ns; /* _SEC_DISABLE2_NS_0, 0xbb4 */
uint32_t sec_disable3_ns; /* _SEC_DISABLE3_NS_0, 0xbb8 */
uint32_t sec_disable4_ns; /* _SEC_DISABLE4_NS_0, 0xbbc */
uint32_t sec_disable5_ns; /* _SEC_DISABLE5_NS_0, 0xbc0 */
uint32_t sec_disable6_ns; /* _SEC_DISABLE6_NS_0, 0xbc4 */
uint32_t sec_disable7_ns; /* _SEC_DISABLE7_NS_0, 0xbc8 */
uint32_t sec_disable8_ns; /* _SEC_DISABLE8_NS_0, 0xbcc */
uint32_t sec_disable9_ns; /* _SEC_DISABLE9_NS_0, 0xbd0 */
uint32_t sec_disable10_ns; /* _SEC_DISABLE10_NS_0, 0xbd4 */
uint32_t _0xbd8[4];
uint32_t tzram_pwr_cntrl; /* _TZRAM_PWR_CNTRL_0, 0xbe8 */
uint32_t tzram_sec_disable; /* _TZRAM_SEC_DISABLE_0, 0xbec */
uint32_t tzram_non_sec_disable; /* _TZRAM_NON_SEC_DISABLE_0, 0xbf0 */
} tegra_pmc_t;
static inline volatile tegra_pmc_t *pmc_get_regs(void)
{
return (volatile tegra_pmc_t *)PMC_BASE;
}
#endif

View File

@ -1,649 +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 <string.h>
#include "utils.h"
#include "se.h"
void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size);
/* Globals for driver. */
static unsigned int g_se_modulus_sizes[KEYSLOT_RSA_MAX];
static unsigned int g_se_exp_sizes[KEYSLOT_RSA_MAX];
/* Initialize a SE linked list. */
void NOINLINE ll_init(volatile se_ll_t *ll, void *buffer, size_t size) {
ll->num_entries = 0; /* 1 Entry. */
if (buffer != NULL) {
ll->addr_info.address = (uint32_t) get_physical_address(buffer);
ll->addr_info.size = (uint32_t) size;
} else {
ll->addr_info.address = 0;
ll->addr_info.size = 0;
}
}
void se_check_error_status_reg(void) {
if (se_get_regs()->SE_ERR_STATUS) {
generic_panic();
}
}
void se_check_for_error(void) {
volatile tegra_se_t *se = se_get_regs();
if (se->SE_INT_STATUS & 0x10000 || se->SE_STATUS & 3 || se->SE_ERR_STATUS) {
generic_panic();
}
}
void se_verify_flags_cleared(void) {
if (se_get_regs()->SE_STATUS & 3) {
generic_panic();
}
}
/* Set the flags for an AES keyslot. */
void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX) {
generic_panic();
}
/* Misc flags. */
if (flags & ~0x80) {
se->SE_CRYPTO_KEYTABLE_ACCESS[keyslot] = ~flags;
}
/* Disable keyslot reads. */
if (flags & 0x80) {
se->SE_CRYPTO_SECURITY_PERKEY &= ~(1 << keyslot);
}
}
/* Set the flags for an RSA keyslot. */
void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_RSA_MAX) {
generic_panic();
}
/* Misc flags. */
if (flags & ~0x80) {
/* TODO: Why are flags assigned this way? */
se->SE_RSA_KEYTABLE_ACCESS[keyslot] = (((flags >> 4) & 4) | (flags & 3)) ^ 7;
}
/* Disable keyslot reads. */
if (flags & 0x80) {
se->SE_RSA_SECURITY_PERKEY &= ~(1 << keyslot);
}
}
void clear_aes_keyslot(unsigned int keyslot) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX) {
generic_panic();
}
/* Zero out the whole keyslot and IV. */
for (unsigned int i = 0; i < 0x10; i++) {
se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | i;
se->SE_CRYPTO_KEYTABLE_DATA = 0;
}
}
void clear_rsa_keyslot(unsigned int keyslot) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_RSA_MAX) {
generic_panic();
}
/* Zero out the whole keyslot. */
for (unsigned int i = 0; i < 0x40; i++) {
/* Select Keyslot Modulus[i] */
se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | i | 0x40;
se->SE_RSA_KEYTABLE_DATA = 0;
}
for (unsigned int i = 0; i < 0x40; i++) {
/* Select Keyslot Expontent[i] */
se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | i;
se->SE_RSA_KEYTABLE_DATA = 0;
}
}
void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX || key_size > KEYSIZE_AES_MAX) {
generic_panic();
}
for (size_t i = 0; i < (key_size >> 2); i++) {
se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | i;
se->SE_CRYPTO_KEYTABLE_DATA = read32le(key, 4 * i);
}
}
void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_size, const void *exponent, size_t exp_size) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_RSA_MAX || modulus_size > KEYSIZE_RSA_MAX || exp_size > KEYSIZE_RSA_MAX) {
generic_panic();
}
for (size_t i = 0; i < (modulus_size >> 2); i++) {
se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | 0x40 | i;
se->SE_RSA_KEYTABLE_DATA = read32be(modulus, (4 * (modulus_size >> 2)) - (4 * i) - 4);
}
for (size_t i = 0; i < (exp_size >> 2); i++) {
se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | i;
se->SE_RSA_KEYTABLE_DATA = read32be(exponent, (4 * (exp_size >> 2)) - (4 * i) - 4);
}
g_se_modulus_sizes[keyslot] = modulus_size;
g_se_exp_sizes[keyslot] = exp_size;
}
void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX || iv_size > 0x10) {
generic_panic();
}
for (size_t i = 0; i < (iv_size >> 2); i++) {
se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | 8 | i;
se->SE_CRYPTO_KEYTABLE_DATA = read32le(iv, 4 * i);
}
}
void clear_aes_keyslot_iv(unsigned int keyslot) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX) {
generic_panic();
}
for (size_t i = 0; i < (0x10 >> 2); i++) {
se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | 8 | i;
se->SE_CRYPTO_KEYTABLE_DATA = 0;
}
}
void set_se_ctr(const void *ctr) {
for (unsigned int i = 0; i < 4; i++) {
se_get_regs()->SE_CRYPTO_LINEAR_CTR[i] = read32le(ctr, i * 4);
}
}
void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_src, const void *wrapped_key, size_t wrapped_key_size) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot_dst >= KEYSLOT_AES_MAX || keyslot_src >= KEYSLOT_AES_MAX || wrapped_key_size > KEYSIZE_AES_MAX) {
generic_panic();
}
se->SE_CONFIG = (ALG_AES_DEC | DST_KEYTAB);
se->SE_CRYPTO_CONFIG = keyslot_src << 24;
se->SE_CRYPTO_LAST_BLOCK = 0;
se->SE_CRYPTO_KEYTABLE_DST = keyslot_dst << 8;
trigger_se_blocking_op(OP_START, NULL, 0, wrapped_key, wrapped_key_size);
}
void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) {
volatile tegra_se_t *se = se_get_regs();
uint8_t ALIGN(16) stack_buf[KEYSIZE_RSA_MAX];
if (keyslot >= KEYSLOT_RSA_MAX || src_size > KEYSIZE_RSA_MAX || dst_size > KEYSIZE_RSA_MAX) {
generic_panic();
}
/* Endian swap the input. */
for (size_t i = 0; i < src_size; i++) {
stack_buf[i] = *((uint8_t *)src + src_size - i - 1);
}
se->SE_CONFIG = (ALG_RSA | DST_RSAREG);
se->SE_RSA_CONFIG = keyslot << 24;
se->SE_RSA_KEY_SIZE = (g_se_modulus_sizes[keyslot] >> 6) - 1;
se->SE_RSA_EXP_SIZE = g_se_exp_sizes[keyslot] >> 2;
trigger_se_blocking_op(OP_START, NULL, 0, stack_buf, src_size);
se_get_exp_mod_output(dst, dst_size);
}
void se_get_exp_mod_output(void *buf, size_t size) {
size_t num_dwords = (size >> 2);
if (num_dwords < 1) {
return;
}
uint32_t *p_out = ((uint32_t *)buf) + num_dwords - 1;
uint32_t offset = 0;
/* Copy endian swapped output. */
while (num_dwords) {
*p_out = read32be(se_get_regs()->SE_RSA_OUTPUT, offset);
offset += 4;
p_out--;
num_dwords--;
}
}
bool se_rsa2048_pss_verify(const void *signature, size_t signature_size, const void *modulus, size_t modulus_size, const void *data, size_t data_size) {
uint8_t message[RSA_2048_BYTES];
uint8_t h_buf[0x24];
/* Hardcode RSA with keyslot 0. */
const uint8_t public_exponent[4] = {0x00, 0x01, 0x00, 0x01};
set_rsa_keyslot(0, modulus, modulus_size, public_exponent, sizeof(public_exponent));
se_synchronous_exp_mod(0, message, sizeof(message), signature, signature_size);
/* Validate sanity byte. */
if (message[RSA_2048_BYTES - 1] != 0xBC) {
return false;
}
/* Copy Salt into MGF1 Hash Buffer. */
memset(h_buf, 0, sizeof(h_buf));
memcpy(h_buf, message + RSA_2048_BYTES - 0x20 - 0x1, 0x20);
/* Decrypt maskedDB (via inline MGF1). */
uint8_t seed = 0;
uint8_t mgf1_buf[0x20];
for (unsigned int ofs = 0; ofs < RSA_2048_BYTES - 0x20 - 1; ofs += 0x20) {
h_buf[sizeof(h_buf) - 1] = seed++;
se_calculate_sha256(mgf1_buf, h_buf, sizeof(h_buf));
for (unsigned int i = ofs; i < ofs + 0x20 && i < RSA_2048_BYTES - 0x20 - 1; i++) {
message[i] ^= mgf1_buf[i - ofs];
}
}
/* Constant lmask for rsa-2048-pss. */
message[0] &= 0x7F;
/* Validate DB is of the form 0000...0001. */
for (unsigned int i = 0; i < RSA_2048_BYTES - 0x20 - 0x20 - 1 - 1; i++) {
if (message[i] != 0) {
return false;
}
}
if (message[RSA_2048_BYTES - 0x20 - 0x20 - 1 - 1] != 1) {
return false;
}
/* Check hash correctness. */
uint8_t validate_buf[8 + 0x20 + 0x20];
uint8_t validate_hash[0x20];
memset(validate_buf, 0, sizeof(validate_buf));
se_calculate_sha256(&validate_buf[8], data, data_size);
memcpy(&validate_buf[0x28], &message[RSA_2048_BYTES - 0x20 - 0x20 - 1], 0x20);
se_calculate_sha256(validate_hash, validate_buf, sizeof(validate_buf));
return memcmp(h_buf, validate_hash, 0x20) == 0;
}
void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size) {
volatile tegra_se_t *se = se_get_regs();
se_ll_t in_ll;
se_ll_t out_ll;
ll_init(&in_ll, (void *)src, src_size);
ll_init(&out_ll, dst, dst_size);
/* Set the LLs. */
se->SE_IN_LL_ADDR = (uint32_t) get_physical_address(&in_ll);
se->SE_OUT_LL_ADDR = (uint32_t) get_physical_address(&out_ll);
/* Set registers for operation. */
se->SE_ERR_STATUS = se->SE_ERR_STATUS;
se->SE_INT_STATUS = se->SE_INT_STATUS;
se->SE_OPERATION = op;
while (!(se->SE_INT_STATUS & 0x10)) { /* Wait a while */ }
se_check_for_error();
}
/* Secure AES Functionality. */
void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, size_t src_size) {
uint8_t block[0x10] = {0};
if (src_size > sizeof(block) || dst_size > sizeof(block)) {
generic_panic();
}
/* Load src data into block. */
if (src_size != 0) {
memcpy(block, src, src_size);
}
/* Trigger AES operation. */
se_get_regs()->SE_CRYPTO_LAST_BLOCK = 0;
trigger_se_blocking_op(OP_START, block, sizeof(block), block, sizeof(block));
/* Copy output data into dst. */
if (dst_size != 0) {
memcpy(dst, block, dst_size);
}
}
void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX || ctr_size != 0x10) {
generic_panic();
}
unsigned int num_blocks = src_size >> 4;
/* Unknown what this write does, but official code writes it for CTR mode. */
se->SE_SPARE = 1;
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY);
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x91E;
set_se_ctr(ctr);
/* Handle any aligned blocks. */
size_t aligned_size = (size_t)num_blocks << 4;
if (aligned_size) {
se->SE_CRYPTO_LAST_BLOCK = num_blocks - 1;
trigger_se_blocking_op(OP_START, dst, dst_size, src, aligned_size);
}
/* Handle final, unaligned block. */
if (aligned_size < dst_size && aligned_size < src_size) {
size_t last_block_size = dst_size - aligned_size;
if (src_size < dst_size) {
last_block_size = src_size - aligned_size;
}
se_perform_aes_block_operation(dst + aligned_size, last_block_size, (uint8_t *)src + aligned_size, src_size - aligned_size);
}
}
void se_aes_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, unsigned int config_high) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) {
generic_panic();
}
/* Set configuration high (256-bit vs 128-bit) based on parameter. */
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16);
se->SE_CRYPTO_CONFIG = keyslot << 24 | 0x100;
se_perform_aes_block_operation(dst, 0x10, src, 0x10);
}
void se_aes_128_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) {
se_aes_ecb_encrypt_block(keyslot, dst, dst_size, src, src_size, 0);
}
void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) {
se_aes_ecb_encrypt_block(keyslot, dst, dst_size, src, src_size, 0x202);
}
void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) {
generic_panic();
}
se->SE_CONFIG = (ALG_AES_DEC | DST_MEMORY);
se->SE_CRYPTO_CONFIG = keyslot << 24;
se_perform_aes_block_operation(dst, 0x10, src, 0x10);
}
void shift_left_xor_rb(uint8_t *key) {
uint8_t prev_high_bit = 0;
for (unsigned int i = 0; i < 0x10; i++) {
uint8_t cur_byte = key[0xF - i];
key[0xF - i] = (cur_byte << 1) | (prev_high_bit);
prev_high_bit = cur_byte >> 7;
}
if (prev_high_bit) {
key[0xF] ^= 0x87;
}
}
void shift_left_xor_rb_le(uint8_t *key) {
uint8_t prev_high_bit = 0;
for (unsigned int i = 0; i < 0x10; i++) {
uint8_t cur_byte = key[i];
key[i] = (cur_byte << 1) | (prev_high_bit);
prev_high_bit = cur_byte >> 7;
}
if (prev_high_bit) {
key[0x0] ^= 0x87;
}
}
void aes_128_xts_nintendo_get_tweak(uint8_t *tweak, size_t sector) {
for (int i = 0xF; i >= 0; i--) { /* Nintendo LE custom tweak... */
tweak[i] = (unsigned char)(sector & 0xFF);
sector >>= 8;
}
}
void aes_128_xts_nintendo_xor_with_tweak(unsigned int keyslot, size_t sector, uint8_t *dst, const uint8_t *src, size_t size) {
if ((size & 0xF) || size == 0) {
generic_panic();
}
uint8_t tweak[0x10];
aes_128_xts_nintendo_get_tweak(tweak, sector);
se_aes_128_ecb_encrypt_block(keyslot, tweak, sizeof(tweak), tweak, sizeof(tweak));
for (unsigned int block = 0; block < (size >> 4); block++) {
for (unsigned int i = 0; i < 0x10; i++) {
dst[(block << 4) | i] = src[(block << 4) | i] ^ tweak[i];
}
shift_left_xor_rb_le(tweak);
}
}
void aes_128_xts_nintendo_crypt_sector(unsigned int keyslot_1, unsigned int keyslot_2, size_t sector, bool encrypt, void *dst, const void *src, size_t size) {
volatile tegra_se_t *se = se_get_regs();
if ((size & 0xF) || size == 0) {
generic_panic();
}
/* XOR. */
aes_128_xts_nintendo_xor_with_tweak(keyslot_2, sector, dst, src, size);
/* Encrypt/Decrypt. */
if (encrypt) {
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY);
se->SE_CRYPTO_CONFIG = keyslot_1 << 24 | 0x100;
} else {
se->SE_CONFIG = (ALG_AES_DEC | DST_MEMORY);
se->SE_CRYPTO_CONFIG = keyslot_1 << 24;
}
se->SE_CRYPTO_LAST_BLOCK = (size >> 4) - 1;
trigger_se_blocking_op(OP_START, dst, size, src, size);
/* XOR. */
aes_128_xts_nintendo_xor_with_tweak(keyslot_2, sector, dst, dst, size);
}
/* Encrypt with AES-XTS (Nintendo's custom tweak). */
void se_aes_128_xts_nintendo_encrypt(unsigned int keyslot_1, unsigned int keyslot_2, size_t base_sector, void *dst, const void *src, size_t size, unsigned int sector_size) {
if ((size & 0xF) || size == 0) {
generic_panic();
}
size_t sector = base_sector;
for (size_t ofs = 0; ofs < size; ofs += sector_size) {
aes_128_xts_nintendo_crypt_sector(keyslot_1, keyslot_2, sector, true, dst + ofs, src + ofs, sector_size);
sector++;
}
}
/* Decrypt with AES-XTS (Nintendo's custom tweak). */
void se_aes_128_xts_nintendo_decrypt(unsigned int keyslot_1, unsigned int keyslot_2, size_t base_sector, void *dst, const void *src, size_t size, unsigned int sector_size) {
if ((size & 0xF) || size == 0) {
generic_panic();
}
size_t sector = base_sector;
for (size_t ofs = 0; ofs < size; ofs += sector_size) {
aes_128_xts_nintendo_crypt_sector(keyslot_1, keyslot_2, sector, false, dst + ofs, src + ofs, sector_size);
sector++;
}
}
void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size, unsigned int config_high) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX) {
generic_panic();
}
/* Generate the derived key, to be XOR'd with final output block. */
uint8_t ALIGN(16) derived_key[0x10] = {0};
se_aes_ecb_encrypt_block(keyslot, derived_key, sizeof(derived_key), derived_key, sizeof(derived_key), config_high);
shift_left_xor_rb(derived_key);
if (data_size & 0xF) {
shift_left_xor_rb(derived_key);
}
se->SE_CONFIG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16);
se->SE_CRYPTO_CONFIG = (keyslot << 24) | (0x145);
clear_aes_keyslot_iv(keyslot);
unsigned int num_blocks = (data_size + 0xF) >> 4;
/* Handle aligned blocks. */
if (num_blocks > 1) {
se->SE_CRYPTO_LAST_BLOCK = num_blocks - 2;
trigger_se_blocking_op(OP_START, NULL, 0, data, data_size);
se->SE_CRYPTO_CONFIG |= 0x80;
}
/* Create final block. */
uint8_t ALIGN(16) last_block[0x10] = {0};
if (data_size & 0xF) {
memcpy(last_block, data + (data_size & ~0xF), data_size & 0xF);
last_block[data_size & 0xF] = 0x80; /* Last block = data || 100...0 */
} else if (data_size >= 0x10) {
memcpy(last_block, data + data_size - 0x10, 0x10);
}
for (unsigned int i = 0; i < 0x10; i++) {
last_block[i] ^= derived_key[i];
}
/* Perform last operation. */
se->SE_CRYPTO_LAST_BLOCK = 0;
trigger_se_blocking_op(OP_START, NULL, 0, last_block, sizeof(last_block));
/* Copy output CMAC. */
for (unsigned int i = 0; i < (cmac_size >> 2); i++) {
((uint32_t *)cmac)[i] = read32le(se->SE_HASH_RESULT, i << 2);
}
}
void se_compute_aes_128_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size) {
se_compute_aes_cmac(keyslot, cmac, cmac_size, data, data_size, 0);
}
void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size) {
se_compute_aes_cmac(keyslot, cmac, cmac_size, data, data_size, 0x202);
}
void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX || src_size < 0x10) {
generic_panic();
}
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY) | (0x202 << 16);
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x144;
set_aes_keyslot_iv(keyslot, iv, 0x10);
se->SE_CRYPTO_LAST_BLOCK = (src_size >> 4) - 1;
trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size);
}
/* SHA256 Implementation. */
void se_calculate_sha256(void *dst, const void *src, size_t src_size) {
volatile tegra_se_t *se = se_get_regs();
/* Setup config for SHA256, size = BITS(src_size) */
se->SE_CONFIG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG);
se->SE_SHA_CONFIG = 1;
se->SE_SHA_MSG_LENGTH[0] = (uint32_t)(src_size << 3);
se->SE_SHA_MSG_LENGTH[1] = 0;
se->SE_SHA_MSG_LENGTH[2] = 0;
se->SE_SHA_MSG_LENGTH[3] = 0;
se->SE_SHA_MSG_LEFT[0] = (uint32_t)(src_size << 3);
se->SE_SHA_MSG_LEFT[1] = 0;
se->SE_SHA_MSG_LEFT[2] = 0;
se->SE_SHA_MSG_LEFT[3] = 0;
/* Trigger the operation. */
trigger_se_blocking_op(OP_START, NULL, 0, src, src_size);
/* Copy output hash. */
for (unsigned int i = 0; i < (0x20 >> 2); i++) {
((uint32_t *)dst)[i] = read32be(se->SE_HASH_RESULT, i << 2);
}
}
/* RNG API */
void se_initialize_rng(unsigned int keyslot) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX) {
generic_panic();
}
/* To initialize the RNG, we'll perform an RNG operation into an output buffer. */
/* This will be discarded, when done. */
uint8_t ALIGN(16) output_buf[0x10];
se->SE_RNG_SRC_CONFIG = 3; /* Entropy enable + Entropy lock enable */
se->SE_RNG_RESEED_INTERVAL = 70001;
se->SE_CONFIG = (ALG_RNG | DST_MEMORY);
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x108;
se->SE_RNG_CONFIG = 5;
se->SE_CRYPTO_LAST_BLOCK = 0;
trigger_se_blocking_op(OP_START, output_buf, 0x10, NULL, 0);
}
void se_generate_random(unsigned int keyslot, void *dst, size_t size) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX) {
generic_panic();
}
uint32_t num_blocks = size >> 4;
size_t aligned_size = num_blocks << 4;
se->SE_CONFIG = (ALG_RNG | DST_MEMORY);
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x108;
se->SE_RNG_CONFIG = 4;
if (num_blocks >= 1) {
se->SE_CRYPTO_LAST_BLOCK = num_blocks - 1;
trigger_se_blocking_op(OP_START, dst, aligned_size, NULL, 0);
}
if (size > aligned_size) {
se_perform_aes_block_operation(dst + aligned_size, size - aligned_size, NULL, 0);
}
}

View File

@ -1,210 +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/>.
*/
#ifndef FUSEE_SE_H
#define FUSEE_SE_H
#define SE_BASE 0x70012000
#define MAKE_SE_REG(n) MAKE_REG32(SE_BASE + n)
#define KEYSLOT_SWITCH_LP0TZRAMKEY 0x2
#define KEYSLOT_SWITCH_SRKGENKEY 0x8
#define KEYSLOT_SWITCH_PACKAGE2KEY 0x8
#define KEYSLOT_SWITCH_TEMPKEY 0x9
#define KEYSLOT_SWITCH_SESSIONKEY 0xA
#define KEYSLOT_SWITCH_RNGKEY 0xB
#define KEYSLOT_SWITCH_MASTERKEY 0xC
#define KEYSLOT_SWITCH_DEVICEKEY 0xD
/* This keyslot was added in 4.0.0. */
#define KEYSLOT_SWITCH_4XNEWDEVICEKEYGENKEY 0xD
#define KEYSLOT_SWITCH_4XNEWCONSOLEKEYGENKEY 0xE
#define KEYSLOT_SWITCH_4XOLDDEVICEKEY 0xF
/* This keyslot was added in 5.0.0. */
#define KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY 0xA
/* Mariko keyslots. */
#define KEYSLOT_SWITCH_MASTERKEY_MARIKO 0x7
#define KEYSLOT_AES_MAX 0x10
#define KEYSLOT_RSA_MAX 0x2
#define KEYSIZE_AES_MAX 0x20
#define KEYSIZE_RSA_MAX 0x100
#define ALG_SHIFT (12)
#define ALG_DEC_SHIFT (8)
#define ALG_NOP (0 << ALG_SHIFT)
#define ALG_AES_ENC (1 << ALG_SHIFT)
#define ALG_AES_DEC ((1 << ALG_DEC_SHIFT) | ALG_NOP)
#define ALG_RNG (2 << ALG_SHIFT)
#define ALG_SHA (3 << ALG_SHIFT)
#define ALG_RSA (4 << ALG_SHIFT)
#define DST_SHIFT (2)
#define DST_MEMORY (0 << DST_SHIFT)
#define DST_HASHREG (1 << DST_SHIFT)
#define DST_KEYTAB (2 << DST_SHIFT)
#define DST_SRK (3 << DST_SHIFT)
#define DST_RSAREG (4 << DST_SHIFT)
#define ENCMODE_SHIFT (24)
#define DECMODE_SHIFT (16)
#define ENCMODE_SHA256 (5 << ENCMODE_SHIFT)
#define HASH_DISABLE (0x0)
#define HASH_ENABLE (0x1)
#define OP_ABORT 0
#define OP_START 1
#define OP_RESTART 2
#define OP_CTX_SAVE 3
#define OP_RESTART_IN 4
#define CTX_SAVE_SRC_SHIFT 29
#define CTX_SAVE_SRC_STICKY_BITS (0 << CTX_SAVE_SRC_SHIFT)
#define CTX_SAVE_SRC_KEYTABLE_AES (2 << CTX_SAVE_SRC_SHIFT)
#define CTX_SAVE_SRC_KEYTABLE_RSA (1 << CTX_SAVE_SRC_SHIFT)
#define CTX_SAVE_SRC_MEM (4 << CTX_SAVE_SRC_SHIFT)
#define CTX_SAVE_SRC_SRK (6 << CTX_SAVE_SRC_SHIFT)
#define CTX_SAVE_KEY_LOW_BITS 0
#define CTX_SAVE_KEY_HIGH_BITS 1
#define CTX_SAVE_KEY_ORIGINAL_IV 2
#define CTX_SAVE_KEY_UPDATED_IV 3
#define CTX_SAVE_STICKY_BIT_INDEX_SHIFT 24
#define CTX_SAVE_KEY_INDEX_SHIFT 8
#define CTX_SAVE_RSA_KEY_INDEX_SHIFT 16
#define CTX_SAVE_RSA_KEY_BLOCK_INDEX_SHIFT 12
#define RSA_2048_BYTES 0x100
typedef struct {
uint32_t SE_SE_SECURITY;
uint32_t SE_TZRAM_SECURITY;
uint32_t SE_OPERATION;
uint32_t SE_INT_ENABLE;
uint32_t SE_INT_STATUS;
uint32_t SE_CONFIG;
uint32_t SE_IN_LL_ADDR;
uint32_t SE_IN_CUR_BYTE_ADDR;
uint32_t SE_IN_CUR_LL_ID;
uint32_t SE_OUT_LL_ADDR;
uint32_t SE_OUT_CUR_BYTE_ADDR;
uint32_t SE_OUT_CUR_LL_ID;
uint32_t SE_HASH_RESULT[0x10];
uint32_t SE_CTX_SAVE_CONFIG;
uint32_t _0x74[0x63];
uint32_t SE_SHA_CONFIG;
uint32_t SE_SHA_MSG_LENGTH[0x4];
uint32_t SE_SHA_MSG_LEFT[0x4];
uint32_t _0x224[0x17];
uint32_t SE_CRYPTO_SECURITY_PERKEY;
uint32_t SE_CRYPTO_KEYTABLE_ACCESS[0x10];
uint32_t _0x2C4[0x10];
uint32_t SE_CRYPTO_CONFIG;
uint32_t SE_CRYPTO_LINEAR_CTR[0x4];
uint32_t SE_CRYPTO_LAST_BLOCK;
uint32_t SE_CRYPTO_KEYTABLE_ADDR;
uint32_t SE_CRYPTO_KEYTABLE_DATA;
uint32_t _0x324[0x3];
uint32_t SE_CRYPTO_KEYTABLE_DST;
uint32_t _0x334[0x3];
uint32_t SE_RNG_CONFIG;
uint32_t SE_RNG_SRC_CONFIG;
uint32_t SE_RNG_RESEED_INTERVAL;
uint32_t _0x34C[0x2D];
uint32_t SE_RSA_CONFIG;
uint32_t SE_RSA_KEY_SIZE;
uint32_t SE_RSA_EXP_SIZE;
uint32_t SE_RSA_SECURITY_PERKEY;
uint32_t SE_RSA_KEYTABLE_ACCESS[0x2];
uint32_t _0x418[0x2];
uint32_t SE_RSA_KEYTABLE_ADDR;
uint32_t SE_RSA_KEYTABLE_DATA;
uint32_t SE_RSA_OUTPUT[0x40];
uint32_t _0x528[0xB6];
uint32_t SE_STATUS;
uint32_t SE_ERR_STATUS;
uint32_t SE_MISC;
uint32_t SE_SPARE;
uint32_t SE_ENTROPY_DEBUG_COUNTER;
uint32_t _0x814;
uint32_t _0x818;
uint32_t _0x81C;
uint32_t _0x820[0x5F8];
} tegra_se_t;
typedef struct {
uint32_t address;
uint32_t size;
} se_addr_info_t;
typedef struct {
uint32_t num_entries; /* Set to total entries - 1 */
se_addr_info_t addr_info; /* This should really be an array...but for our use case it works. */
} se_ll_t;
static inline volatile tegra_se_t *se_get_regs(void) {
return (volatile tegra_se_t *)SE_BASE;
}
void se_check_error_status_reg(void);
void se_check_for_error(void);
void se_trigger_interrupt(void);
void se_validate_stored_vector(void);
void se_generate_stored_vector(void);
void se_verify_flags_cleared(void);
void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags);
void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags);
void clear_aes_keyslot(unsigned int keyslot);
void clear_rsa_keyslot(unsigned int keyslot);
void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size);
void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_src, const void *wrapped_key, size_t wrapped_key_size);
void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_size, const void *exponent, size_t exp_size);
void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size);
void set_se_ctr(const void *ctr);
/* Secure AES API */
void se_aes_128_xts_nintendo_decrypt(unsigned int keyslot_1, unsigned int keyslot_2, unsigned int base_sector, void *dst, const void *src, size_t size, unsigned int sector_size);
void se_aes_128_xts_nintendo_encrypt(unsigned int keyslot_1, unsigned int keyslot_2, unsigned int base_sector, void *dst, const void *src, size_t size, unsigned int sector_size);
void se_compute_aes_128_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size);
void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size);
void se_aes_128_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size);
void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv);
/* Hash API */
void se_calculate_sha256(void *dst, const void *src, size_t src_size);
/* RSA API */
void se_get_exp_mod_output(void *buf, size_t size);
void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
bool se_rsa2048_pss_verify(const void *signature, size_t signature_size, const void *modulus, size_t modulus_size, const void *data, size_t data_size);
/* RNG API */
void se_initialize_rng(unsigned int keyslot);
void se_generate_random(unsigned int keyslot, void *dst, size_t size);
#endif

View File

@ -1,104 +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/>.
*/
.section .text.start, "ax", %progbits
.arm
.align 5
.global _start
.type _start, %function
_start:
/* Set coldboot */
mov r0, #0x0
ldr r1, =0x7000E400
str r0, [r1, #0x50]
/* Tell pk1ldr normal reboot, no error */
str r0, [r1, #0x1B4]
str r0, [r1, #0x840]
/* Cleanup SVC handler address. */
ldr r0, =0x40004C30
ldr r1, =0x6000F208
str r0, [r1]
/* Disable RCM forcefully */
mov r0, #0x4
ldr r1, =0x15DC
ldr r2, =0xE020
bl ipatch_word
/* Patch BCT signature check */
mov r0, #0x5
ldr r1, =0x4AEE
ldr r2, =0xE05B
bl ipatch_word
/* Patch bootloader read */
mov r0, #0x6
ldr r1, =0x4E88
ldr r2, =0xE018
bl ipatch_word
ldr r0, =__main_phys_start__
ldr r1, =__main_start__
mov r2, #0x0
ldr r3, =(__main_size__)
copy_panic_payload:
ldr r4, [r0, r2]
str r4, [r1, r2]
add r2, r2, #0x4
cmp r2, r3
bne copy_panic_payload
/* Jump back to bootrom start. */
ldr r0, =0x101010
bx r0
/* Unused, but forces inclusion in binary. */
b main
.section .text.ipatch_word, "ax", %progbits
.arm
.align 5
.global ipatch_word
.type ipatch_word, %function
ipatch_word:
ldr r3, =0x6001dc00
lsl r0, r0, #0x2
lsr r1, r1, #0x1
lsl r1, r1, #0x10
orr r1, r1, r2
str r1, [r3, r0]
bx lr
.section .text.jump_to_main, "ax", %progbits
.arm
.align 5
.global jump_to_main
.type jump_to_main, %function
jump_to_main:
/* Insert 0x240 of NOPs, for version compatibility. */
.rept (0x240/4)
nop
.endr
/* Just jump to main */
ldr sp, =__stack_top__
b main

View File

@ -1,48 +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/>.
*/
#ifndef FUSEE_SYSREG_H
#define FUSEE_SYSREG_H
#include <stdint.h>
#define SYSREG_BASE 0x6000C000
#define SB_BASE (SYSREG_BASE + 0x200)
#define EXCP_VEC_BASE 0x6000F000
#define MAKE_SYSREG(n) MAKE_REG32(SYSREG_BASE + n)
#define MAKE_SB_REG(n) MAKE_REG32(SB_BASE + n)
#define MAKE_EXCP_VEC_REG(n) MAKE_REG32(EXCP_VEC_BASE + n)
#define AHB_ARBITRATION_DISABLE_0 MAKE_SYSREG(0x004)
#define AHB_ARBITRATION_XBAR_CTRL_0 MAKE_SYSREG(0x0E0)
#define AHB_AHB_SPARE_REG_0 MAKE_SYSREG(0x110)
#define SB_CSR_0 MAKE_SB_REG(0x00)
#define SB_PIROM_START_0 MAKE_SB_REG(0x04)
#define SB_PFCFG_0 MAKE_SB_REG(0x08)
#define SB_SECURE_SPAREREG_0_0 MAKE_SB_REG(0x0C)
#define SB_SECURE_SPAREREG_1_0 MAKE_SB_REG(0x10)
#define SB_SECURE_SPAREREG_2_0 MAKE_SB_REG(0x14)
#define SB_SECURE_SPAREREG_3_0 MAKE_SB_REG(0x18)
#define SB_SECURE_SPAREREG_4_0 MAKE_SB_REG(0x1C)
#define SB_SECURE_SPAREREG_5_0 MAKE_SB_REG(0x20)
#define SB_SECURE_SPAREREG_6_0 MAKE_SB_REG(0x24)
#define SB_SECURE_SPAREREG_7_0 MAKE_SB_REG(0x28)
#define SB_AA64_RESET_LOW_0 MAKE_SB_REG(0x30)
#define SB_AA64_RESET_HIGH_0 MAKE_SB_REG(0x34)
#endif

View File

@ -1,101 +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/>.
*/
#ifndef FUSEE_TIMERS_H
#define FUSEE_TIMERS_H
#include "utils.h"
#define TIMERS_BASE 0x60005000
#define MAKE_TIMERS_REG(n) MAKE_REG32(TIMERS_BASE + n)
#define TIMERUS_CNTR_1US_0 MAKE_TIMERS_REG(0x10)
#define TIMERUS_USEC_CFG_0 MAKE_TIMERS_REG(0x14)
#define SHARED_INTR_STATUS_0 MAKE_TIMERS_REG(0x1A0)
#define SHARED_TIMER_SECURE_CFG_0 MAKE_TIMERS_REG(0x1A4)
#define RTC_BASE 0x7000E000
#define MAKE_RTC_REG(n) MAKE_REG32(RTC_BASE + n)
#define RTC_SECONDS MAKE_RTC_REG(0x08)
#define RTC_SHADOW_SECONDS MAKE_RTC_REG(0x0C)
#define RTC_MILLI_SECONDS MAKE_RTC_REG(0x10)
typedef struct {
uint32_t CONFIG;
uint32_t STATUS;
uint32_t COMMAND;
uint32_t PATTERN;
} watchdog_timers_t;
#define GET_WDT(n) ((volatile watchdog_timers_t *)(TIMERS_BASE + 0x100 + 0x20 * n))
#define WDT_REBOOT_PATTERN 0xC45A
#define GET_WDT_REBOOT_CFG_REG(n) MAKE_REG32(TIMERS_BASE + 0x60 + 0x8 * n)
void wait(uint32_t microseconds);
static inline uint32_t get_time_s(void) {
return RTC_SECONDS;
}
static inline uint32_t get_time_ms(void) {
return (RTC_MILLI_SECONDS | (RTC_SHADOW_SECONDS << 10));
}
static inline uint32_t get_time_us(void) {
return TIMERUS_CNTR_1US_0;
}
/**
* Returns the time in microseconds.
*/
static inline uint32_t get_time(void) {
return get_time_us();
}
/**
* Returns the number of microseconds that have passed since a given get_time().
*/
static inline uint32_t get_time_since(uint32_t base) {
return get_time_us() - base;
}
/**
* Delays for a given number of microseconds.
*/
static inline void udelay(uint32_t usecs) {
uint32_t start = get_time_us();
while (get_time_us() - start < usecs);
}
/**
* Delays until a number of usecs have passed since an absolute start time.
*/
static inline void udelay_absolute(uint32_t start, uint32_t usecs) {
while (get_time_us() - start < usecs);
}
/**
* Delays for a given number of milliseconds.
*/
static inline void mdelay(uint32_t msecs) {
uint32_t start = get_time_ms();
while (get_time_ms() - start < msecs);
}
__attribute__ ((noreturn)) void watchdog_reboot(void);
#endif

View File

@ -1,307 +0,0 @@
/*
* Copyright (c) 2018 naehrwert
* 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/>.
*/
#ifndef FUSEE_TSEC_H_
#define FUSEE_TSEC_H_
#include <string.h>
#include <stdbool.h>
#define TSEC_BASE 0x54500000
#define SOR1_BASE 0x54580000
#define KFUSE_BASE 0x7000FC00
#define SOR1_DP_HDCP_BKSV_LSB MAKE_REG32(SOR1_BASE + 0x1E8)
#define SOR1_TMDS_HDCP_BKSV_LSB MAKE_REG32(SOR1_BASE + 0x21C)
#define SOR1_TMDS_HDCP_CN_MSB MAKE_REG32(SOR1_BASE + 0x208)
#define SOR1_TMDS_HDCP_CN_LSB MAKE_REG32(SOR1_BASE + 0x20C)
#define KFUSE_FUSECTRL MAKE_REG32(KFUSE_BASE + 0x00)
#define KFUSE_FUSEADDR MAKE_REG32(KFUSE_BASE + 0x04)
#define KFUSE_FUSEDATA0 MAKE_REG32(KFUSE_BASE + 0x08)
#define KFUSE_FUSEWRDATA0 MAKE_REG32(KFUSE_BASE + 0x0C)
#define KFUSE_FUSETIME_RD1 MAKE_REG32(KFUSE_BASE + 0x10)
#define KFUSE_FUSETIME_RD2 MAKE_REG32(KFUSE_BASE + 0x14)
#define KFUSE_FUSETIME_PGM1 MAKE_REG32(KFUSE_BASE + 0x18)
#define KFUSE_FUSETIME_PGM2 MAKE_REG32(KFUSE_BASE + 0x1C)
#define KFUSE_REGULATOR MAKE_REG32(KFUSE_BASE + 0x20)
#define KFUSE_PD MAKE_REG32(KFUSE_BASE + 0x24)
#define KFUSE_FUSETIME_RD3 MAKE_REG32(KFUSE_BASE + 0x28)
#define KFUSE_STATE MAKE_REG32(KFUSE_BASE + 0x80)
#define KFUSE_ERRCOUNT MAKE_REG32(KFUSE_BASE + 0x84)
#define KFUSE_KEYADDR MAKE_REG32(KFUSE_BASE + 0x88)
#define KFUSE_KEYS MAKE_REG32(KFUSE_BASE + 0x8C)
typedef struct {
uint32_t TSEC_THI_INCR_SYNCPT; /* Tegra Host Interface registers. */
uint32_t TSEC_THI_INCR_SYNCPT_CTRL;
uint32_t TSEC_THI_INCR_SYNCPT_ERR;
uint32_t TSEC_THI_CTXSW_INCR_SYNCPT;
uint32_t _0x10[0x4];
uint32_t TSEC_THI_CTXSW;
uint32_t TSEC_THI_CTXSW_NEXT;
uint32_t TSEC_THI_CONT_SYNCPT_EOF;
uint32_t TSEC_THI_CONT_SYNCPT_L1;
uint32_t TSEC_THI_STREAMID0;
uint32_t TSEC_THI_STREAMID1;
uint32_t TSEC_THI_THI_SEC;
uint32_t _0x3C;
uint32_t TSEC_THI_METHOD0;
uint32_t TSEC_THI_METHOD1;
uint32_t _0x48[0x6];
uint32_t TSEC_THI_CONTEXT_SWITCH;
uint32_t _0x64[0x5];
uint32_t TSEC_THI_INT_STATUS;
uint32_t TSEC_THI_INT_MASK;
uint32_t TSEC_THI_CONFIG0;
uint32_t TSEC_THI_DBG_MISC;
uint32_t TSEC_THI_SLCG_OVERRIDE_HIGH_A;
uint32_t TSEC_THI_SLCG_OVERRIDE_LOW_A;
uint32_t _0x90[0x35C];
uint32_t TSEC_THI_CLK_OVERRIDE;
uint32_t _0xE04[0x7F];
uint32_t TSEC_FALCON_IRQSSET; /* Falcon microcontroller registers. */
uint32_t TSEC_FALCON_IRQSCLR;
uint32_t TSEC_FALCON_IRQSTAT;
uint32_t TSEC_FALCON_IRQMODE;
uint32_t TSEC_FALCON_IRQMSET;
uint32_t TSEC_FALCON_IRQMCLR;
uint32_t TSEC_FALCON_IRQMASK;
uint32_t TSEC_FALCON_IRQDEST;
uint32_t TSEC_FALCON_GPTMRINT;
uint32_t TSEC_FALCON_GPTMRVAL;
uint32_t TSEC_FALCON_GPTMRCTL;
uint32_t TSEC_FALCON_PTIMER0;
uint32_t TSEC_FALCON_PTIMER1;
uint32_t TSEC_FALCON_WDTMRVAL;
uint32_t TSEC_FALCON_WDTMRCTL;
uint32_t TSEC_FALCON_IRQDEST2;
uint32_t TSEC_FALCON_MAILBOX0;
uint32_t TSEC_FALCON_MAILBOX1;
uint32_t TSEC_FALCON_ITFEN;
uint32_t TSEC_FALCON_IDLESTATE;
uint32_t TSEC_FALCON_CURCTX;
uint32_t TSEC_FALCON_NXTCTX;
uint32_t TSEC_FALCON_CTXACK;
uint32_t TSEC_FALCON_FHSTATE;
uint32_t TSEC_FALCON_PRIVSTATE;
uint32_t TSEC_FALCON_MTHDDATA;
uint32_t TSEC_FALCON_MTHDID;
uint32_t TSEC_FALCON_MTHDWDAT;
uint32_t TSEC_FALCON_MTHDCOUNT;
uint32_t TSEC_FALCON_MTHDPOP;
uint32_t TSEC_FALCON_MTHDRAMSZ;
uint32_t TSEC_FALCON_SFTRESET;
uint32_t TSEC_FALCON_OS;
uint32_t TSEC_FALCON_RM;
uint32_t TSEC_FALCON_SOFT_PM;
uint32_t TSEC_FALCON_SOFT_MODE;
uint32_t TSEC_FALCON_DEBUG1;
uint32_t TSEC_FALCON_DEBUGINFO;
uint32_t TSEC_FALCON_IBRKPT1;
uint32_t TSEC_FALCON_IBRKPT2;
uint32_t TSEC_FALCON_CGCTL;
uint32_t TSEC_FALCON_ENGCTL;
uint32_t TSEC_FALCON_PMM;
uint32_t TSEC_FALCON_ADDR;
uint32_t TSEC_FALCON_IBRKPT3;
uint32_t TSEC_FALCON_IBRKPT4;
uint32_t TSEC_FALCON_IBRKPT5;
uint32_t _0x10BC[0x5];
uint32_t TSEC_FALCON_EXCI;
uint32_t TSEC_FALCON_SVEC_SPR;
uint32_t TSEC_FALCON_RSTAT0;
uint32_t TSEC_FALCON_RSTAT3;
uint32_t _0x10E0[0x8];
uint32_t TSEC_FALCON_CPUCTL;
uint32_t TSEC_FALCON_BOOTVEC;
uint32_t TSEC_FALCON_HWCFG;
uint32_t TSEC_FALCON_DMACTL;
uint32_t TSEC_FALCON_DMATRFBASE;
uint32_t TSEC_FALCON_DMATRFMOFFS;
uint32_t TSEC_FALCON_DMATRFCMD;
uint32_t TSEC_FALCON_DMATRFFBOFFS;
uint32_t TSEC_FALCON_DMAPOLL_FB;
uint32_t TSEC_FALCON_DMAPOLL_CP;
uint32_t TSEC_FALCON_DBG_STATE;
uint32_t TSEC_FALCON_HWCFG1;
uint32_t TSEC_FALCON_CPUCTL_ALIAS;
uint32_t _0x1134;
uint32_t TSEC_FALCON_STACKCFG;
uint32_t _0x113C;
uint32_t TSEC_FALCON_IMCTL;
uint32_t TSEC_FALCON_IMSTAT;
uint32_t TSEC_FALCON_TRACEIDX;
uint32_t TSEC_FALCON_TRACEPC;
uint32_t TSEC_FALCON_IMFILLRNG0;
uint32_t TSEC_FALCON_IMFILLRNG1;
uint32_t TSEC_FALCON_IMFILLCTL;
uint32_t TSEC_FALCON_IMCTL_DEBUG;
uint32_t TSEC_FALCON_CMEMBASE;
uint32_t TSEC_FALCON_DMEMAPERT;
uint32_t TSEC_FALCON_EXTERRADDR;
uint32_t TSEC_FALCON_EXTERRSTAT;
uint32_t _0x1170[0x3];
uint32_t TSEC_FALCON_CG2;
uint32_t TSEC_FALCON_IMEMC0;
uint32_t TSEC_FALCON_IMEMD0;
uint32_t TSEC_FALCON_IMEMT0;
uint32_t _0x118C;
uint32_t TSEC_FALCON_IMEMC1;
uint32_t TSEC_FALCON_IMEMD1;
uint32_t TSEC_FALCON_IMEMT1;
uint32_t _0x119C;
uint32_t TSEC_FALCON_IMEMC2;
uint32_t TSEC_FALCON_IMEMD2;
uint32_t TSEC_FALCON_IMEMT2;
uint32_t _0x11AC;
uint32_t TSEC_FALCON_IMEMC3;
uint32_t TSEC_FALCON_IMEMD3;
uint32_t TSEC_FALCON_IMEMT3;
uint32_t _0x11BC;
uint32_t TSEC_FALCON_DMEMC0;
uint32_t TSEC_FALCON_DMEMD0;
uint32_t TSEC_FALCON_DMEMC1;
uint32_t TSEC_FALCON_DMEMD1;
uint32_t TSEC_FALCON_DMEMC2;
uint32_t TSEC_FALCON_DMEMD2;
uint32_t TSEC_FALCON_DMEMC3;
uint32_t TSEC_FALCON_DMEMD3;
uint32_t TSEC_FALCON_DMEMC4;
uint32_t TSEC_FALCON_DMEMD4;
uint32_t TSEC_FALCON_DMEMC5;
uint32_t TSEC_FALCON_DMEMD5;
uint32_t TSEC_FALCON_DMEMC6;
uint32_t TSEC_FALCON_DMEMD6;
uint32_t TSEC_FALCON_DMEMC7;
uint32_t TSEC_FALCON_DMEMD7;
uint32_t TSEC_FALCON_ICD_CMD;
uint32_t TSEC_FALCON_ICD_ADDR;
uint32_t TSEC_FALCON_ICD_WDATA;
uint32_t TSEC_FALCON_ICD_RDATA;
uint32_t _0x1210[0xC];
uint32_t TSEC_FALCON_SCTL;
uint32_t TSEC_FALCON_SSTAT;
uint32_t _0x1248[0xE];
uint32_t TSEC_FALCON_SPROT_IMEM;
uint32_t TSEC_FALCON_SPROT_DMEM;
uint32_t TSEC_FALCON_SPROT_CPUCTL;
uint32_t TSEC_FALCON_SPROT_MISC;
uint32_t TSEC_FALCON_SPROT_IRQ;
uint32_t TSEC_FALCON_SPROT_MTHD;
uint32_t TSEC_FALCON_SPROT_SCTL;
uint32_t TSEC_FALCON_SPROT_WDTMR;
uint32_t _0x12A0[0x8];
uint32_t TSEC_FALCON_DMAINFO_FINISHED_FBRD_LOW;
uint32_t TSEC_FALCON_DMAINFO_FINISHED_FBRD_HIGH;
uint32_t TSEC_FALCON_DMAINFO_FINISHED_FBWR_LOW;
uint32_t TSEC_FALCON_DMAINFO_FINISHED_FBWR_HIGH;
uint32_t TSEC_FALCON_DMAINFO_CURRENT_FBRD_LOW;
uint32_t TSEC_FALCON_DMAINFO_CURRENT_FBRD_HIGH;
uint32_t TSEC_FALCON_DMAINFO_CURRENT_FBWR_LOW;
uint32_t TSEC_FALCON_DMAINFO_CURRENT_FBWR_HIGH;
uint32_t TSEC_FALCON_DMAINFO_CTL;
uint32_t _0x12E4[0x47];
uint32_t TSEC_SCP_CTL0; /* Secure Co-processor registers. */
uint32_t TSEC_SCP_CTL1;
uint32_t TSEC_SCP_CTL_STAT;
uint32_t TSEC_SCP_CTL_LOCK;
uint32_t TSEC_SCP_CFG;
uint32_t TSEC_SCP_CTL_SCP;
uint32_t TSEC_SCP_CTL_PKEY;
uint32_t TSEC_SCP_CTL_DBG;
uint32_t TSEC_SCP_DBG0;
uint32_t TSEC_SCP_DBG1;
uint32_t TSEC_SCP_DBG2;
uint32_t _0x142C;
uint32_t TSEC_SCP_CMD;
uint32_t _0x1434[0x7];
uint32_t TSEC_SCP_STAT0;
uint32_t TSEC_SCP_STAT1;
uint32_t TSEC_SCP_STAT2;
uint32_t _0x145C[0x5];
uint32_t TSEC_SCP_RND_STAT0;
uint32_t TSEC_SCP_RND_STAT1;
uint32_t _0x1478[0x2];
uint32_t TSEC_SCP_IRQSTAT;
uint32_t TSEC_SCP_IRQMASK;
uint32_t _0x1488[0x2];
uint32_t TSEC_SCP_ACL_ERR;
uint32_t TSEC_SCP_SEC_ERR;
uint32_t TSEC_SCP_CMD_ERR;
uint32_t _0x149C[0x19];
uint32_t TSEC_RND_CTL0; /* Random Number Generator registers. */
uint32_t TSEC_RND_CTL1;
uint32_t TSEC_RND_CTL2;
uint32_t TSEC_RND_CTL3;
uint32_t TSEC_RND_CTL4;
uint32_t TSEC_RND_CTL5;
uint32_t TSEC_RND_CTL6;
uint32_t TSEC_RND_CTL7;
uint32_t TSEC_RND_CTL8;
uint32_t TSEC_RND_CTL9;
uint32_t TSEC_RND_CTL10;
uint32_t TSEC_RND_CTL11;
uint32_t _0x1530[0x34];
uint32_t TSEC_TFBIF_CTL; /* Tegra Framebuffer Interface registers. */
uint32_t TSEC_TFBIF_MCCIF_FIFOCTRL;
uint32_t TSEC_TFBIF_THROTTLE;
uint32_t TSEC_TFBIF_DBG_STAT0;
uint32_t TSEC_TFBIF_DBG_STAT1;
uint32_t TSEC_TFBIF_DBG_RDCOUNT_LO;
uint32_t TSEC_TFBIF_DBG_RDCOUNT_HI;
uint32_t TSEC_TFBIF_DBG_WRCOUNT_LO;
uint32_t TSEC_TFBIF_DBG_WRCOUNT_HI;
uint32_t TSEC_TFBIF_DBG_R32COUNT;
uint32_t TSEC_TFBIF_DBG_R64COUNT;
uint32_t TSEC_TFBIF_DBG_R128COUNT;
uint32_t _0x1630;
uint32_t TSEC_TFBIF_MCCIF_FIFOCTRL1;
uint32_t TSEC_TFBIF_WRR_RDP;
uint32_t _0x163C;
uint32_t TSEC_TFBIF_SPROT_EMEM;
uint32_t TSEC_TFBIF_TRANSCFG;
uint32_t TSEC_TFBIF_REGIONCFG;
uint32_t TSEC_TFBIF_ACTMON_ACTIVE_MASK;
uint32_t TSEC_TFBIF_ACTMON_ACTIVE_BORPS;
uint32_t TSEC_TFBIF_ACTMON_ACTIVE_WEIGHT;
uint32_t _0x1658[0x2];
uint32_t TSEC_TFBIF_ACTMON_MCB_MASK;
uint32_t TSEC_TFBIF_ACTMON_MCB_BORPS;
uint32_t TSEC_TFBIF_ACTMON_MCB_WEIGHT;
uint32_t _0x166C;
uint32_t TSEC_TFBIF_THI_TRANSPROP;
uint32_t _0x1674[0x17];
uint32_t TSEC_CG; /* Clock Gate registers. */
uint32_t _0x16D4[0xB];
uint32_t TSEC_BAR0_CTL; /* HOST1X device DMA registers. */
uint32_t TSEC_BAR0_ADDR;
uint32_t TSEC_BAR0_DATA;
uint32_t TSEC_BAR0_TIMEOUT;
uint32_t _0x1710[0x3C];
uint32_t TSEC_TEGRA_FALCON_IP_VER; /* Miscellaneous registers. */
uint32_t _0x1804[0xD];
uint32_t TSEC_TEGRA_CTL;
uint32_t _0x183C[0x31];
} tegra_tsec_t;
static inline volatile tegra_tsec_t *tsec_get_regs(void)
{
return (volatile tegra_tsec_t *)TSEC_BASE;
}
#endif

View File

@ -1,82 +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 <stdbool.h>
#include <stdarg.h>
#include "utils.h"
#include "se.h"
#include "fuse.h"
#include "pmc.h"
#include "timers.h"
#include "panic.h"
#include "car.h"
#include "btn.h"
#include <inttypes.h>
void wait(uint32_t microseconds) {
uint32_t old_time = TIMERUS_CNTR_1US_0;
while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) {
/* Spin-lock. */
}
}
__attribute__((noreturn)) void watchdog_reboot(void) {
volatile watchdog_timers_t *wdt = GET_WDT(4);
wdt->PATTERN = WDT_REBOOT_PATTERN;
wdt->COMMAND = 2; /* Disable Counter. */
GET_WDT_REBOOT_CFG_REG(4) = 0xC0000000;
wdt->CONFIG = 0x8019; /* Full System Reset after Fourth Counter expires, using TIMER(9). */
wdt->COMMAND = 1; /* Enable Counter. */
while (true) {
/* Wait for reboot. */
}
}
__attribute__((noreturn)) void pmc_reboot(uint32_t scratch0) {
APBDEV_PMC_SCRATCH0_0 = scratch0;
/* Reset the processor. */
APBDEV_PMC_CONTROL = BIT(4);
while (true) {
/* Wait for reboot. */
}
}
__attribute__((noreturn)) void wait_for_button_and_reboot(void) {
uint32_t button;
while (true) {
button = btn_read();
if (button & BTN_POWER) {
pmc_reboot(2);
}
}
}
__attribute__ ((noreturn)) void generic_panic(void) {
panic(0xFF000006);
}
__attribute__((noinline)) bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, uint64_t be)
{
if(as <= bs && bs <= ae)
return true;
if(bs <= as && as <= be)
return true;
return false;
}

View File

@ -1,128 +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/>.
*/
#ifndef FUSEE_UTILS_H
#define FUSEE_UTILS_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#define BIT(n) (1u << (n))
#define BITL(n) (1ull << (n))
#define MASK(n) (BIT(n) - 1)
#define MASKL(n) (BITL(n) - 1)
#define MASK2(a,b) (MASK(a) & ~MASK(b))
#define MASK2L(a,b) (MASKL(a) & ~MASKL(b))
#define MAKE_REG32(a) (*(volatile uint32_t *)(a))
#define ALIGN(m) __attribute__((aligned(m)))
#define PACKED __attribute__((packed))
#define ALINLINE __attribute__((always_inline))
#define NOINLINE __attribute__((noinline))
#define SET_SYSREG(reg, val) do { temp_reg = (val); __asm__ __volatile__ ("msr " #reg ", %0" :: "r"(temp_reg) : "memory"); } while(false)
static inline uintptr_t get_physical_address(const void *addr) {
return (uintptr_t)addr;
}
static inline uint32_t read32le(const volatile void *dword, size_t offset) {
uintptr_t addr = (uintptr_t)dword + offset;
volatile uint32_t *target = (uint32_t *)addr;
return *target;
}
static inline uint32_t read32be(const volatile void *dword, size_t offset) {
return __builtin_bswap32(read32le(dword, offset));
}
static inline uint64_t read64le(const volatile void *qword, size_t offset) {
uintptr_t addr = (uintptr_t)qword + offset;
volatile uint64_t *target = (uint64_t *)addr;
return *target;
}
static inline uint64_t read64be(const volatile void *qword, size_t offset) {
return __builtin_bswap64(read64le(qword, offset));
}
static inline void write32le(volatile void *dword, size_t offset, uint32_t value) {
uintptr_t addr = (uintptr_t)dword + offset;
volatile uint32_t *target = (uint32_t *)addr;
*target = value;
}
static inline void write32be(volatile void *dword, size_t offset, uint32_t value) {
write32le(dword, offset, __builtin_bswap32(value));
}
static inline void write64le(volatile void *qword, size_t offset, uint64_t value) {
uintptr_t addr = (uintptr_t)qword + offset;
volatile uint64_t *target = (uint64_t *)addr;
*target = value;
}
static inline void write64be(volatile void *qword, size_t offset, uint64_t value) {
write64le(qword, offset, __builtin_bswap64(value));
}
static inline bool check_32bit_additive_overflow(uint32_t a, uint32_t b) {
return __builtin_add_overflow_p(a, b, (uint32_t)0);
}
static inline bool check_32bit_address_loadable(uintptr_t addr) {
/* FWIW the bootROM forbids loading anything between 0x40000000 and 0x40010000, using it for itself... */
return (addr >= 0x40010000u && addr < 0x40040000u) || addr >= 0x80000000u;
}
static inline bool check_32bit_address_range_loadable(uintptr_t addr, size_t size) {
return
!__builtin_add_overflow_p(addr, size, (uintptr_t)0) && /* the range doesn't overflow */
check_32bit_address_loadable(addr) && check_32bit_address_loadable(addr + size) && /* bounds are valid */
!(addr >= 0x40010000u && addr < 0x40040000u && addr + size >= 0x40040000u) /* the range doesn't cross MMIO */
;
}
bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, uint64_t be);
static inline bool overlaps_a(const void *as, const void *ae, const void *bs, const void *be) {
return overlaps((uint64_t)(uintptr_t)as, (uint64_t)(uintptr_t)ae, (uint64_t)(uintptr_t)bs, (uint64_t)(uintptr_t)be);
}
static inline bool check_32bit_address_range_in_program(uintptr_t addr, size_t size) {
extern uint8_t __chainloader_start__[], __chainloader_end__[];
extern uint8_t __stack_bottom__[], __stack_top__[];
extern uint8_t __start__[], __end__[];
uint8_t *start = (uint8_t *)addr, *end = start + size;
return overlaps_a(start, end, __chainloader_start__, __chainloader_end__) ||
overlaps_a(start, end, __stack_bottom__, __stack_top__) ||
overlaps_a(start, end, (void *)0xC0000000, (void *)0xC03C0000) || /* framebuffer */
overlaps_a(start, end, __start__, __end__);
}
void hexdump(const void* data, size_t size, uintptr_t addrbase);
__attribute__((noreturn)) void watchdog_reboot(void);
__attribute__((noreturn)) void pmc_reboot(uint32_t scratch0);
__attribute__((noreturn)) void wait_for_button_and_reboot(void);
__attribute__((noreturn)) void generic_panic(void);
#endif

View File

@ -1,38 +0,0 @@
NUM_KEYS = 2
HOVI_ENC_KEY_PRD = [
bytearray.fromhex('00000000000000000000000000000000'),
bytearray.fromhex('00000000000000000000000000000000'),
]
HOVI_SIG_KEY_PRD = [
bytearray.fromhex('00000000000000000000000000000000'),
bytearray.fromhex('00000000000000000000000000000000'),
]
HOVI_ENC_KEY_DEV = [
bytearray.fromhex('00000000000000000000000000000000'),
bytearray.fromhex('00000000000000000000000000000000'),
]
HOVI_SIG_KEY_DEV = [
bytearray.fromhex('00000000000000000000000000000000'),
bytearray.fromhex('00000000000000000000000000000000'),
]
IV = [
bytearray.fromhex('00000000000000000000000000000000'),
bytearray.fromhex('00000000000000000000000000000000'),
]
IV_DEV = [
bytearray.fromhex('00000000000000000000000000000000'),
bytearray.fromhex('00000000000000000000000000000000'),
]
assert len(HOVI_ENC_KEY_PRD) == NUM_KEYS
assert len(HOVI_SIG_KEY_PRD) == NUM_KEYS
assert len(HOVI_ENC_KEY_DEV) == NUM_KEYS
assert len(HOVI_SIG_KEY_DEV) == NUM_KEYS
assert len(IV) == NUM_KEYS
assert len(IV_DEV) == NUM_KEYS

View File

@ -1,196 +0,0 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
AMS := $(TOPDIR)/../../
include $(DEVKITARM)/base_rules
AMSBRANCH := $(shell git symbolic-ref --short HEAD)
AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD)
ifneq (, $(strip $(shell git status --porcelain 2>/dev/null)))
AMSREV := $(AMSREV)-dirty
endif
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := src ../../fusee/common ../../fusee/common/display ../../fusee/common/fatfs ../../fusee/common/sdmmc
DATA := data
INCLUDES := include ../../libraries/libvapours/include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
DEFINES := -D__BPMP__ -DSEPT_STAGE2_SRC -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\"
CFLAGS := \
-g \
-gdwarf-4 \
-O2 \
-fomit-frame-pointer \
-ffunction-sections \
-fdata-sections \
-std=gnu11 \
-Werror \
-Wall \
-Wno-array-bounds \
-Wno-stringop-overflow \
-Wno-stringop-overread \
-fstrict-volatile-bitfields \
$(ARCH) $(DEFINES)
CFLAGS += $(INCLUDE)
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g -gdwarf-4 $(ARCH)
LDFLAGS = -specs=$(TOPDIR)/linker.specs -g -gdwarf-4 $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS :=
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS :=
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
$(AMS)/exosphere/program/rebootstub \
$(TOPDIR)/key_derivation
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) rebootstub.bin key_derivation.bin
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
.PHONY: $(BUILD) clean all check_rebootstub check_key_derivation
#---------------------------------------------------------------------------------
all: check_rebootstub check_key_derivation $(BUILD)
check_rebootstub:
@$(MAKE) -C $(AMS)/exosphere/program/rebootstub all
check_key_derivation:
@$(MAKE) -C key_derivation
$(BUILD): check_rebootstub check_key_derivation
ifeq ($(strip $(SEPT_00_ENC_PATH)),)
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
else
@touch $(TOPDIR)/$(TARGET).bin
@cp $(SEPT_00_ENC_PATH) $(TOPDIR)/$(TARGET)_00.enc
@cp $(SEPT_01_ENC_PATH) $(TOPDIR)/$(TARGET)_01.enc
@cp $(SEPT_DEV_00_ENC_PATH) $(TOPDIR)/$(TARGET)_dev_00.enc
@cp $(SEPT_DEV_01_ENC_PATH) $(TOPDIR)/$(TARGET)_dev_01.enc
endif
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@$(MAKE) -C $(AMS)/exosphere/program/rebootstub clean
@$(MAKE) -C key_derivation clean
@rm -fr $(BUILD) $(TARGET).bin $(TARGET)_*.enc $(TARGET).elf
#---------------------------------------------------------------------------------
else
.PHONY: all
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
all : $(OUTPUT)_dev_01.enc
$(OUTPUT)_dev_01.enc : $(OUTPUT)_dev_00.enc
$(OUTPUT)_dev_00.enc : $(OUTPUT)_01.enc
$(OUTPUT)_01.enc : $(OUTPUT)_00.enc
$(OUTPUT)_00.enc : $(OUTPUT).bin
@python $(TOPDIR)/sept_sign.py $(OUTPUT).bin $(OUTPUT).enc
@echo built ... $(notdir $@)
$(OUTPUT).bin : $(OUTPUT).elf
$(OBJCOPY) -S -O binary $< $@
@echo built ... $(notdir $@)
$(OUTPUT).elf : $(OFILES)
%.elf: $(OFILES)
@echo linking $(notdir $@)
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
@$(NM) -CSn $@ > $(notdir $*.lst)
$(OFILES_SRC) : $(HFILES_BIN)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o %_bin.h: %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

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

View File

@ -1,17 +0,0 @@
OUTPUT_ARCH(aarch64)
ENTRY(_start)
SECTIONS
{
. = 0x4003D000;
__start__ = ABSOLUTE(.);
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
.bss : ALIGN(8) { __bss_start__ = .; *(.bss* COMMON); . = ALIGN(8); __bss_end__ = .; }
. = ALIGN(4);
__end__ = ABSOLUTE(.);
}

View File

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

View File

@ -1,155 +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 <string.h>
#include "pmc.h"
#include "se.h"
#include "utils.h"
#define AL16 __attribute__((aligned(16)))
#define DERIVATION_ID_MAX 2
static const uint8_t AL16 keyblob_seed_00[0x10] = {
0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3
};
static const uint8_t AL16 masterkey_seed[0x10] = {
0xD8, 0xA2, 0x41, 0x0A, 0xC6, 0xC5, 0x90, 0x01, 0xC6, 0x1D, 0x6A, 0x26, 0x7C, 0x51, 0x3F, 0x3C
};
static const uint8_t AL16 devicekey_seed[0x10] = {
0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78
};
static const uint8_t AL16 devicekey_4x_seed[0x10] = {
0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28
};
static const uint8_t AL16 masterkey_4x_seed[0x10] = {
0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66
};
static const uint8_t AL16 zeroes[0x10] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* Note: 9.0.0 did not change the TSEC firmware. Thus, the root key is the same. */
/* To avoid distribution of more and more sept binaries, we will simply derive the 9.0.0 master key */
/* on 8.1.0 and 9.0.0. Exosphere supports this already with no issues. */
static const uint8_t AL16 master_kek_seeds[DERIVATION_ID_MAX][0x10] = {
{0x9A, 0x3E, 0xA9, 0xAB, 0xFD, 0x56, 0x46, 0x1C, 0x9B, 0xF6, 0x48, 0x7F, 0x5C, 0xFA, 0x09, 0x5C},
/* 8.1.0: {0xDE, 0xDC, 0xE3, 0x39, 0x30, 0x88, 0x16, 0xF8, 0xAE, 0x97, 0xAD, 0xEC, 0x64, 0x2D, 0x41, 0x41}, */
/* 9.0.0: {0x1A, 0xEC, 0x11, 0x82, 0x2B, 0x32, 0x38, 0x7A, 0x2B, 0xED, 0xBA, 0x01, 0x47, 0x7E, 0x3B, 0x67}, */
/* 9.1.0: {0x30, 0x3F, 0x02, 0x7E, 0xD8, 0x38, 0xEC, 0xD7, 0x93, 0x25, 0x34, 0xB5, 0x30, 0xEB, 0xCA, 0x7A}, */
{0x84, 0x67, 0xB6, 0x7F, 0x13, 0x11, 0xAE, 0xE6, 0x58, 0x9B, 0x19, 0xAF, 0x13, 0x6C, 0x80, 0x7A},
};
static const uint8_t AL16 master_devkey_seeds[DERIVATION_ID_MAX][0x10] = {
{0x8F, 0x77, 0x5A, 0x96, 0xB0, 0x94, 0xFD, 0x8D, 0x28, 0xE4, 0x19, 0xC8, 0x16, 0x1C, 0xDB, 0x3D},
/* 8.1.0: {0x67, 0x62, 0xD4, 0x8E, 0x55, 0xCF, 0xFF, 0x41, 0x31, 0x15, 0x3B, 0x24, 0x0C, 0x7C, 0x07, 0xAE}, */
/* 9.0.0: {0x4A, 0xC3, 0x4E, 0x14, 0x8B, 0x96, 0x4A, 0xD5, 0xD4, 0x99, 0x73, 0xC4, 0x45, 0xAB, 0x8B, 0x49}, */
/* 9.1.0: {0x14, 0xB8, 0x74, 0x12, 0xCB, 0xBD, 0x0B, 0x8F, 0x20, 0xFB, 0x30, 0xDA, 0x27, 0xE4, 0x58, 0x94}, */
{0xAA, 0xFD, 0xBC, 0xBB, 0x25, 0xC3, 0xA4, 0xEF, 0xE3, 0xEE, 0x58, 0x53, 0xB7, 0xF8, 0xDD, 0xD6},
};
static const uint8_t AL16 master_devkey_vectors[DERIVATION_ID_MAX][0x10] = {
{0xD8, 0xD3, 0x67, 0x4F, 0xF3, 0xA2, 0xA4, 0x4E, 0xE4, 0x04, 0x37, 0xC2, 0xD9, 0xCF, 0x41, 0x6F},
/* 8.1.0: {0x72, 0xD0, 0xAD, 0xEB, 0xE1, 0xF6, 0x35, 0x90, 0xB4, 0x43, 0xCC, 0x4B, 0xC4, 0xDC, 0x88, 0x0A}, */
/* 9.0.0: {0x8B, 0xD6, 0x13, 0x2F, 0xC3, 0x4D, 0x53, 0x2D, 0x10, 0xA1, 0x63, 0x85, 0x49, 0x2B, 0xCF, 0x3F}, */
/* 9.1.0: {0xA8, 0x58, 0x05, 0x8D, 0xDD, 0x9A, 0xA0, 0x2F, 0x01, 0x62, 0x4A, 0x6B, 0xC6, 0x77, 0xE9, 0x86}, */
{0x95, 0x7E, 0x99, 0xB4, 0x4B, 0xDE, 0xA0, 0xA3, 0x9A, 0x51, 0xF0, 0x32, 0xB7, 0xDF, 0x89, 0x0D},
};
void derive_keys(void) {
/* Set mailbox. */
volatile uint32_t *mailbox = (volatile uint32_t *)0x4003FF00;
const uint32_t derivation_id = *((volatile uint32_t *)0x4003E800);
if (derivation_id < DERIVATION_ID_MAX) {
uint8_t *enc_se_state = (uint8_t *)0x4003E000;
uint32_t AL16 work_buffer[4];
/* Derive Keyblob Key 00. */
se_aes_ecb_decrypt_block(0xC, work_buffer, 0x10, keyblob_seed_00, 0x10);
decrypt_data_into_keyslot(0xF, 0xE, work_buffer, 0x10);
/* Derive master kek. */
decrypt_data_into_keyslot(0xE, 0xD, master_kek_seeds[derivation_id], 0x10);
/* Clear the copy of the root key inside the SE. */
clear_aes_keyslot(0xD);
/* Derive master key, device master key. */
decrypt_data_into_keyslot(0xC, 0xE, masterkey_seed, 0x10);
decrypt_data_into_keyslot(0xE, 0xE, masterkey_4x_seed, 0x10);
clear_aes_keyslot(0xD);
/* Derive device keys. */
decrypt_data_into_keyslot(0xA, 0xF, devicekey_4x_seed, 0x10);
decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10);
clear_aes_keyslot(0xD);
/* Derive firmware specific device key. */
se_aes_ecb_decrypt_block(0xA, work_buffer, 0x10, master_devkey_seeds[derivation_id], 0x10);
decrypt_data_into_keyslot(0xE, 0xE, work_buffer, 0x10);
clear_aes_keyslot(0xD);
/* Test against a vector. */
for (size_t i = 0; i < 4; i++) {
work_buffer[i] = 0;
}
if (memcmp(work_buffer, zeroes, 0x10) != 0) {
clear_aes_keyslot(0xE);
clear_aes_keyslot(0xD);
clear_aes_keyslot(0xC);
clear_aes_keyslot(0xA);
clear_aes_keyslot(0xF);
generic_panic();
}
se_aes_ecb_decrypt_block(0xE, work_buffer, 0x10, master_devkey_vectors[derivation_id], 0x10);
if (memcmp(work_buffer, zeroes, 0x10) == 0) {
clear_aes_keyslot(0xE);
clear_aes_keyslot(0xD);
clear_aes_keyslot(0xC);
clear_aes_keyslot(0xA);
clear_aes_keyslot(0xF);
generic_panic();
}
/* Clear work buffer. */
for (size_t i = 0; i < 4; i++) {
work_buffer[i] = 0xCCCCCCCC;
}
/* Save context for real. */
se_set_in_context_save_mode(true);
se_save_context(KEYSLOT_SWITCH_SRKGENKEY, KEYSLOT_SWITCH_RNGKEY, enc_se_state);
se_set_in_context_save_mode(false);
}
/* Clear all keyslots. */
for (size_t i = 0; i < 0x10; i++) {
clear_aes_keyslot(i);
}
*mailbox = 7;
while (1) { /* Wait for sept to handle the rest. */ }
}

View File

@ -1,26 +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/>.
*/
#ifndef SEPT_KEYDERIVATION_H
#define SEPT_KEYDERIVATION_H
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
void derive_keys(void);
#endif

View File

@ -1,713 +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/>.
*/
#ifndef FUSEE_PMC_H
#define FUSEE_PMC_H
#include <stdint.h>
#define PMC_BASE 0x7000E400
#define MAKE_PMC_REG(n) MAKE_REG32(PMC_BASE + n)
#define PMC_CONTROL_SDMMC1 (1 << 12)
#define PMC_CONTROL_SDMMC3 (1 << 13)
#define PMC_CONTROL_SDMMC4 (1 << 14)
#define APBDEV_PMC_CONTROL MAKE_PMC_REG(0x00)
#define APBDEV_PM_0 MAKE_PMC_REG(0x14)
#define APBDEV_PMC_DPD_ENABLE_0 MAKE_PMC_REG(0x24)
#define APBDEV_PMC_PWRGATE_TOGGLE_0 MAKE_PMC_REG(0x30)
#define APBDEV_PMC_PWRGATE_STATUS_0 MAKE_PMC_REG(0x38)
#define APBDEV_PMC_NO_IOPOWER_0 MAKE_PMC_REG(0x44)
#define APBDEV_PMC_SCRATCH0_0 MAKE_PMC_REG(0x50)
#define APBDEV_PMC_SCRATCH1_0 MAKE_PMC_REG(0x54)
#define APBDEV_PMC_SCRATCH20_0 MAKE_PMC_REG(0xA0)
#define APBDEV_PMC_PWR_DET_VAL_0 MAKE_PMC_REG(0xE4)
#define APBDEV_PMC_DDR_PWR_0 MAKE_PMC_REG(0xE8)
#define APBDEV_PMC_CRYPTO_OP_0 MAKE_PMC_REG(0xF4)
#define APBDEV_PMC_WAKE2_STATUS_0 MAKE_PMC_REG(0x168)
#define APBDEV_PMC_OSC_EDPD_OVER_0 MAKE_PMC_REG(0x1A4)
#define APBDEV_PMC_RST_STATUS_0 MAKE_PMC_REG(0x1B4)
#define APBDEV_PMC_IO_DPD_REQ_0 MAKE_PMC_REG(0x1B8)
#define APBDEV_PMC_IO_DPD2_REQ_0 MAKE_PMC_REG(0x1C0)
#define APBDEV_PMC_VDDP_SEL_0 MAKE_PMC_REG(0x1CC)
#define APBDEV_PMC_SCRATCH49_0 MAKE_PMC_REG(0x244)
#define APBDEV_PMC_TSC_MULT_0 MAKE_PMC_REG(0x2B4)
#define APBDEV_PMC_REG_SHORT_0 MAKE_PMC_REG(0x2CC)
#define APBDEV_PMC_WEAK_BIAS_0 MAKE_PMC_REG(0x2C8)
#define APBDEV_PMC_SECURE_SCRATCH21_0 MAKE_PMC_REG(0x334)
#define APBDEV_PMC_SECURE_SCRATCH32_0 MAKE_PMC_REG(0x360)
#define APBDEV_PMC_SECURE_SCRATCH49_0 MAKE_PMC_REG(0x3A4)
#define APBDEV_PMC_CNTRL2_0 MAKE_PMC_REG(0x440)
#define APBDEV_PMC_IO_DPD4_REQ_0 MAKE_PMC_REG(0x464)
#define APBDEV_PMC_UTMIP_PAD_CFG1_0 MAKE_PMC_REG(0x4C4)
#define APBDEV_PMC_UTMIP_PAD_CFG3_0 MAKE_PMC_REG(0x4CC)
#define APBDEV_PMC_DDR_CNTRL_0 MAKE_PMC_REG(0x4E4)
#define APBDEV_PMC_SCRATCH43_0 MAKE_PMC_REG(0x22C)
#define APBDEV_PMC_SCRATCH188_0 MAKE_PMC_REG(0x810)
#define APBDEV_PMC_SCRATCH190_0 MAKE_PMC_REG(0x818)
#define APBDEV_PMC_SCRATCH200_0 MAKE_PMC_REG(0x840)
#define APBDEV_PMC_SCRATCH45_0 MAKE_PMC_REG(0x234)
#define APBDEV_PMC_SCRATCH46_0 MAKE_PMC_REG(0x238)
#define APBDEV_PMC_SCRATCH33_0 MAKE_PMC_REG(0x120)
#define APBDEV_PMC_SCRATCH40_0 MAKE_PMC_REG(0x13C)
/* Power Management Controller (APBDEV_PMC_) regs */
typedef struct {
uint32_t cntrl; /* _CNTRL_0, 0x00 */
uint32_t sec_disable; /* _SEC_DISABLE_0, 0x04 */
uint32_t pmc_swrst; /* _PMC_SWRST_0, 0x08 */
uint32_t wake_mask; /* _WAKE_MASK_0, 0x0c */
uint32_t wake_lvl; /* _WAKE_LVL_0, 0x10 */
uint32_t wake_status; /* _WAKE_STATUS_0, 0x14 */
uint32_t sw_wake_status; /* _SW_WAKE_STATUS_0, 0x18 */
uint32_t dpd_pads_oride; /* _DPD_PADS_ORIDE_0, 0x1c */
uint32_t dpd_sample; /* _DPD_SAMPLE_0, 0x20 */
uint32_t dpd_enable; /* _DPD_ENABLE_0, 0x24 */
uint32_t pwrgate_timer_off; /* _PWRGATE_TIMER_OFF_0, 0x28 */
uint32_t clamp_status; /* _CLAMP_STATUS_0, 0x2c */
uint32_t pwrgate_toggle; /* _PWRGATE_TOGGLE_0, 0x30 */
uint32_t remove_clamping; /* _REMOVE_CLAMPING_0, 0x34 */
uint32_t pwrgate_status; /* _PWRGATE_STATUS_0, 0x38 */
uint32_t pwrgood_timer; /* _PWRGOOD_TIMER_0, 0x3c */
uint32_t blink_timer; /* _BLINK_TIMER_0, 0x40 */
uint32_t no_iopower; /* _NO_IOPOWER_0, 0x44 */
uint32_t pwr_det; /* _PWR_DET_0, 0x48 */
uint32_t pwr_det_latch; /* _PWR_DET_LATCH_0, 0x4c */
uint32_t scratch0; /* _SCRATCH0_0, 0x50 */
uint32_t scratch1; /* _SCRATCH1_0, 0x54 */
uint32_t scratch2; /* _SCRATCH2_0, 0x58 */
uint32_t scratch3; /* _SCRATCH3_0, 0x5c */
uint32_t scratch4; /* _SCRATCH4_0, 0x60 */
uint32_t scratch5; /* _SCRATCH5_0, 0x64 */
uint32_t scratch6; /* _SCRATCH6_0, 0x68 */
uint32_t scratch7; /* _SCRATCH7_0, 0x6c */
uint32_t scratch8; /* _SCRATCH8_0, 0x70 */
uint32_t scratch9; /* _SCRATCH9_0, 0x74 */
uint32_t scratch10; /* _SCRATCH10_0, 0x78 */
uint32_t scratch11; /* _SCRATCH11_0, 0x7c */
uint32_t scratch12; /* _SCRATCH12_0, 0x80 */
uint32_t scratch13; /* _SCRATCH13_0, 0x84 */
uint32_t scratch14; /* _SCRATCH14_0, 0x88 */
uint32_t scratch15; /* _SCRATCH15_0, 0x8c */
uint32_t scratch16; /* _SCRATCH16_0, 0x90 */
uint32_t scratch17; /* _SCRATCH17_0, 0x94 */
uint32_t scratch18; /* _SCRATCH18_0, 0x98 */
uint32_t scratch19; /* _SCRATCH19_0, 0x9c */
uint32_t scratch20; /* _SCRATCH20_0, 0xa0 */
uint32_t scratch21; /* _SCRATCH21_0, 0xa4 */
uint32_t scratch22; /* _SCRATCH22_0, 0xa8 */
uint32_t scratch23; /* _SCRATCH23_0, 0xac */
uint32_t secure_scratch0; /* _SECURE_SCRATCH0_0, 0xb0 */
uint32_t secure_scratch1; /* _SECURE_SCRATCH1_0, 0xb4 */
uint32_t secure_scratch2; /* _SECURE_SCRATCH2_0, 0xb8 */
uint32_t secure_scratch3; /* _SECURE_SCRATCH3_0, 0xbc */
uint32_t secure_scratch4; /* _SECURE_SCRATCH4_0, 0xc0 */
uint32_t secure_scratch5; /* _SECURE_SCRATCH5_0, 0xc4 */
uint32_t cpupwrgood_timer; /* _CPUPWRGOOD_TIMER_0, 0xc8 */
uint32_t cpupwroff_timer; /* _CPUPWROFF_TIMER_0, 0xcc */
uint32_t pg_mask; /* _PG_MASK_0, 0xd0 */
uint32_t pg_mask_1; /* _PG_MASK_1_0, 0xd4 */
uint32_t auto_wake_lvl; /* _AUTO_WAKE_LVL_0, 0xd8 */
uint32_t auto_wake_lvl_mask; /* _AUTO_WAKE_LVL_MASK_0, 0xdc */
uint32_t wake_delay; /* _WAKE_DELAY_0, 0xe0 */
uint32_t pwr_det_val; /* _PWR_DET_VAL_0, 0xe4 */
uint32_t ddr_pwr; /* _DDR_PWR_0, 0xe8 */
uint32_t usb_debounce_del; /* _USB_DEBOUNCE_DEL_0, 0xec */
uint32_t usb_ao; /* _USB_AO_0, 0xf0 */
uint32_t crypto_op; /* _CRYPTO_OP_0, 0xf4 */
uint32_t pllp_wb0_override; /* _PLLP_WB0_OVERRIDE_0, 0xf8 */
uint32_t scratch24; /* _SCRATCH24_0, 0xfc */
uint32_t scratch25; /* _SCRATCH25_0, 0x100 */
uint32_t scratch26; /* _SCRATCH26_0, 0x104 */
uint32_t scratch27; /* _SCRATCH27_0, 0x108 */
uint32_t scratch28; /* _SCRATCH28_0, 0x10c */
uint32_t scratch29; /* _SCRATCH29_0, 0x110 */
uint32_t scratch30; /* _SCRATCH30_0, 0x114 */
uint32_t scratch31; /* _SCRATCH31_0, 0x118 */
uint32_t scratch32; /* _SCRATCH32_0, 0x11c */
uint32_t scratch33; /* _SCRATCH33_0, 0x120 */
uint32_t scratch34; /* _SCRATCH34_0, 0x124 */
uint32_t scratch35; /* _SCRATCH35_0, 0x128 */
uint32_t scratch36; /* _SCRATCH36_0, 0x12c */
uint32_t scratch37; /* _SCRATCH37_0, 0x130 */
uint32_t scratch38; /* _SCRATCH38_0, 0x134 */
uint32_t scratch39; /* _SCRATCH39_0, 0x138 */
uint32_t scratch40; /* _SCRATCH40_0, 0x13c */
uint32_t scratch41; /* _SCRATCH41_0, 0x140 */
uint32_t scratch42; /* _SCRATCH42_0, 0x144 */
uint32_t bondout_mirror0; /* _BONDOUT_MIRROR0_0, 0x148 */
uint32_t bondout_mirror1; /* _BONDOUT_MIRROR1_0, 0x14c */
uint32_t bondout_mirror2; /* _BONDOUT_MIRROR2_0, 0x150 */
uint32_t sys_33v_en; /* _SYS_33V_EN_0, 0x154 */
uint32_t bondout_mirror_access; /* _BONDOUT_MIRROR_ACCESS_0, 0x158 */
uint32_t gate; /* _GATE_0, 0x15c */
uint32_t wake2_mask; /* _WAKE2_MASK_0, 0x160 */
uint32_t wake2_lvl; /* _WAKE2_LVL_0, 0x164 */
uint32_t wake2_status; /* _WAKE2_STATUS_0, 0x168 */
uint32_t sw_wake2_status; /* _SW_WAKE2_STATUS_0, 0x16c */
uint32_t auto_wake2_lvl_mask; /* _AUTO_WAKE2_LVL_MASK_0, 0x170 */
uint32_t pg_mask_2; /* _PG_MASK_2_0, 0x174 */
uint32_t pg_mask_ce1; /* _PG_MASK_CE1_0, 0x178 */
uint32_t pg_mask_ce2; /* _PG_MASK_CE2_0, 0x17c */
uint32_t pg_mask_ce3; /* _PG_MASK_CE3_0, 0x180 */
uint32_t pwrgate_timer_ce_0; /* _PWRGATE_TIMER_CE_0_0, 0x184 */
uint32_t pwrgate_timer_ce_1; /* _PWRGATE_TIMER_CE_1_0, 0x188 */
uint32_t pwrgate_timer_ce_2; /* _PWRGATE_TIMER_CE_2_0, 0x18c */
uint32_t pwrgate_timer_ce_3; /* _PWRGATE_TIMER_CE_3_0, 0x190 */
uint32_t pwrgate_timer_ce_4; /* _PWRGATE_TIMER_CE_4_0, 0x194 */
uint32_t pwrgate_timer_ce_5; /* _PWRGATE_TIMER_CE_5_0, 0x198 */
uint32_t pwrgate_timer_ce_6; /* _PWRGATE_TIMER_CE_6_0, 0x19c */
uint32_t pcx_edpd_cntrl; /* _PCX_EDPD_CNTRL_0, 0x1a0 */
uint32_t osc_edpd_over; /* _OSC_EDPD_OVER_0, 0x1a4 */
uint32_t clk_out_cntrl; /* _CLK_OUT_CNTRL_0, 0x1a8 */
uint32_t sata_pwrgt; /* _SATA_PWRGT_0, 0x1ac */
uint32_t sensor_ctrl; /* _SENSOR_CTRL_0, 0x1b0 */
uint32_t rst_status; /* _RST_STATUS_0, 0x1b4 */
uint32_t io_dpd_req; /* _IO_DPD_REQ_0, 0x1b8 */
uint32_t io_dpd_status; /* _IO_DPD_STATUS_0, 0x1bc */
uint32_t io_dpd2_req; /* _IO_DPD2_REQ_0, 0x1c0 */
uint32_t io_dpd2_status; /* _IO_DPD2_STATUS_0, 0x1c4 */
uint32_t sel_dpd_tim; /* _SEL_DPD_TIM_0, 0x1c8 */
uint32_t vddp_sel; /* _VDDP_SEL_0, 0x1cc */
uint32_t ddr_cfg; /* _DDR_CFG_0, 0x1d0 */
uint32_t _0x1d4[2];
uint32_t pllm_wb0_override_freq; /* _PLLM_WB0_OVERRIDE_FREQ_0, 0x1dc */
uint32_t _0x1e0;
uint32_t pwrgate_timer_mult; /* _PWRGATE_TIMER_MULT_0, 0x1e4 */
uint32_t dsi_sel_dpd; /* _DSI_SEL_DPD_0, 0x1e8 */
uint32_t utmip_uhsic_triggers; /* _UTMIP_UHSIC_TRIGGERS_0, 0x1ec */
uint32_t utmip_uhsic_saved_state; /* _UTMIP_UHSIC_SAVED_STATE_0, 0x1f0 */
uint32_t _0x1f4;
uint32_t utmip_term_pad_cfg; /* _UTMIP_TERM_PAD_CFG_0, 0x1f8 */
uint32_t utmip_uhsic_sleep_cfg; /* _UTMIP_UHSIC_SLEEP_CFG_0, 0x1fc */
uint32_t utmip_uhsic_sleepwalk_cfg; /* _UTMIP_UHSIC_SLEEPWALK_CFG_0, 0x200 */
uint32_t utmip_sleepwalk_p0; /* _UTMIP_SLEEPWALK_P0_0, 0x204 */
uint32_t utmip_sleepwalk_p1; /* _UTMIP_SLEEPWALK_P1_0, 0x208 */
uint32_t utmip_sleepwalk_p2; /* _UTMIP_SLEEPWALK_P2_0, 0x20c */
uint32_t uhsic_sleepwalk_p0; /* _UHSIC_SLEEPWALK_P0_0, 0x210 */
uint32_t utmip_uhsic_status; /* _UTMIP_UHSIC_STATUS_0, 0x214 */
uint32_t utmip_uhsic_fake; /* _UTMIP_UHSIC_FAKE_0, 0x218 */
uint32_t bondout_mirror3; /* _BONDOUT_MIRROR3_0, 0x21c */
uint32_t bondout_mirror4; /* _BONDOUT_MIRROR4_0, 0x220 */
uint32_t secure_scratch6; /* _SECURE_SCRATCH6_0, 0x224 */
uint32_t secure_scratch7; /* _SECURE_SCRATCH7_0, 0x228 */
uint32_t scratch43; /* _SCRATCH43_0, 0x22c */
uint32_t scratch44; /* _SCRATCH44_0, 0x230 */
uint32_t scratch45; /* _SCRATCH45_0, 0x234 */
uint32_t scratch46; /* _SCRATCH46_0, 0x238 */
uint32_t scratch47; /* _SCRATCH47_0, 0x23c */
uint32_t scratch48; /* _SCRATCH48_0, 0x240 */
uint32_t scratch49; /* _SCRATCH49_0, 0x244 */
uint32_t scratch50; /* _SCRATCH50_0, 0x248 */
uint32_t scratch51; /* _SCRATCH51_0, 0x24c */
uint32_t scratch52; /* _SCRATCH52_0, 0x250 */
uint32_t scratch53; /* _SCRATCH53_0, 0x254 */
uint32_t scratch54; /* _SCRATCH54_0, 0x258 */
uint32_t scratch55; /* _SCRATCH55_0, 0x25c */
uint32_t scratch0_eco; /* _SCRATCH0_ECO_0, 0x260 */
uint32_t por_dpd_ctrl; /* _POR_DPD_CTRL_0, 0x264 */
uint32_t scratch2_eco; /* _SCRATCH2_ECO_0, 0x268 */
uint32_t utmip_uhsic_line_wakeup; /* _UTMIP_UHSIC_LINE_WAKEUP_0, 0x26c */
uint32_t utmip_bias_master_cntrl; /* _UTMIP_BIAS_MASTER_CNTRL_0, 0x270 */
uint32_t utmip_master_config; /* _UTMIP_MASTER_CONFIG_0, 0x274 */
uint32_t td_pwrgate_inter_part_timer; /* _TD_PWRGATE_INTER_PART_TIMER_0, 0x278 */
uint32_t utmip_uhsic2_triggers; /* _UTMIP_UHSIC2_TRIGGERS_0, 0x27c */
uint32_t utmip_uhsic2_saved_state; /* _UTMIP_UHSIC2_SAVED_STATE_0, 0x280 */
uint32_t utmip_uhsic2_sleep_cfg; /* _UTMIP_UHSIC2_SLEEP_CFG_0, 0x284 */
uint32_t utmip_uhsic2_sleepwalk_cfg; /* _UTMIP_UHSIC2_SLEEPWALK_CFG_0, 0x288 */
uint32_t uhsic2_sleepwalk_p1; /* _UHSIC2_SLEEPWALK_P1_0, 0x28c */
uint32_t utmip_uhsic2_status; /* _UTMIP_UHSIC2_STATUS_0, 0x290 */
uint32_t utmip_uhsic2_fake; /* _UTMIP_UHSIC2_FAKE_0, 0x294 */
uint32_t utmip_uhsic2_line_wakeup; /* _UTMIP_UHSIC2_LINE_WAKEUP_0, 0x298 */
uint32_t utmip_master2_config; /* _UTMIP_MASTER2_CONFIG_0, 0x29c */
uint32_t utmip_uhsic_rpd_cfg; /* _UTMIP_UHSIC_RPD_CFG_0, 0x2a0 */
uint32_t pg_mask_ce0; /* _PG_MASK_CE0_0, 0x2a4 */
uint32_t pg_mask_3; /* _PG_MASK_3_0, 0x2a8 */
uint32_t pg_mask_4; /* _PG_MASK_4_0, 0x2ac */
uint32_t pllm_wb0_override2; /* _PLLM_WB0_OVERRIDE2_0, 0x2b0 */
uint32_t tsc_mult; /* _TSC_MULT_0, 0x2b4 */
uint32_t cpu_vsense_override; /* _CPU_VSENSE_OVERRIDE_0, 0x2b8 */
uint32_t glb_amap_cfg; /* _GLB_AMAP_CFG_0, 0x2bc */
uint32_t sticky_bits; /* _STICKY_BITS_0, 0x2c0 */
uint32_t sec_disable2; /* _SEC_DISABLE2_0, 0x2c4 */
uint32_t weak_bias; /* _WEAK_BIAS_0, 0x2c8 */
uint32_t reg_short; /* _REG_SHORT_0, 0x2cc */
uint32_t pg_mask_andor; /* _PG_MASK_ANDOR_0, 0x2d0 */
uint32_t gpu_rg_cntrl; /* _GPU_RG_CNTRL_0, 0x2d4 */
uint32_t sec_disable3; /* _SEC_DISABLE3_0, 0x2d8 */
uint32_t pg_mask_5; /* _PG_MASK_5_0, 0x2dc */
uint32_t pg_mask_6; /* _PG_MASK_6_0, 0x2e0 */
uint32_t _0x2e4[7];
uint32_t secure_scratch8; /* _SECURE_SCRATCH8_0, 0x300 */
uint32_t secure_scratch9; /* _SECURE_SCRATCH9_0, 0x304 */
uint32_t secure_scratch10; /* _SECURE_SCRATCH10_0, 0x308 */
uint32_t secure_scratch11; /* _SECURE_SCRATCH11_0, 0x30c */
uint32_t secure_scratch12; /* _SECURE_SCRATCH12_0, 0x310 */
uint32_t secure_scratch13; /* _SECURE_SCRATCH13_0, 0x314 */
uint32_t secure_scratch14; /* _SECURE_SCRATCH14_0, 0x318 */
uint32_t secure_scratch15; /* _SECURE_SCRATCH15_0, 0x31c */
uint32_t secure_scratch16; /* _SECURE_SCRATCH16_0, 0x320 */
uint32_t secure_scratch17; /* _SECURE_SCRATCH17_0, 0x324 */
uint32_t secure_scratch18; /* _SECURE_SCRATCH18_0, 0x328 */
uint32_t secure_scratch19; /* _SECURE_SCRATCH19_0, 0x32c */
uint32_t secure_scratch20; /* _SECURE_SCRATCH20_0, 0x330 */
uint32_t secure_scratch21; /* _SECURE_SCRATCH21_0, 0x334 */
uint32_t secure_scratch22; /* _SECURE_SCRATCH22_0, 0x338 */
uint32_t secure_scratch23; /* _SECURE_SCRATCH23_0, 0x33c */
uint32_t secure_scratch24; /* _SECURE_SCRATCH24_0, 0x340 */
uint32_t secure_scratch25; /* _SECURE_SCRATCH25_0, 0x344 */
uint32_t secure_scratch26; /* _SECURE_SCRATCH26_0, 0x348 */
uint32_t secure_scratch27; /* _SECURE_SCRATCH27_0, 0x34c */
uint32_t secure_scratch28; /* _SECURE_SCRATCH28_0, 0x350 */
uint32_t secure_scratch29; /* _SECURE_SCRATCH29_0, 0x354 */
uint32_t secure_scratch30; /* _SECURE_SCRATCH30_0, 0x358 */
uint32_t secure_scratch31; /* _SECURE_SCRATCH31_0, 0x35c */
uint32_t secure_scratch32; /* _SECURE_SCRATCH32_0, 0x360 */
uint32_t secure_scratch33; /* _SECURE_SCRATCH33_0, 0x364 */
uint32_t secure_scratch34; /* _SECURE_SCRATCH34_0, 0x368 */
uint32_t secure_scratch35; /* _SECURE_SCRATCH35_0, 0x36c */
uint32_t secure_scratch36; /* _SECURE_SCRATCH36_0, 0x370 */
uint32_t secure_scratch37; /* _SECURE_SCRATCH37_0, 0x374 */
uint32_t secure_scratch38; /* _SECURE_SCRATCH38_0, 0x378 */
uint32_t secure_scratch39; /* _SECURE_SCRATCH39_0, 0x37c */
uint32_t secure_scratch40; /* _SECURE_SCRATCH40_0, 0x380 */
uint32_t secure_scratch41; /* _SECURE_SCRATCH41_0, 0x384 */
uint32_t secure_scratch42; /* _SECURE_SCRATCH42_0, 0x388 */
uint32_t secure_scratch43; /* _SECURE_SCRATCH43_0, 0x38c */
uint32_t secure_scratch44; /* _SECURE_SCRATCH44_0, 0x390 */
uint32_t secure_scratch45; /* _SECURE_SCRATCH45_0, 0x394 */
uint32_t secure_scratch46; /* _SECURE_SCRATCH46_0, 0x398 */
uint32_t secure_scratch47; /* _SECURE_SCRATCH47_0, 0x39c */
uint32_t secure_scratch48; /* _SECURE_SCRATCH48_0, 0x3a0 */
uint32_t secure_scratch49; /* _SECURE_SCRATCH49_0, 0x3a4 */
uint32_t secure_scratch50; /* _SECURE_SCRATCH50_0, 0x3a8 */
uint32_t secure_scratch51; /* _SECURE_SCRATCH51_0, 0x3ac */
uint32_t secure_scratch52; /* _SECURE_SCRATCH52_0, 0x3b0 */
uint32_t secure_scratch53; /* _SECURE_SCRATCH53_0, 0x3b4 */
uint32_t secure_scratch54; /* _SECURE_SCRATCH54_0, 0x3b8 */
uint32_t secure_scratch55; /* _SECURE_SCRATCH55_0, 0x3bc */
uint32_t secure_scratch56; /* _SECURE_SCRATCH56_0, 0x3c0 */
uint32_t secure_scratch57; /* _SECURE_SCRATCH57_0, 0x3c4 */
uint32_t secure_scratch58; /* _SECURE_SCRATCH58_0, 0x3c8 */
uint32_t secure_scratch59; /* _SECURE_SCRATCH59_0, 0x3cc */
uint32_t secure_scratch60; /* _SECURE_SCRATCH60_0, 0x3d0 */
uint32_t secure_scratch61; /* _SECURE_SCRATCH61_0, 0x3d4 */
uint32_t secure_scratch62; /* _SECURE_SCRATCH62_0, 0x3d8 */
uint32_t secure_scratch63; /* _SECURE_SCRATCH63_0, 0x3dc */
uint32_t secure_scratch64; /* _SECURE_SCRATCH64_0, 0x3e0 */
uint32_t secure_scratch65; /* _SECURE_SCRATCH65_0, 0x3e4 */
uint32_t secure_scratch66; /* _SECURE_SCRATCH66_0, 0x3e8 */
uint32_t secure_scratch67; /* _SECURE_SCRATCH67_0, 0x3ec */
uint32_t secure_scratch68; /* _SECURE_SCRATCH68_0, 0x3f0 */
uint32_t secure_scratch69; /* _SECURE_SCRATCH69_0, 0x3f4 */
uint32_t secure_scratch70; /* _SECURE_SCRATCH70_0, 0x3f8 */
uint32_t secure_scratch71; /* _SECURE_SCRATCH71_0, 0x3fc */
uint32_t secure_scratch72; /* _SECURE_SCRATCH72_0, 0x400 */
uint32_t secure_scratch73; /* _SECURE_SCRATCH73_0, 0x404 */
uint32_t secure_scratch74; /* _SECURE_SCRATCH74_0, 0x408 */
uint32_t secure_scratch75; /* _SECURE_SCRATCH75_0, 0x40c */
uint32_t secure_scratch76; /* _SECURE_SCRATCH76_0, 0x410 */
uint32_t secure_scratch77; /* _SECURE_SCRATCH77_0, 0x414 */
uint32_t secure_scratch78; /* _SECURE_SCRATCH78_0, 0x418 */
uint32_t secure_scratch79; /* _SECURE_SCRATCH79_0, 0x41c */
uint32_t _0x420[8];
uint32_t cntrl2; /* _CNTRL2_0, 0x440 */
uint32_t io_dpd_off_mask; /* _IO_DPD_OFF_MASK_0, 0x444 */
uint32_t io_dpd2_off_mask; /* _IO_DPD2_OFF_MASK_0, 0x448 */
uint32_t event_counter; /* _EVENT_COUNTER_0, 0x44c */
uint32_t fuse_control; /* _FUSE_CONTROL_0, 0x450 */
uint32_t scratch1_eco; /* _SCRATCH1_ECO_0, 0x454 */
uint32_t _0x458;
uint32_t io_dpd3_req; /* _IO_DPD3_REQ_0, 0x45c */
uint32_t io_dpd3_status; /* _IO_DPD3_STATUS_0, 0x460 */
uint32_t io_dpd4_req; /* _IO_DPD4_REQ_0, 0x464 */
uint32_t io_dpd4_status; /* _IO_DPD4_STATUS_0, 0x468 */
uint32_t _0x46c[2];
uint32_t direct_thermtrip_cfg; /* _DIRECT_THERMTRIP_CFG_0, 0x474 */
uint32_t tsosc_delay; /* _TSOSC_DELAY_0, 0x478 */
uint32_t set_sw_clamp; /* _SET_SW_CLAMP_0, 0x47c */
uint32_t debug_authentication; /* _DEBUG_AUTHENTICATION_0, 0x480 */
uint32_t aotag_cfg; /* _AOTAG_CFG_0, 0x484 */
uint32_t aotag_thresh1_cfg; /* _AOTAG_THRESH1_CFG_0, 0x488 */
uint32_t aotag_thresh2_cfg; /* _AOTAG_THRESH2_CFG_0, 0x48c */
uint32_t aotag_thresh3_cfg; /* _AOTAG_THRESH3_CFG_0, 0x490 */
uint32_t aotag_status; /* _AOTAG_STATUS_0, 0x494 */
uint32_t aotag_security; /* _AOTAG_SECURITY_0, 0x498 */
uint32_t tsensor_config0; /* _TSENSOR_CONFIG0_0, 0x49c */
uint32_t tsensor_config1; /* _TSENSOR_CONFIG1_0, 0x4a0 */
uint32_t tsensor_config2; /* _TSENSOR_CONFIG2_0, 0x4a4 */
uint32_t tsensor_status0; /* _TSENSOR_STATUS0_0, 0x4a8 */
uint32_t tsensor_status1; /* _TSENSOR_STATUS1_0, 0x4ac */
uint32_t tsensor_status2; /* _TSENSOR_STATUS2_0, 0x4b0 */
uint32_t tsensor_pdiv; /* _TSENSOR_PDIV_0, 0x4b4 */
uint32_t aotag_intr_en; /* _AOTAG_INTR_EN_0, 0x4b8 */
uint32_t aotag_intr_dis; /* _AOTAG_INTR_DIS_0, 0x4bc */
uint32_t utmip_pad_cfg0; /* _UTMIP_PAD_CFG0_0, 0x4c0 */
uint32_t utmip_pad_cfg1; /* _UTMIP_PAD_CFG1_0, 0x4c4 */
uint32_t utmip_pad_cfg2; /* _UTMIP_PAD_CFG2_0, 0x4c8 */
uint32_t utmip_pad_cfg3; /* _UTMIP_PAD_CFG3_0, 0x4cc */
uint32_t utmip_uhsic_sleep_cfg1; /* _UTMIP_UHSIC_SLEEP_CFG1_0, 0x4d0 */
uint32_t cc4_hvc_control; /* _CC4_HVC_CONTROL_0, 0x4d4 */
uint32_t wake_debounce_en; /* _WAKE_DEBOUNCE_EN_0, 0x4d8 */
uint32_t ramdump_ctl_status; /* _RAMDUMP_CTL_STATUS_0, 0x4dc */
uint32_t utmip_sleepwalk_p3; /* _UTMIP_SLEEPWALK_P3_0, 0x4e0 */
uint32_t ddr_cntrl; /* _DDR_CNTRL_0, 0x4e4 */
uint32_t _0x4e8[50];
uint32_t sec_disable4; /* _SEC_DISABLE4_0, 0x5b0 */
uint32_t sec_disable5; /* _SEC_DISABLE5_0, 0x5b4 */
uint32_t sec_disable6; /* _SEC_DISABLE6_0, 0x5b8 */
uint32_t sec_disable7; /* _SEC_DISABLE7_0, 0x5bc */
uint32_t sec_disable8; /* _SEC_DISABLE8_0, 0x5c0 */
uint32_t sec_disable9; /* _SEC_DISABLE9_0, 0x5c4 */
uint32_t sec_disable10; /* _SEC_DISABLE10_0, 0x5c8 */
uint32_t _0x5cc[13];
uint32_t scratch56; /* _SCRATCH56_0, 0x600 */
uint32_t scratch57; /* _SCRATCH57_0, 0x604 */
uint32_t scratch58; /* _SCRATCH58_0, 0x608 */
uint32_t scratch59; /* _SCRATCH59_0, 0x60c */
uint32_t scratch60; /* _SCRATCH60_0, 0x610 */
uint32_t scratch61; /* _SCRATCH61_0, 0x614 */
uint32_t scratch62; /* _SCRATCH62_0, 0x618 */
uint32_t scratch63; /* _SCRATCH63_0, 0x61c */
uint32_t scratch64; /* _SCRATCH64_0, 0x620 */
uint32_t scratch65; /* _SCRATCH65_0, 0x624 */
uint32_t scratch66; /* _SCRATCH66_0, 0x628 */
uint32_t scratch67; /* _SCRATCH67_0, 0x62c */
uint32_t scratch68; /* _SCRATCH68_0, 0x630 */
uint32_t scratch69; /* _SCRATCH69_0, 0x634 */
uint32_t scratch70; /* _SCRATCH70_0, 0x638 */
uint32_t scratch71; /* _SCRATCH71_0, 0x63c */
uint32_t scratch72; /* _SCRATCH72_0, 0x640 */
uint32_t scratch73; /* _SCRATCH73_0, 0x644 */
uint32_t scratch74; /* _SCRATCH74_0, 0x648 */
uint32_t scratch75; /* _SCRATCH75_0, 0x64c */
uint32_t scratch76; /* _SCRATCH76_0, 0x650 */
uint32_t scratch77; /* _SCRATCH77_0, 0x654 */
uint32_t scratch78; /* _SCRATCH78_0, 0x658 */
uint32_t scratch79; /* _SCRATCH79_0, 0x65c */
uint32_t scratch80; /* _SCRATCH80_0, 0x660 */
uint32_t scratch81; /* _SCRATCH81_0, 0x664 */
uint32_t scratch82; /* _SCRATCH82_0, 0x668 */
uint32_t scratch83; /* _SCRATCH83_0, 0x66c */
uint32_t scratch84; /* _SCRATCH84_0, 0x670 */
uint32_t scratch85; /* _SCRATCH85_0, 0x674 */
uint32_t scratch86; /* _SCRATCH86_0, 0x678 */
uint32_t scratch87; /* _SCRATCH87_0, 0x67c */
uint32_t scratch88; /* _SCRATCH88_0, 0x680 */
uint32_t scratch89; /* _SCRATCH89_0, 0x684 */
uint32_t scratch90; /* _SCRATCH90_0, 0x688 */
uint32_t scratch91; /* _SCRATCH91_0, 0x68c */
uint32_t scratch92; /* _SCRATCH92_0, 0x690 */
uint32_t scratch93; /* _SCRATCH93_0, 0x694 */
uint32_t scratch94; /* _SCRATCH94_0, 0x698 */
uint32_t scratch95; /* _SCRATCH95_0, 0x69c */
uint32_t scratch96; /* _SCRATCH96_0, 0x6a0 */
uint32_t scratch97; /* _SCRATCH97_0, 0x6a4 */
uint32_t scratch98; /* _SCRATCH98_0, 0x6a8 */
uint32_t scratch99; /* _SCRATCH99_0, 0x6ac */
uint32_t scratch100; /* _SCRATCH100_0, 0x6b0 */
uint32_t scratch101; /* _SCRATCH101_0, 0x6b4 */
uint32_t scratch102; /* _SCRATCH102_0, 0x6b8 */
uint32_t scratch103; /* _SCRATCH103_0, 0x6bc */
uint32_t scratch104; /* _SCRATCH104_0, 0x6c0 */
uint32_t scratch105; /* _SCRATCH105_0, 0x6c4 */
uint32_t scratch106; /* _SCRATCH106_0, 0x6c8 */
uint32_t scratch107; /* _SCRATCH107_0, 0x6cc */
uint32_t scratch108; /* _SCRATCH108_0, 0x6d0 */
uint32_t scratch109; /* _SCRATCH109_0, 0x6d4 */
uint32_t scratch110; /* _SCRATCH110_0, 0x6d8 */
uint32_t scratch111; /* _SCRATCH111_0, 0x6dc */
uint32_t scratch112; /* _SCRATCH112_0, 0x6e0 */
uint32_t scratch113; /* _SCRATCH113_0, 0x6e4 */
uint32_t scratch114; /* _SCRATCH114_0, 0x6e8 */
uint32_t scratch115; /* _SCRATCH115_0, 0x6ec */
uint32_t scratch116; /* _SCRATCH116_0, 0x6f0 */
uint32_t scratch117; /* _SCRATCH117_0, 0x6f4 */
uint32_t scratch118; /* _SCRATCH118_0, 0x6f8 */
uint32_t scratch119; /* _SCRATCH119_0, 0x6fc */
uint32_t scratch120; /* _SCRATCH120_0, 0x700 */
uint32_t scratch121; /* _SCRATCH121_0, 0x704 */
uint32_t scratch122; /* _SCRATCH122_0, 0x708 */
uint32_t scratch123; /* _SCRATCH123_0, 0x70c */
uint32_t scratch124; /* _SCRATCH124_0, 0x710 */
uint32_t scratch125; /* _SCRATCH125_0, 0x714 */
uint32_t scratch126; /* _SCRATCH126_0, 0x718 */
uint32_t scratch127; /* _SCRATCH127_0, 0x71c */
uint32_t scratch128; /* _SCRATCH128_0, 0x720 */
uint32_t scratch129; /* _SCRATCH129_0, 0x724 */
uint32_t scratch130; /* _SCRATCH130_0, 0x728 */
uint32_t scratch131; /* _SCRATCH131_0, 0x72c */
uint32_t scratch132; /* _SCRATCH132_0, 0x730 */
uint32_t scratch133; /* _SCRATCH133_0, 0x734 */
uint32_t scratch134; /* _SCRATCH134_0, 0x738 */
uint32_t scratch135; /* _SCRATCH135_0, 0x73c */
uint32_t scratch136; /* _SCRATCH136_0, 0x740 */
uint32_t scratch137; /* _SCRATCH137_0, 0x744 */
uint32_t scratch138; /* _SCRATCH138_0, 0x748 */
uint32_t scratch139; /* _SCRATCH139_0, 0x74c */
uint32_t scratch140; /* _SCRATCH140_0, 0x750 */
uint32_t scratch141; /* _SCRATCH141_0, 0x754 */
uint32_t scratch142; /* _SCRATCH142_0, 0x758 */
uint32_t scratch143; /* _SCRATCH143_0, 0x75c */
uint32_t scratch144; /* _SCRATCH144_0, 0x760 */
uint32_t scratch145; /* _SCRATCH145_0, 0x764 */
uint32_t scratch146; /* _SCRATCH146_0, 0x768 */
uint32_t scratch147; /* _SCRATCH147_0, 0x76c */
uint32_t scratch148; /* _SCRATCH148_0, 0x770 */
uint32_t scratch149; /* _SCRATCH149_0, 0x774 */
uint32_t scratch150; /* _SCRATCH150_0, 0x778 */
uint32_t scratch151; /* _SCRATCH151_0, 0x77c */
uint32_t scratch152; /* _SCRATCH152_0, 0x780 */
uint32_t scratch153; /* _SCRATCH153_0, 0x784 */
uint32_t scratch154; /* _SCRATCH154_0, 0x788 */
uint32_t scratch155; /* _SCRATCH155_0, 0x78c */
uint32_t scratch156; /* _SCRATCH156_0, 0x790 */
uint32_t scratch157; /* _SCRATCH157_0, 0x794 */
uint32_t scratch158; /* _SCRATCH158_0, 0x798 */
uint32_t scratch159; /* _SCRATCH159_0, 0x79c */
uint32_t scratch160; /* _SCRATCH160_0, 0x7a0 */
uint32_t scratch161; /* _SCRATCH161_0, 0x7a4 */
uint32_t scratch162; /* _SCRATCH162_0, 0x7a8 */
uint32_t scratch163; /* _SCRATCH163_0, 0x7ac */
uint32_t scratch164; /* _SCRATCH164_0, 0x7b0 */
uint32_t scratch165; /* _SCRATCH165_0, 0x7b4 */
uint32_t scratch166; /* _SCRATCH166_0, 0x7b8 */
uint32_t scratch167; /* _SCRATCH167_0, 0x7bc */
uint32_t scratch168; /* _SCRATCH168_0, 0x7c0 */
uint32_t scratch169; /* _SCRATCH169_0, 0x7c4 */
uint32_t scratch170; /* _SCRATCH170_0, 0x7c8 */
uint32_t scratch171; /* _SCRATCH171_0, 0x7cc */
uint32_t scratch172; /* _SCRATCH172_0, 0x7d0 */
uint32_t scratch173; /* _SCRATCH173_0, 0x7d4 */
uint32_t scratch174; /* _SCRATCH174_0, 0x7d8 */
uint32_t scratch175; /* _SCRATCH175_0, 0x7dc */
uint32_t scratch176; /* _SCRATCH176_0, 0x7e0 */
uint32_t scratch177; /* _SCRATCH177_0, 0x7e4 */
uint32_t scratch178; /* _SCRATCH178_0, 0x7e8 */
uint32_t scratch179; /* _SCRATCH179_0, 0x7ec */
uint32_t scratch180; /* _SCRATCH180_0, 0x7f0 */
uint32_t scratch181; /* _SCRATCH181_0, 0x7f4 */
uint32_t scratch182; /* _SCRATCH182_0, 0x7f8 */
uint32_t scratch183; /* _SCRATCH183_0, 0x7fc */
uint32_t scratch184; /* _SCRATCH184_0, 0x800 */
uint32_t scratch185; /* _SCRATCH185_0, 0x804 */
uint32_t scratch186; /* _SCRATCH186_0, 0x808 */
uint32_t scratch187; /* _SCRATCH187_0, 0x80c */
uint32_t scratch188; /* _SCRATCH188_0, 0x810 */
uint32_t scratch189; /* _SCRATCH189_0, 0x814 */
uint32_t scratch190; /* _SCRATCH190_0, 0x818 */
uint32_t scratch191; /* _SCRATCH191_0, 0x81c */
uint32_t scratch192; /* _SCRATCH192_0, 0x820 */
uint32_t scratch193; /* _SCRATCH193_0, 0x824 */
uint32_t scratch194; /* _SCRATCH194_0, 0x828 */
uint32_t scratch195; /* _SCRATCH195_0, 0x82c */
uint32_t scratch196; /* _SCRATCH196_0, 0x830 */
uint32_t scratch197; /* _SCRATCH197_0, 0x834 */
uint32_t scratch198; /* _SCRATCH198_0, 0x838 */
uint32_t scratch199; /* _SCRATCH199_0, 0x83c */
uint32_t scratch200; /* _SCRATCH200_0, 0x840 */
uint32_t scratch201; /* _SCRATCH201_0, 0x844 */
uint32_t scratch202; /* _SCRATCH202_0, 0x848 */
uint32_t scratch203; /* _SCRATCH203_0, 0x84c */
uint32_t scratch204; /* _SCRATCH204_0, 0x850 */
uint32_t scratch205; /* _SCRATCH205_0, 0x854 */
uint32_t scratch206; /* _SCRATCH206_0, 0x858 */
uint32_t scratch207; /* _SCRATCH207_0, 0x85c */
uint32_t scratch208; /* _SCRATCH208_0, 0x860 */
uint32_t scratch209; /* _SCRATCH209_0, 0x864 */
uint32_t scratch210; /* _SCRATCH210_0, 0x868 */
uint32_t scratch211; /* _SCRATCH211_0, 0x86c */
uint32_t scratch212; /* _SCRATCH212_0, 0x870 */
uint32_t scratch213; /* _SCRATCH213_0, 0x874 */
uint32_t scratch214; /* _SCRATCH214_0, 0x878 */
uint32_t scratch215; /* _SCRATCH215_0, 0x87c */
uint32_t scratch216; /* _SCRATCH216_0, 0x880 */
uint32_t scratch217; /* _SCRATCH217_0, 0x884 */
uint32_t scratch218; /* _SCRATCH218_0, 0x888 */
uint32_t scratch219; /* _SCRATCH219_0, 0x88c */
uint32_t scratch220; /* _SCRATCH220_0, 0x890 */
uint32_t scratch221; /* _SCRATCH221_0, 0x894 */
uint32_t scratch222; /* _SCRATCH222_0, 0x898 */
uint32_t scratch223; /* _SCRATCH223_0, 0x89c */
uint32_t scratch224; /* _SCRATCH224_0, 0x8a0 */
uint32_t scratch225; /* _SCRATCH225_0, 0x8a4 */
uint32_t scratch226; /* _SCRATCH226_0, 0x8a8 */
uint32_t scratch227; /* _SCRATCH227_0, 0x8ac */
uint32_t scratch228; /* _SCRATCH228_0, 0x8b0 */
uint32_t scratch229; /* _SCRATCH229_0, 0x8b4 */
uint32_t scratch230; /* _SCRATCH230_0, 0x8b8 */
uint32_t scratch231; /* _SCRATCH231_0, 0x8bc */
uint32_t scratch232; /* _SCRATCH232_0, 0x8c0 */
uint32_t scratch233; /* _SCRATCH233_0, 0x8c4 */
uint32_t scratch234; /* _SCRATCH234_0, 0x8c8 */
uint32_t scratch235; /* _SCRATCH235_0, 0x8cc */
uint32_t scratch236; /* _SCRATCH236_0, 0x8d0 */
uint32_t scratch237; /* _SCRATCH237_0, 0x8d4 */
uint32_t scratch238; /* _SCRATCH238_0, 0x8d8 */
uint32_t scratch239; /* _SCRATCH239_0, 0x8dc */
uint32_t scratch240; /* _SCRATCH240_0, 0x8e0 */
uint32_t scratch241; /* _SCRATCH241_0, 0x8e4 */
uint32_t scratch242; /* _SCRATCH242_0, 0x8e8 */
uint32_t scratch243; /* _SCRATCH243_0, 0x8ec */
uint32_t scratch244; /* _SCRATCH244_0, 0x8f0 */
uint32_t scratch245; /* _SCRATCH245_0, 0x8f4 */
uint32_t scratch246; /* _SCRATCH246_0, 0x8f8 */
uint32_t scratch247; /* _SCRATCH247_0, 0x8fc */
uint32_t scratch248; /* _SCRATCH248_0, 0x900 */
uint32_t scratch249; /* _SCRATCH249_0, 0x904 */
uint32_t scratch250; /* _SCRATCH250_0, 0x908 */
uint32_t scratch251; /* _SCRATCH251_0, 0x90c */
uint32_t scratch252; /* _SCRATCH252_0, 0x910 */
uint32_t scratch253; /* _SCRATCH253_0, 0x914 */
uint32_t scratch254; /* _SCRATCH254_0, 0x918 */
uint32_t scratch255; /* _SCRATCH255_0, 0x91c */
uint32_t scratch256; /* _SCRATCH256_0, 0x920 */
uint32_t scratch257; /* _SCRATCH257_0, 0x924 */
uint32_t scratch258; /* _SCRATCH258_0, 0x928 */
uint32_t scratch259; /* _SCRATCH259_0, 0x92c */
uint32_t scratch260; /* _SCRATCH260_0, 0x930 */
uint32_t scratch261; /* _SCRATCH261_0, 0x934 */
uint32_t scratch262; /* _SCRATCH262_0, 0x938 */
uint32_t scratch263; /* _SCRATCH263_0, 0x93c */
uint32_t scratch264; /* _SCRATCH264_0, 0x940 */
uint32_t scratch265; /* _SCRATCH265_0, 0x944 */
uint32_t scratch266; /* _SCRATCH266_0, 0x948 */
uint32_t scratch267; /* _SCRATCH267_0, 0x94c */
uint32_t scratch268; /* _SCRATCH268_0, 0x950 */
uint32_t scratch269; /* _SCRATCH269_0, 0x954 */
uint32_t scratch270; /* _SCRATCH270_0, 0x958 */
uint32_t scratch271; /* _SCRATCH271_0, 0x95c */
uint32_t scratch272; /* _SCRATCH272_0, 0x960 */
uint32_t scratch273; /* _SCRATCH273_0, 0x964 */
uint32_t scratch274; /* _SCRATCH274_0, 0x968 */
uint32_t scratch275; /* _SCRATCH275_0, 0x96c */
uint32_t scratch276; /* _SCRATCH276_0, 0x970 */
uint32_t scratch277; /* _SCRATCH277_0, 0x974 */
uint32_t scratch278; /* _SCRATCH278_0, 0x978 */
uint32_t scratch279; /* _SCRATCH279_0, 0x97c */
uint32_t scratch280; /* _SCRATCH280_0, 0x980 */
uint32_t scratch281; /* _SCRATCH281_0, 0x984 */
uint32_t scratch282; /* _SCRATCH282_0, 0x988 */
uint32_t scratch283; /* _SCRATCH283_0, 0x98c */
uint32_t scratch284; /* _SCRATCH284_0, 0x990 */
uint32_t scratch285; /* _SCRATCH285_0, 0x994 */
uint32_t scratch286; /* _SCRATCH286_0, 0x998 */
uint32_t scratch287; /* _SCRATCH287_0, 0x99c */
uint32_t scratch288; /* _SCRATCH288_0, 0x9a0 */
uint32_t scratch289; /* _SCRATCH289_0, 0x9a4 */
uint32_t scratch290; /* _SCRATCH290_0, 0x9a8 */
uint32_t scratch291; /* _SCRATCH291_0, 0x9ac */
uint32_t scratch292; /* _SCRATCH292_0, 0x9b0 */
uint32_t scratch293; /* _SCRATCH293_0, 0x9b4 */
uint32_t scratch294; /* _SCRATCH294_0, 0x9b8 */
uint32_t scratch295; /* _SCRATCH295_0, 0x9bc */
uint32_t scratch296; /* _SCRATCH296_0, 0x9c0 */
uint32_t scratch297; /* _SCRATCH297_0, 0x9c4 */
uint32_t scratch298; /* _SCRATCH298_0, 0x9c8 */
uint32_t scratch299; /* _SCRATCH299_0, 0x9cc */
uint32_t _0x9d0[50];
uint32_t secure_scratch80; /* _SECURE_SCRATCH80_0, 0xa98 */
uint32_t secure_scratch81; /* _SECURE_SCRATCH81_0, 0xa9c */
uint32_t secure_scratch82; /* _SECURE_SCRATCH82_0, 0xaa0 */
uint32_t secure_scratch83; /* _SECURE_SCRATCH83_0, 0xaa4 */
uint32_t secure_scratch84; /* _SECURE_SCRATCH84_0, 0xaa8 */
uint32_t secure_scratch85; /* _SECURE_SCRATCH85_0, 0xaac */
uint32_t secure_scratch86; /* _SECURE_SCRATCH86_0, 0xab0 */
uint32_t secure_scratch87; /* _SECURE_SCRATCH87_0, 0xab4 */
uint32_t secure_scratch88; /* _SECURE_SCRATCH88_0, 0xab8 */
uint32_t secure_scratch89; /* _SECURE_SCRATCH89_0, 0xabc */
uint32_t secure_scratch90; /* _SECURE_SCRATCH90_0, 0xac0 */
uint32_t secure_scratch91; /* _SECURE_SCRATCH91_0, 0xac4 */
uint32_t secure_scratch92; /* _SECURE_SCRATCH92_0, 0xac8 */
uint32_t secure_scratch93; /* _SECURE_SCRATCH93_0, 0xacc */
uint32_t secure_scratch94; /* _SECURE_SCRATCH94_0, 0xad0 */
uint32_t secure_scratch95; /* _SECURE_SCRATCH95_0, 0xad4 */
uint32_t secure_scratch96; /* _SECURE_SCRATCH96_0, 0xad8 */
uint32_t secure_scratch97; /* _SECURE_SCRATCH97_0, 0xadc */
uint32_t secure_scratch98; /* _SECURE_SCRATCH98_0, 0xae0 */
uint32_t secure_scratch99; /* _SECURE_SCRATCH99_0, 0xae4 */
uint32_t secure_scratch100; /* _SECURE_SCRATCH100_0, 0xae8 */
uint32_t secure_scratch101; /* _SECURE_SCRATCH101_0, 0xaec */
uint32_t secure_scratch102; /* _SECURE_SCRATCH102_0, 0xaf0 */
uint32_t secure_scratch103; /* _SECURE_SCRATCH103_0, 0xaf4 */
uint32_t secure_scratch104; /* _SECURE_SCRATCH104_0, 0xaf8 */
uint32_t secure_scratch105; /* _SECURE_SCRATCH105_0, 0xafc */
uint32_t secure_scratch106; /* _SECURE_SCRATCH106_0, 0xb00 */
uint32_t secure_scratch107; /* _SECURE_SCRATCH107_0, 0xb04 */
uint32_t secure_scratch108; /* _SECURE_SCRATCH108_0, 0xb08 */
uint32_t secure_scratch109; /* _SECURE_SCRATCH109_0, 0xb0c */
uint32_t secure_scratch110; /* _SECURE_SCRATCH110_0, 0xb10 */
uint32_t secure_scratch111; /* _SECURE_SCRATCH111_0, 0xb14 */
uint32_t secure_scratch112; /* _SECURE_SCRATCH112_0, 0xb18 */
uint32_t secure_scratch113; /* _SECURE_SCRATCH113_0, 0xb1c */
uint32_t secure_scratch114; /* _SECURE_SCRATCH114_0, 0xb20 */
uint32_t secure_scratch115; /* _SECURE_SCRATCH115_0, 0xb24 */
uint32_t secure_scratch116; /* _SECURE_SCRATCH116_0, 0xb28 */
uint32_t secure_scratch117; /* _SECURE_SCRATCH117_0, 0xb2c */
uint32_t secure_scratch118; /* _SECURE_SCRATCH118_0, 0xb30 */
uint32_t secure_scratch119; /* _SECURE_SCRATCH119_0, 0xb34 */
uint32_t secure_scratch120; /* _SECURE_SCRATCH120_0, 0xb38 */
uint32_t secure_scratch121; /* _SECURE_SCRATCH121_0, 0xb3c */
uint32_t secure_scratch122; /* _SECURE_SCRATCH122_0, 0xb40 */
uint32_t secure_scratch123; /* _SECURE_SCRATCH123_0, 0xb44 */
uint32_t led_breathing_ctrl; /* _LED_BREATHING_CTRL_0, 0xb48 */
uint32_t led_breathing_counter0; /* _LED_BREATHING_COUNTER0_0, 0xb4c */
uint32_t led_breathing_counter1; /* _LED_BREATHING_COUNTER1_0, 0xb50 */
uint32_t led_breathing_counter2; /* _LED_BREATHING_COUNTER2_0, 0xb54 */
uint32_t led_breathing_counter3; /* _LED_BREATHING_COUNTER3_0, 0xb58 */
uint32_t led_breathing_status; /* _LED_BREATHING_STATUS_0, 0xb5c */
uint32_t _0xb60[2];
uint32_t secure_scratch124; /* _SECURE_SCRATCH124_0, 0xb68 */
uint32_t secure_scratch125; /* _SECURE_SCRATCH125_0, 0xb6c */
uint32_t secure_scratch126; /* _SECURE_SCRATCH126_0, 0xb70 */
uint32_t secure_scratch127; /* _SECURE_SCRATCH127_0, 0xb74 */
uint32_t secure_scratch128; /* _SECURE_SCRATCH128_0, 0xb78 */
uint32_t secure_scratch129; /* _SECURE_SCRATCH129_0, 0xb7c */
uint32_t secure_scratch130; /* _SECURE_SCRATCH130_0, 0xb80 */
uint32_t secure_scratch131; /* _SECURE_SCRATCH131_0, 0xb84 */
uint32_t secure_scratch132; /* _SECURE_SCRATCH132_0, 0xb88 */
uint32_t secure_scratch133; /* _SECURE_SCRATCH133_0, 0xb8c */
uint32_t secure_scratch134; /* _SECURE_SCRATCH134_0, 0xb90 */
uint32_t secure_scratch135; /* _SECURE_SCRATCH135_0, 0xb94 */
uint32_t secure_scratch136; /* _SECURE_SCRATCH136_0, 0xb98 */
uint32_t secure_scratch137; /* _SECURE_SCRATCH137_0, 0xb9c */
uint32_t secure_scratch138; /* _SECURE_SCRATCH138_0, 0xba0 */
uint32_t secure_scratch139; /* _SECURE_SCRATCH139_0, 0xba4 */
uint32_t _0xba8[2];
uint32_t sec_disable_ns; /* _SEC_DISABLE_NS_0, 0xbb0 */
uint32_t sec_disable2_ns; /* _SEC_DISABLE2_NS_0, 0xbb4 */
uint32_t sec_disable3_ns; /* _SEC_DISABLE3_NS_0, 0xbb8 */
uint32_t sec_disable4_ns; /* _SEC_DISABLE4_NS_0, 0xbbc */
uint32_t sec_disable5_ns; /* _SEC_DISABLE5_NS_0, 0xbc0 */
uint32_t sec_disable6_ns; /* _SEC_DISABLE6_NS_0, 0xbc4 */
uint32_t sec_disable7_ns; /* _SEC_DISABLE7_NS_0, 0xbc8 */
uint32_t sec_disable8_ns; /* _SEC_DISABLE8_NS_0, 0xbcc */
uint32_t sec_disable9_ns; /* _SEC_DISABLE9_NS_0, 0xbd0 */
uint32_t sec_disable10_ns; /* _SEC_DISABLE10_NS_0, 0xbd4 */
uint32_t _0xbd8[4];
uint32_t tzram_pwr_cntrl; /* _TZRAM_PWR_CNTRL_0, 0xbe8 */
uint32_t tzram_sec_disable; /* _TZRAM_SEC_DISABLE_0, 0xbec */
uint32_t tzram_non_sec_disable; /* _TZRAM_NON_SEC_DISABLE_0, 0xbf0 */
} tegra_pmc_t;
static inline volatile tegra_pmc_t *pmc_get_regs(void)
{
return (volatile tegra_pmc_t *)PMC_BASE;
}
#endif

View File

@ -1,757 +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 <string.h>
#include "utils.h"
#include "se.h"
void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size);
/* Globals for driver. */
static unsigned int g_se_modulus_sizes[KEYSLOT_RSA_MAX];
static unsigned int g_se_exp_sizes[KEYSLOT_RSA_MAX];
/* Initialize a SE linked list. */
void NOINLINE ll_init(volatile se_ll_t *ll, void *buffer, size_t size) {
ll->num_entries = 0; /* 1 Entry. */
if (buffer != NULL) {
ll->addr_info.address = (uint32_t) get_physical_address(buffer);
ll->addr_info.size = (uint32_t) size;
} else {
ll->addr_info.address = 0;
ll->addr_info.size = 0;
}
}
void se_check_error_status_reg(void) {
if (se_get_regs()->SE_ERR_STATUS) {
generic_panic();
}
}
void se_check_for_error(void) {
volatile tegra_se_t *se = se_get_regs();
if (se->SE_INT_STATUS & 0x10000 || se->SE_STATUS & 3 || se->SE_ERR_STATUS) {
generic_panic();
}
}
void se_verify_flags_cleared(void) {
if (se_get_regs()->SE_STATUS & 3) {
generic_panic();
}
}
/* Set the flags for an AES keyslot. */
void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX) {
generic_panic();
}
/* Misc flags. */
if (flags & ~0x80) {
se->SE_CRYPTO_KEYTABLE_ACCESS[keyslot] = ~flags;
}
/* Disable keyslot reads. */
if (flags & 0x80) {
se->SE_CRYPTO_SECURITY_PERKEY &= ~(1 << keyslot);
}
}
/* Set the flags for an RSA keyslot. */
void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_RSA_MAX) {
generic_panic();
}
/* Misc flags. */
if (flags & ~0x80) {
/* TODO: Why are flags assigned this way? */
se->SE_RSA_KEYTABLE_ACCESS[keyslot] = (((flags >> 4) & 4) | (flags & 3)) ^ 7;
}
/* Disable keyslot reads. */
if (flags & 0x80) {
se->SE_RSA_SECURITY_PERKEY &= ~(1 << keyslot);
}
}
void clear_aes_keyslot(unsigned int keyslot) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX) {
generic_panic();
}
/* Zero out the whole keyslot and IV. */
for (unsigned int i = 0; i < 0x10; i++) {
se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | i;
se->SE_CRYPTO_KEYTABLE_DATA = 0;
}
}
void clear_rsa_keyslot(unsigned int keyslot) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_RSA_MAX) {
generic_panic();
}
/* Zero out the whole keyslot. */
for (unsigned int i = 0; i < 0x40; i++) {
/* Select Keyslot Modulus[i] */
se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | i | 0x40;
se->SE_RSA_KEYTABLE_DATA = 0;
}
for (unsigned int i = 0; i < 0x40; i++) {
/* Select Keyslot Expontent[i] */
se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | i;
se->SE_RSA_KEYTABLE_DATA = 0;
}
}
void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX || key_size > KEYSIZE_AES_MAX) {
generic_panic();
}
for (size_t i = 0; i < (key_size >> 2); i++) {
se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | i;
se->SE_CRYPTO_KEYTABLE_DATA = read32le(key, 4 * i);
}
}
void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_size, const void *exponent, size_t exp_size) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_RSA_MAX || modulus_size > KEYSIZE_RSA_MAX || exp_size > KEYSIZE_RSA_MAX) {
generic_panic();
}
for (size_t i = 0; i < (modulus_size >> 2); i++) {
se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | 0x40 | i;
se->SE_RSA_KEYTABLE_DATA = read32be(modulus, (4 * (modulus_size >> 2)) - (4 * i) - 4);
}
for (size_t i = 0; i < (exp_size >> 2); i++) {
se->SE_RSA_KEYTABLE_ADDR = (keyslot << 7) | i;
se->SE_RSA_KEYTABLE_DATA = read32be(exponent, (4 * (exp_size >> 2)) - (4 * i) - 4);
}
g_se_modulus_sizes[keyslot] = modulus_size;
g_se_exp_sizes[keyslot] = exp_size;
}
void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX || iv_size > 0x10) {
generic_panic();
}
for (size_t i = 0; i < (iv_size >> 2); i++) {
se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | 8 | i;
se->SE_CRYPTO_KEYTABLE_DATA = read32le(iv, 4 * i);
}
}
void clear_aes_keyslot_iv(unsigned int keyslot) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX) {
generic_panic();
}
for (size_t i = 0; i < (0x10 >> 2); i++) {
se->SE_CRYPTO_KEYTABLE_ADDR = (keyslot << 4) | 8 | i;
se->SE_CRYPTO_KEYTABLE_DATA = 0;
}
}
void set_se_ctr(const void *ctr) {
for (unsigned int i = 0; i < 4; i++) {
se_get_regs()->SE_CRYPTO_LINEAR_CTR[i] = read32le(ctr, i * 4);
}
}
void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_src, const void *wrapped_key, size_t wrapped_key_size) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot_dst >= KEYSLOT_AES_MAX || keyslot_src >= KEYSLOT_AES_MAX || wrapped_key_size > KEYSIZE_AES_MAX) {
generic_panic();
}
/* Write config, validate. */
se->SE_CONFIG = (ALG_AES_DEC | DST_KEYTAB);
if (se->SE_CONFIG != (ALG_AES_DEC | DST_KEYTAB)) {
generic_panic();
}
se->SE_CRYPTO_CONFIG = keyslot_src << 24;
if (se->SE_CRYPTO_CONFIG != (keyslot_src << 24)) {
generic_panic();
}
se->SE_CRYPTO_LAST_BLOCK = 0;
if (se->SE_CRYPTO_LAST_BLOCK != 0) {
generic_panic();
}
se->SE_CRYPTO_KEYTABLE_DST = keyslot_dst << 8;
if (se->SE_CRYPTO_KEYTABLE_DST != (keyslot_dst << 8)) {
generic_panic();
}
/* Clear address context. */
se->SE_IN_LL_ADDR = 0;
se->SE_OUT_LL_ADDR = 0;
if (se->SE_IN_LL_ADDR != 0 || se->SE_OUT_LL_ADDR != 0) {
generic_panic();
}
trigger_se_blocking_op(OP_START, NULL, 0, wrapped_key, wrapped_key_size);
/* Validate address context. */
if (se->SE_IN_LL_ADDR == 0 || se->SE_OUT_LL_ADDR == 0) {
generic_panic();
}
}
void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) {
volatile tegra_se_t *se = se_get_regs();
uint8_t ALIGN(16) stack_buf[KEYSIZE_RSA_MAX];
if (keyslot >= KEYSLOT_RSA_MAX || src_size > KEYSIZE_RSA_MAX || dst_size > KEYSIZE_RSA_MAX) {
generic_panic();
}
/* Endian swap the input. */
for (size_t i = 0; i < src_size; i++) {
stack_buf[i] = *((uint8_t *)src + src_size - i - 1);
}
se->SE_CONFIG = (ALG_RSA | DST_RSAREG);
se->SE_RSA_CONFIG = keyslot << 24;
se->SE_RSA_KEY_SIZE = (g_se_modulus_sizes[keyslot] >> 6) - 1;
se->SE_RSA_EXP_SIZE = g_se_exp_sizes[keyslot] >> 2;
trigger_se_blocking_op(OP_START, NULL, 0, stack_buf, src_size);
se_get_exp_mod_output(dst, dst_size);
}
void se_get_exp_mod_output(void *buf, size_t size) {
size_t num_dwords = (size >> 2);
if (num_dwords < 1) {
return;
}
uint32_t *p_out = ((uint32_t *)buf) + num_dwords - 1;
uint32_t offset = 0;
/* Copy endian swapped output. */
while (num_dwords) {
*p_out = read32be(se_get_regs()->SE_RSA_OUTPUT, offset);
offset += 4;
p_out--;
num_dwords--;
}
}
bool se_rsa2048_pss_verify(const void *signature, size_t signature_size, const void *modulus, size_t modulus_size, const void *data, size_t data_size) {
uint8_t message[RSA_2048_BYTES];
uint8_t h_buf[0x24];
/* Hardcode RSA with keyslot 0. */
const uint8_t public_exponent[4] = {0x00, 0x01, 0x00, 0x01};
set_rsa_keyslot(0, modulus, modulus_size, public_exponent, sizeof(public_exponent));
se_synchronous_exp_mod(0, message, sizeof(message), signature, signature_size);
/* Validate sanity byte. */
if (message[RSA_2048_BYTES - 1] != 0xBC) {
return false;
}
/* Copy Salt into MGF1 Hash Buffer. */
memset(h_buf, 0, sizeof(h_buf));
memcpy(h_buf, message + RSA_2048_BYTES - 0x20 - 0x1, 0x20);
/* Decrypt maskedDB (via inline MGF1). */
uint8_t seed = 0;
uint8_t mgf1_buf[0x20];
for (unsigned int ofs = 0; ofs < RSA_2048_BYTES - 0x20 - 1; ofs += 0x20) {
h_buf[sizeof(h_buf) - 1] = seed++;
se_calculate_sha256(mgf1_buf, h_buf, sizeof(h_buf));
for (unsigned int i = ofs; i < ofs + 0x20 && i < RSA_2048_BYTES - 0x20 - 1; i++) {
message[i] ^= mgf1_buf[i - ofs];
}
}
/* Constant lmask for rsa-2048-pss. */
message[0] &= 0x7F;
/* Validate DB is of the form 0000...0001. */
for (unsigned int i = 0; i < RSA_2048_BYTES - 0x20 - 0x20 - 1 - 1; i++) {
if (message[i] != 0) {
return false;
}
}
if (message[RSA_2048_BYTES - 0x20 - 0x20 - 1 - 1] != 1) {
return false;
}
/* Check hash correctness. */
uint8_t validate_buf[8 + 0x20 + 0x20];
uint8_t validate_hash[0x20];
memset(validate_buf, 0, sizeof(validate_buf));
se_calculate_sha256(&validate_buf[8], data, data_size);
memcpy(&validate_buf[0x28], &message[RSA_2048_BYTES - 0x20 - 0x20 - 1], 0x20);
se_calculate_sha256(validate_hash, validate_buf, sizeof(validate_buf));
return memcmp(h_buf, validate_hash, 0x20) == 0;
}
void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size) {
volatile tegra_se_t *se = se_get_regs();
se_ll_t in_ll;
se_ll_t out_ll;
ll_init(&in_ll, (void *)src, src_size);
ll_init(&out_ll, dst, dst_size);
/* Set the LLs. */
se->SE_IN_LL_ADDR = (uint32_t) get_physical_address(&in_ll);
se->SE_OUT_LL_ADDR = (uint32_t) get_physical_address(&out_ll);
/* Set registers for operation. */
se->SE_ERR_STATUS = se->SE_ERR_STATUS;
se->SE_INT_STATUS = se->SE_INT_STATUS;
if (se->SE_IN_LL_ADDR != (uint32_t) get_physical_address(&in_ll) || se->SE_OUT_LL_ADDR != (uint32_t) get_physical_address(&out_ll) || (se->SE_INT_STATUS & 0x10) || (se->SE_STATUS & 0x3)) {
generic_panic();
}
se->SE_OPERATION = op;
while (!(se->SE_INT_STATUS & 0x10)) { /* Wait a while */ }
se_check_for_error();
}
/* Secure AES Functionality. */
void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, size_t src_size) {
uint8_t block[0x10] = {0};
if (src_size > sizeof(block) || dst_size > sizeof(block)) {
generic_panic();
}
/* Load src data into block. */
if (src_size != 0) {
memcpy(block, src, src_size);
}
/* Trigger AES operation. */
se_get_regs()->SE_CRYPTO_LAST_BLOCK = 0;
trigger_se_blocking_op(OP_START, block, sizeof(block), block, sizeof(block));
/* Copy output data into dst. */
if (dst_size != 0) {
memcpy(dst, block, dst_size);
}
}
void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX || ctr_size != 0x10) {
generic_panic();
}
unsigned int num_blocks = src_size >> 4;
/* Unknown what this write does, but official code writes it for CTR mode. */
se->SE_SPARE = 1;
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY);
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x91E;
set_se_ctr(ctr);
/* Handle any aligned blocks. */
size_t aligned_size = (size_t)num_blocks << 4;
if (aligned_size) {
se->SE_CRYPTO_LAST_BLOCK = num_blocks - 1;
trigger_se_blocking_op(OP_START, dst, dst_size, src, aligned_size);
}
/* Handle final, unaligned block. */
if (aligned_size < dst_size && aligned_size < src_size) {
size_t last_block_size = dst_size - aligned_size;
if (src_size < dst_size) {
last_block_size = src_size - aligned_size;
}
se_perform_aes_block_operation(dst + aligned_size, last_block_size, (uint8_t *)src + aligned_size, src_size - aligned_size);
}
}
void se_aes_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, unsigned int config_high) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) {
generic_panic();
}
/* Set configuration high (256-bit vs 128-bit) based on parameter. */
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16);
se->SE_CRYPTO_CONFIG = keyslot << 24 | 0x100;
se_perform_aes_block_operation(dst, 0x10, src, 0x10);
}
void se_aes_128_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) {
se_aes_ecb_encrypt_block(keyslot, dst, dst_size, src, src_size, 0);
}
void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) {
se_aes_ecb_encrypt_block(keyslot, dst, dst_size, src, src_size, 0x202);
}
void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) {
generic_panic();
}
se->SE_CONFIG = (ALG_AES_DEC | DST_MEMORY);
se->SE_CRYPTO_CONFIG = keyslot << 24;
se_perform_aes_block_operation(dst, 0x10, src, 0x10);
}
void shift_left_xor_rb(uint8_t *key) {
uint8_t prev_high_bit = 0;
for (unsigned int i = 0; i < 0x10; i++) {
uint8_t cur_byte = key[0xF - i];
key[0xF - i] = (cur_byte << 1) | (prev_high_bit);
prev_high_bit = cur_byte >> 7;
}
if (prev_high_bit) {
key[0xF] ^= 0x87;
}
}
void shift_left_xor_rb_le(uint8_t *key) {
uint8_t prev_high_bit = 0;
for (unsigned int i = 0; i < 0x10; i++) {
uint8_t cur_byte = key[i];
key[i] = (cur_byte << 1) | (prev_high_bit);
prev_high_bit = cur_byte >> 7;
}
if (prev_high_bit) {
key[0x0] ^= 0x87;
}
}
void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size, unsigned int config_high) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX) {
generic_panic();
}
/* Generate the derived key, to be XOR'd with final output block. */
uint8_t ALIGN(16) derived_key[0x10] = {0};
se_aes_ecb_encrypt_block(keyslot, derived_key, sizeof(derived_key), derived_key, sizeof(derived_key), config_high);
shift_left_xor_rb(derived_key);
if (data_size & 0xF) {
shift_left_xor_rb(derived_key);
}
se->SE_CONFIG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16);
se->SE_CRYPTO_CONFIG = (keyslot << 24) | (0x145);
clear_aes_keyslot_iv(keyslot);
unsigned int num_blocks = (data_size + 0xF) >> 4;
/* Handle aligned blocks. */
if (num_blocks > 1) {
se->SE_CRYPTO_LAST_BLOCK = num_blocks - 2;
trigger_se_blocking_op(OP_START, NULL, 0, data, data_size);
se->SE_CRYPTO_CONFIG |= 0x80;
}
/* Create final block. */
uint8_t ALIGN(16) last_block[0x10] = {0};
if (data_size & 0xF) {
memcpy(last_block, data + (data_size & ~0xF), data_size & 0xF);
last_block[data_size & 0xF] = 0x80; /* Last block = data || 100...0 */
} else if (data_size >= 0x10) {
memcpy(last_block, data + data_size - 0x10, 0x10);
}
for (unsigned int i = 0; i < 0x10; i++) {
last_block[i] ^= derived_key[i];
}
/* Perform last operation. */
se->SE_CRYPTO_LAST_BLOCK = 0;
trigger_se_blocking_op(OP_START, NULL, 0, last_block, sizeof(last_block));
/* Copy output CMAC. */
for (unsigned int i = 0; i < (cmac_size >> 2); i++) {
((uint32_t *)cmac)[i] = read32le(se->SE_HASH_RESULT, i << 2);
}
}
void se_compute_aes_128_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size) {
se_compute_aes_cmac(keyslot, cmac, cmac_size, data, data_size, 0);
}
void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size) {
se_compute_aes_cmac(keyslot, cmac, cmac_size, data, data_size, 0x202);
}
void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX || src_size < 0x10) {
generic_panic();
}
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY) | (0x202 << 16);
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x144;
set_aes_keyslot_iv(keyslot, iv, 0x10);
se->SE_CRYPTO_LAST_BLOCK = (src_size >> 4) - 1;
trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size);
}
void se_aes_128_cbc_decrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX || src_size < 0x10) {
generic_panic();
}
se->SE_CONFIG = (ALG_AES_DEC | DST_MEMORY) | (0x000 << 16);
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x66;
clear_aes_keyslot_iv(keyslot);
se->SE_CRYPTO_LAST_BLOCK = (src_size >> 4) - 1;
trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size);
}
/* SHA256 Implementation. */
void se_calculate_sha256(void *dst, const void *src, size_t src_size) {
volatile tegra_se_t *se = se_get_regs();
/* Setup config for SHA256, size = BITS(src_size) */
se->SE_CONFIG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG);
se->SE_SHA_CONFIG = 1;
se->SE_SHA_MSG_LENGTH[0] = (uint32_t)(src_size << 3);
se->SE_SHA_MSG_LENGTH[1] = 0;
se->SE_SHA_MSG_LENGTH[2] = 0;
se->SE_SHA_MSG_LENGTH[3] = 0;
se->SE_SHA_MSG_LEFT[0] = (uint32_t)(src_size << 3);
se->SE_SHA_MSG_LEFT[1] = 0;
se->SE_SHA_MSG_LEFT[2] = 0;
se->SE_SHA_MSG_LEFT[3] = 0;
/* Trigger the operation. */
trigger_se_blocking_op(OP_START, NULL, 0, src, src_size);
/* Copy output hash. */
for (unsigned int i = 0; i < (0x20 >> 2); i++) {
((uint32_t *)dst)[i] = read32be(se->SE_HASH_RESULT, i << 2);
}
}
/* RNG API */
void se_initialize_rng(unsigned int keyslot) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX) {
generic_panic();
}
/* To initialize the RNG, we'll perform an RNG operation into an output buffer. */
/* This will be discarded, when done. */
uint8_t ALIGN(16) output_buf[0x10];
se->SE_RNG_SRC_CONFIG = 3; /* Entropy enable + Entropy lock enable */
se->SE_RNG_RESEED_INTERVAL = 70001;
se->SE_CONFIG = (ALG_RNG | DST_MEMORY);
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x108;
se->SE_RNG_CONFIG = 5;
se->SE_CRYPTO_LAST_BLOCK = 0;
trigger_se_blocking_op(OP_START, output_buf, 0x10, NULL, 0);
}
void se_generate_random(unsigned int keyslot, void *dst, size_t size) {
volatile tegra_se_t *se = se_get_regs();
if (keyslot >= KEYSLOT_AES_MAX) {
generic_panic();
}
uint32_t num_blocks = size >> 4;
size_t aligned_size = num_blocks << 4;
se->SE_CONFIG = (ALG_RNG | DST_MEMORY);
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x108;
se->SE_RNG_CONFIG = 4;
if (num_blocks >= 1) {
se->SE_CRYPTO_LAST_BLOCK = num_blocks - 1;
trigger_se_blocking_op(OP_START, dst, aligned_size, NULL, 0);
}
if (size > aligned_size) {
se_perform_aes_block_operation(dst + aligned_size, size - aligned_size, NULL, 0);
}
}
void se_generate_random_key(unsigned int dst_keyslot, unsigned int rng_keyslot) {
volatile tegra_se_t *se = se_get_regs();
if (dst_keyslot >= KEYSLOT_AES_MAX || rng_keyslot >= KEYSLOT_AES_MAX) {
generic_panic();
}
/* Setup Config. */
se->SE_CONFIG = (ALG_RNG | DST_KEYTAB);
se->SE_CRYPTO_CONFIG = (rng_keyslot << 24) | 0x108;
se->SE_RNG_CONFIG = 4;
se->SE_CRYPTO_LAST_BLOCK = 0;
/* Generate low part of key. */
se->SE_CRYPTO_KEYTABLE_DST = (dst_keyslot << 8);
trigger_se_blocking_op(OP_START, NULL, 0, NULL, 0);
/* Generate high part of key. */
se->SE_CRYPTO_KEYTABLE_DST = (dst_keyslot << 8) | 1;
trigger_se_blocking_op(OP_START, NULL, 0, NULL, 0);
}
/* SE context save API. */
void se_set_in_context_save_mode(bool is_context_save_mode) {
volatile tegra_se_t *se = se_get_regs();
uint32_t val = se->SE_SE_SECURITY;
if (is_context_save_mode) {
val |= 0x10000;
} else {
val &= 0xFFFEFFFF;
}
se->SE_SE_SECURITY = val;
/* Perform a useless read from flags reg. */
(void)(se->SE_STATUS);
}
void se_generate_srk(unsigned int srkgen_keyslot) {
volatile tegra_se_t *se = se_get_regs();
se->SE_CONFIG = (ALG_RNG | DST_SRK);
se->SE_CRYPTO_CONFIG = (srkgen_keyslot << 24) | 0x108;
se->SE_RNG_CONFIG = 6;
se->SE_CRYPTO_LAST_BLOCK = 0;
trigger_se_blocking_op(OP_START, NULL, 0, NULL, 0);
}
void se_encrypt_with_srk(void *dst, size_t dst_size, const void *src, size_t src_size) {
uint8_t output[0x80];
uint8_t *aligned_out = (uint8_t *)(((uintptr_t)output + 0x7F) & ~0x3F);
if (dst_size > 0x10) {
generic_panic();
}
if (dst_size) {
trigger_se_blocking_op(OP_CTX_SAVE, aligned_out, dst_size, src, src_size);
memcpy(dst, aligned_out, dst_size);
} else {
trigger_se_blocking_op(OP_CTX_SAVE, aligned_out, 0, src, src_size);
}
}
void se_save_context(unsigned int srkgen_keyslot, unsigned int rng_keyslot, void *dst) {
volatile tegra_se_t *se = se_get_regs();
uint8_t _work_buf[0x80];
uint8_t *work_buf = (uint8_t *)(((uintptr_t)_work_buf + 0x7F) & ~0x3F);
/* Generate the SRK (context save encryption key). */
se_generate_random_key(srkgen_keyslot, rng_keyslot);
se_generate_srk(srkgen_keyslot);
se_generate_random(rng_keyslot, work_buf, 0x10);
/* Save random initial block. */
se->SE_CONFIG = (ALG_AES_ENC | DST_MEMORY);
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_MEM);
se->SE_CRYPTO_LAST_BLOCK = 0;
se_encrypt_with_srk(dst, 0x10, work_buf, 0x10);
/* Save Sticky Bits. */
for (unsigned int i = 0; i < 0x2; i++) {
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_STICKY_BITS) | (i << CTX_SAVE_STICKY_BIT_INDEX_SHIFT);
se->SE_CRYPTO_LAST_BLOCK = 0;
se_encrypt_with_srk(dst + 0x10 + (i * 0x10), 0x10, NULL, 0);
}
/* Save AES Key Table. */
for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) {
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_LOW_BITS);
se->SE_CRYPTO_LAST_BLOCK = 0;
se_encrypt_with_srk(dst + 0x30 + (i * 0x20), 0x10, NULL, 0);
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_HIGH_BITS);
se->SE_CRYPTO_LAST_BLOCK = 0;
se_encrypt_with_srk(dst + 0x40 + (i * 0x20), 0x10, NULL, 0);
}
/* Save AES Original IVs. */
for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) {
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_ORIGINAL_IV);
se->SE_CRYPTO_LAST_BLOCK = 0;
se_encrypt_with_srk(dst + 0x230 + (i * 0x10), 0x10, NULL, 0);
}
/* Save AES Updated IVs */
for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) {
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_UPDATED_IV);
se->SE_CRYPTO_LAST_BLOCK = 0;
se_encrypt_with_srk(dst + 0x330 + (i * 0x10), 0x10, NULL, 0);
}
/* Save RSA Keytable. */
uint8_t *rsa_ctx_out = (uint8_t *)dst + 0x430;
for (unsigned int rsa_key = 0; rsa_key < KEYSLOT_RSA_MAX; rsa_key++) {
for (unsigned int mod_exp = 0; mod_exp < 2; mod_exp++) {
for (unsigned int sub_block = 0; sub_block < 0x10; sub_block++) {
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_KEYTABLE_RSA) | ((2 * rsa_key + (1 - mod_exp)) << CTX_SAVE_RSA_KEY_INDEX_SHIFT) | (sub_block << CTX_SAVE_RSA_KEY_BLOCK_INDEX_SHIFT);
se->SE_CRYPTO_LAST_BLOCK = 0;
se_encrypt_with_srk(rsa_ctx_out, 0x10, NULL, 0);
rsa_ctx_out += 0x10;
}
}
}
/* Save "Known Pattern. " */
static const uint8_t context_save_known_pattern[0x10] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_MEM);
se->SE_CRYPTO_LAST_BLOCK = 0;
se_encrypt_with_srk(dst + 0x830, 0x10, context_save_known_pattern, 0x10);
/* Save SRK into PMC registers. */
se->SE_CTX_SAVE_CONFIG = (CTX_SAVE_SRC_SRK);
se->SE_CRYPTO_LAST_BLOCK = 0;
se_encrypt_with_srk(work_buf, 0, NULL, 0);
se->SE_CONFIG = 0;
se_encrypt_with_srk(work_buf, 0, NULL, 0);
}

View File

@ -1,216 +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 <stdbool.h>
#ifndef FUSEE_SE_H
#define FUSEE_SE_H
#define SE_BASE 0x70012000
#define MAKE_SE_REG(n) MAKE_REG32(SE_BASE + n)
#define KEYSLOT_SWITCH_LP0TZRAMKEY 0x2
#define KEYSLOT_SWITCH_SRKGENKEY 0x8
#define KEYSLOT_SWITCH_PACKAGE2KEY 0x8
#define KEYSLOT_SWITCH_TEMPKEY 0x9
#define KEYSLOT_SWITCH_SESSIONKEY 0xA
#define KEYSLOT_SWITCH_RNGKEY 0xB
#define KEYSLOT_SWITCH_MASTERKEY 0xC
#define KEYSLOT_SWITCH_DEVICEKEY 0xD
/* This keyslot was added in 4.0.0. */
#define KEYSLOT_SWITCH_4XNEWDEVICEKEYGENKEY 0xD
#define KEYSLOT_SWITCH_4XNEWCONSOLEKEYGENKEY 0xE
#define KEYSLOT_SWITCH_4XOLDDEVICEKEY 0xF
/* This keyslot was added in 5.0.0. */
#define KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY 0xA
/* Mariko keyslots. */
#define KEYSLOT_SWITCH_MASTERKEY_MARIKO 0x7
#define KEYSLOT_AES_MAX 0x10
#define KEYSLOT_RSA_MAX 0x2
#define KEYSIZE_AES_MAX 0x20
#define KEYSIZE_RSA_MAX 0x100
#define ALG_SHIFT (12)
#define ALG_DEC_SHIFT (8)
#define ALG_NOP (0 << ALG_SHIFT)
#define ALG_AES_ENC (1 << ALG_SHIFT)
#define ALG_AES_DEC ((1 << ALG_DEC_SHIFT) | ALG_NOP)
#define ALG_RNG (2 << ALG_SHIFT)
#define ALG_SHA (3 << ALG_SHIFT)
#define ALG_RSA (4 << ALG_SHIFT)
#define DST_SHIFT (2)
#define DST_MEMORY (0 << DST_SHIFT)
#define DST_HASHREG (1 << DST_SHIFT)
#define DST_KEYTAB (2 << DST_SHIFT)
#define DST_SRK (3 << DST_SHIFT)
#define DST_RSAREG (4 << DST_SHIFT)
#define ENCMODE_SHIFT (24)
#define DECMODE_SHIFT (16)
#define ENCMODE_SHA256 (5 << ENCMODE_SHIFT)
#define HASH_DISABLE (0x0)
#define HASH_ENABLE (0x1)
#define OP_ABORT 0
#define OP_START 1
#define OP_RESTART 2
#define OP_CTX_SAVE 3
#define OP_RESTART_IN 4
#define CTX_SAVE_SRC_SHIFT 29
#define CTX_SAVE_SRC_STICKY_BITS (0 << CTX_SAVE_SRC_SHIFT)
#define CTX_SAVE_SRC_KEYTABLE_AES (2 << CTX_SAVE_SRC_SHIFT)
#define CTX_SAVE_SRC_KEYTABLE_RSA (1 << CTX_SAVE_SRC_SHIFT)
#define CTX_SAVE_SRC_MEM (4 << CTX_SAVE_SRC_SHIFT)
#define CTX_SAVE_SRC_SRK (6 << CTX_SAVE_SRC_SHIFT)
#define CTX_SAVE_KEY_LOW_BITS 0
#define CTX_SAVE_KEY_HIGH_BITS 1
#define CTX_SAVE_KEY_ORIGINAL_IV 2
#define CTX_SAVE_KEY_UPDATED_IV 3
#define CTX_SAVE_STICKY_BIT_INDEX_SHIFT 24
#define CTX_SAVE_KEY_INDEX_SHIFT 8
#define CTX_SAVE_RSA_KEY_INDEX_SHIFT 16
#define CTX_SAVE_RSA_KEY_BLOCK_INDEX_SHIFT 12
#define RSA_2048_BYTES 0x100
typedef struct {
uint32_t SE_SE_SECURITY;
uint32_t SE_TZRAM_SECURITY;
uint32_t SE_OPERATION;
uint32_t SE_INT_ENABLE;
uint32_t SE_INT_STATUS;
uint32_t SE_CONFIG;
uint32_t SE_IN_LL_ADDR;
uint32_t SE_IN_CUR_BYTE_ADDR;
uint32_t SE_IN_CUR_LL_ID;
uint32_t SE_OUT_LL_ADDR;
uint32_t SE_OUT_CUR_BYTE_ADDR;
uint32_t SE_OUT_CUR_LL_ID;
uint32_t SE_HASH_RESULT[0x10];
uint32_t SE_CTX_SAVE_CONFIG;
uint32_t _0x74[0x63];
uint32_t SE_SHA_CONFIG;
uint32_t SE_SHA_MSG_LENGTH[0x4];
uint32_t SE_SHA_MSG_LEFT[0x4];
uint32_t _0x224[0x17];
uint32_t SE_CRYPTO_SECURITY_PERKEY;
uint32_t SE_CRYPTO_KEYTABLE_ACCESS[0x10];
uint32_t _0x2C4[0x10];
uint32_t SE_CRYPTO_CONFIG;
uint32_t SE_CRYPTO_LINEAR_CTR[0x4];
uint32_t SE_CRYPTO_LAST_BLOCK;
uint32_t SE_CRYPTO_KEYTABLE_ADDR;
uint32_t SE_CRYPTO_KEYTABLE_DATA;
uint32_t _0x324[0x3];
uint32_t SE_CRYPTO_KEYTABLE_DST;
uint32_t _0x334[0x3];
uint32_t SE_RNG_CONFIG;
uint32_t SE_RNG_SRC_CONFIG;
uint32_t SE_RNG_RESEED_INTERVAL;
uint32_t _0x34C[0x2D];
uint32_t SE_RSA_CONFIG;
uint32_t SE_RSA_KEY_SIZE;
uint32_t SE_RSA_EXP_SIZE;
uint32_t SE_RSA_SECURITY_PERKEY;
uint32_t SE_RSA_KEYTABLE_ACCESS[0x2];
uint32_t _0x418[0x2];
uint32_t SE_RSA_KEYTABLE_ADDR;
uint32_t SE_RSA_KEYTABLE_DATA;
uint32_t SE_RSA_OUTPUT[0x40];
uint32_t _0x528[0xB6];
uint32_t SE_STATUS;
uint32_t SE_ERR_STATUS;
uint32_t SE_MISC;
uint32_t SE_SPARE;
uint32_t SE_ENTROPY_DEBUG_COUNTER;
uint32_t _0x814;
uint32_t _0x818;
uint32_t _0x81C;
uint32_t _0x820[0x5F8];
} tegra_se_t;
typedef struct {
uint32_t address;
uint32_t size;
} se_addr_info_t;
typedef struct {
uint32_t num_entries; /* Set to total entries - 1 */
se_addr_info_t addr_info; /* This should really be an array...but for our use case it works. */
} se_ll_t;
static inline volatile tegra_se_t *se_get_regs(void) {
return (volatile tegra_se_t *)SE_BASE;
}
void se_check_error_status_reg(void);
void se_check_for_error(void);
void se_trigger_interrupt(void);
void se_validate_stored_vector(void);
void se_generate_stored_vector(void);
void se_verify_flags_cleared(void);
void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags);
void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags);
void clear_aes_keyslot(unsigned int keyslot);
void clear_rsa_keyslot(unsigned int keyslot);
void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size);
void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_src, const void *wrapped_key, size_t wrapped_key_size);
void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_size, const void *exponent, size_t exp_size);
void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size);
void set_se_ctr(const void *ctr);
/* Secure AES API */
void se_compute_aes_128_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size);
void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size);
void se_aes_128_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size);
void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv);
void se_aes_128_cbc_decrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
/* Hash API */
void se_calculate_sha256(void *dst, const void *src, size_t src_size);
/* RSA API */
void se_get_exp_mod_output(void *buf, size_t size);
void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
bool se_rsa2048_pss_verify(const void *signature, size_t signature_size, const void *modulus, size_t modulus_size, const void *data, size_t data_size);
/* RNG API */
void se_initialize_rng(unsigned int keyslot);
void se_generate_random(unsigned int keyslot, void *dst, size_t size);
/* SE context save API. */
void se_generate_srk(unsigned int srkgen_keyslot);
void se_set_in_context_save_mode(bool is_context_save_mode);
void se_generate_random_key(unsigned int dst_keyslot, unsigned int rng_keyslot);
void se_save_context(unsigned int srk_keyslot, unsigned int rng_keyslot, void *dst);
#endif

View File

@ -1,100 +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/>.
*/
/* For some reason GAS doesn't know about it, even with .cpu cortex-a57 */
#define cpuactlr_el1 s3_1_c15_c2_0
#define cpuectlr_el1 s3_1_c15_c2_1
.macro RESET_CORE
mov x0, #(1 << 63)
msr cpuactlr_el1, x0 /* disable regional clock gating */
isb
mov x0, #3
msr rmr_el3, x0
isb
dsb sy
/* Nintendo forgot to copy-paste the branch instruction below. */
1:
wfi
b 1b
.endm
.macro ERRATUM_INVALIDATE_BTB_AT_BOOT
/* Nintendo copy-pasted https://github.com/ARM-software/arm-trusted-firmware/blob/master/plat/nvidia/tegra/common/aarch64/tegra_helpers.S#L312 */
/*
* Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/* The following comments are mine. */
/* mask all interrupts */
msr daifset, 0b1111
/*
Enable invalidates of branch target buffer, then flush
the entire instruction cache at the local level, and
with the reg change, the branch target buffer, then disable
invalidates of the branch target buffer again.
*/
mrs x0, cpuactlr_el1
orr x0, x0, #1
msr cpuactlr_el1, x0
dsb sy
isb
ic iallu
dsb sy
isb
mrs x0, cpuactlr_el1
bic x0, x0, #1
msr cpuactlr_el1, x0
.rept 7
nop /* wait long enough for the write to cpuactlr_el1 to have completed */
.endr
/* if the OS lock is set, disable it and request a warm reset */
mrs x0, oslsr_el1
ands x0, x0, #2
b.eq 2f
mov x0, xzr
msr oslar_el1, x0
RESET_CORE
.rept 65
nop /* guard against speculative excecution */
.endr
2:
/* set the OS lock */
mov x0, #1
msr oslar_el1, x0
.endm
.section .text.start
.align 4
.global _start
_start:
ERRATUM_INVALIDATE_BTB_AT_BOOT
msr spsel, #0
ldr x0, =__start__
mov sp, x0
mov fp, #0x0
bl derive_keys

View File

@ -1,33 +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 <stdbool.h>
#include <stdarg.h>
#include "utils.h"
#include "se.h"
#include <inttypes.h>
__attribute__ ((noreturn)) void generic_panic(void) {
/* Clear keyslots. */
clear_aes_keyslot(0xD);
clear_aes_keyslot(0xE);
for (size_t i = 0; i < 0x10; i++) {
clear_aes_keyslot(i);
}
clear_aes_keyslot(0xD);
clear_aes_keyslot(0xE);
while(1) { /* ... */ }
}

View File

@ -1,122 +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/>.
*/
#ifndef FUSEE_UTILS_H
#define FUSEE_UTILS_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#define BIT(n) (1u << (n))
#define BITL(n) (1ull << (n))
#define MASK(n) (BIT(n) - 1)
#define MASKL(n) (BITL(n) - 1)
#define MASK2(a,b) (MASK(a) & ~MASK(b))
#define MASK2L(a,b) (MASKL(a) & ~MASKL(b))
#define MAKE_REG32(a) (*(volatile uint32_t *)(a))
#define ALIGN(m) __attribute__((aligned(m)))
#define PACKED __attribute__((packed))
#define ALINLINE __attribute__((always_inline))
#define NOINLINE __attribute__((noinline))
#define SET_SYSREG(reg, val) do { temp_reg = (val); __asm__ __volatile__ ("msr " #reg ", %0" :: "r"(temp_reg) : "memory"); } while(false)
static inline uintptr_t get_physical_address(const void *addr) {
return (uintptr_t)addr;
}
static inline uint32_t read32le(const volatile void *dword, size_t offset) {
uintptr_t addr = (uintptr_t)dword + offset;
volatile uint32_t *target = (uint32_t *)addr;
return *target;
}
static inline uint32_t read32be(const volatile void *dword, size_t offset) {
return __builtin_bswap32(read32le(dword, offset));
}
static inline uint64_t read64le(const volatile void *qword, size_t offset) {
uintptr_t addr = (uintptr_t)qword + offset;
volatile uint64_t *target = (uint64_t *)addr;
return *target;
}
static inline uint64_t read64be(const volatile void *qword, size_t offset) {
return __builtin_bswap64(read64le(qword, offset));
}
static inline void write32le(volatile void *dword, size_t offset, uint32_t value) {
uintptr_t addr = (uintptr_t)dword + offset;
volatile uint32_t *target = (uint32_t *)addr;
*target = value;
}
static inline void write32be(volatile void *dword, size_t offset, uint32_t value) {
write32le(dword, offset, __builtin_bswap32(value));
}
static inline void write64le(volatile void *qword, size_t offset, uint64_t value) {
uintptr_t addr = (uintptr_t)qword + offset;
volatile uint64_t *target = (uint64_t *)addr;
*target = value;
}
static inline void write64be(volatile void *qword, size_t offset, uint64_t value) {
write64le(qword, offset, __builtin_bswap64(value));
}
static inline bool check_32bit_additive_overflow(uint32_t a, uint32_t b) {
return __builtin_add_overflow_p(a, b, (uint32_t)0);
}
static inline bool check_32bit_address_loadable(uintptr_t addr) {
/* FWIW the bootROM forbids loading anything between 0x40000000 and 0x40010000, using it for itself... */
return (addr >= 0x40010000u && addr < 0x40040000u) || addr >= 0x80000000u;
}
static inline bool check_32bit_address_range_loadable(uintptr_t addr, size_t size) {
return
!__builtin_add_overflow_p(addr, size, (uintptr_t)0) && /* the range doesn't overflow */
check_32bit_address_loadable(addr) && check_32bit_address_loadable(addr + size) && /* bounds are valid */
!(addr >= 0x40010000u && addr < 0x40040000u && addr + size >= 0x40040000u) /* the range doesn't cross MMIO */
;
}
bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, uint64_t be);
static inline bool overlaps_a(const void *as, const void *ae, const void *bs, const void *be) {
return overlaps((uint64_t)(uintptr_t)as, (uint64_t)(uintptr_t)ae, (uint64_t)(uintptr_t)bs, (uint64_t)(uintptr_t)be);
}
static inline bool check_32bit_address_range_in_program(uintptr_t addr, size_t size) {
extern uint8_t __chainloader_start__[], __chainloader_end__[];
extern uint8_t __stack_bottom__[], __stack_top__[];
extern uint8_t __start__[], __end__[];
uint8_t *start = (uint8_t *)addr, *end = start + size;
return overlaps_a(start, end, __chainloader_start__, __chainloader_end__) ||
overlaps_a(start, end, __stack_bottom__, __stack_top__) ||
overlaps_a(start, end, (void *)0xC0000000, (void *)0xC03C0000) || /* framebuffer */
overlaps_a(start, end, __start__, __end__);
}
__attribute__((noreturn)) void generic_panic(void);
#endif

View File

@ -1,193 +0,0 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
PHDRS
{
crt0 PT_LOAD;
chainloader PT_LOAD;
main PT_LOAD;
}
/* Mostly copied from https://github.com/devkitPro/buildscripts/blob/master/dkarm-eabi/crtls/3dsx.ld */
MEMORY
{
NULL : ORIGIN = 0x00000000, LENGTH = 0x1000
main : ORIGIN = 0x40010000, LENGTH = 0x20000
low_iram : ORIGIN = 0x40002000, LENGTH = 0x6000
}
SECTIONS
{
PROVIDE(__start__ = 0x40010000);
PROVIDE(__stack_top__ = 0x40010000);
PROVIDE(__stack_bottom__ = 0x40008000);
PROVIDE(__heap_start__ = 0);
PROVIDE(__heap_end__ = 0);
. = __start__;
.crt0 :
{
KEEP( *(.text.start) )
KEEP( *(.init) )
. = ALIGN(32);
} >main :crt0
.chainloader_loadable :
{
. = ALIGN(32);
PROVIDE (__chainloader_start__ = ABSOLUTE(.));
PROVIDE (__chainloader_lma__ = LOADADDR(.chainloader_loadable));
KEEP(*(.chainloader.text.start))
chainloader.o(.text*)
chainloader.o(.rodata*)
chainloader.o(.data*)
. = ALIGN(32);
} >low_iram AT>main :chainloader
.chainloader_bss (NOLOAD) :
{
. = ALIGN(32);
PROVIDE (__chainloader_bss_start__ = ABSOLUTE(.));
chainloader.o(.bss* COMMON)
. = ALIGN(32);
PROVIDE (__chainloader_end__ = ABSOLUTE(.));
} >low_iram :NONE
.text :
{
. = ALIGN(32);
/* .text */
*(.text)
*(.text.*)
*(.glue_7)
*(.glue_7t)
*(.stub)
*(.gnu.warning)
*(.gnu.linkonce.t*)
/* .fini */
KEEP( *(.fini) )
. = ALIGN(8);
} >main :main
.rodata :
{
*(.rodata)
*(.roda)
*(.rodata.*)
*all.rodata*(*)
*(.gnu.linkonce.r*)
SORT(CONSTRUCTORS)
. = ALIGN(8);
} >main
.preinit_array :
{
PROVIDE (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE (__preinit_array_end = .);
} >main
.init_array ALIGN(4) :
{
PROVIDE (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
PROVIDE (__init_array_end = .);
} >main
.fini_array ALIGN(4) :
{
PROVIDE (__fini_array_start = .);
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
PROVIDE (__fini_array_end = .);
} >main
.ctors ALIGN(4) :
{
KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >main
.dtors ALIGN(4) :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >main
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) __exidx_start = ABSOLUTE(.);} >main
ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) __exidx_end = ABSOLUTE(.);} >main
.data :
{
*(.data)
*(.data.*)
*(.gnu.linkonce.d*)
CONSTRUCTORS
. = ALIGN(32);
} >main
.bss (NOLOAD) :
{
. = ALIGN(32);
PROVIDE (__bss_start__ = ABSOLUTE(.));
*(.dynbss)
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b*)
*(COMMON)
. = ALIGN(32);
PROVIDE (__bss_end__ = ABSOLUTE(.));
} >main :NONE
. = ALIGN(32);
__end__ = ABSOLUTE(.) ;
/* ==================
==== Metadata ====
================== */
/* Discard sections that difficult post-processing */
/DISCARD/ : { *(.group .comment .note) }
/* 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) }
}

View File

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

View File

@ -1,84 +0,0 @@
#!/usr/bin/env python
import sys, os
from struct import pack as pk, unpack as up
from Crypto.Cipher import AES
from Crypto.Hash import CMAC
try:
import KEYS
except ImportError:
import KEYS_template as KEYS
print('Warning: output will not work on 7.0.0+!')
def shift_left_xor_rb(s):
if hasattr(int, "from_bytes"):
N = int.from_bytes(s, byteorder="big")
else:
N = int(s.encode('hex'), 16)
if N & (1 << 127):
N = ((N << 1) ^ 0x87) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
else:
N = ((N << 1) ^ 0x00) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
return bytearray.fromhex('%032x' % N)
def sxor(x, y):
return bytearray(a^b for a,b in zip(x, y))
def get_last_block_for_desired_mac(key, data, desired_mac):
assert len(desired_mac) == 0x10
k1 = shift_left_xor_rb(AES.new(key, AES.MODE_ECB).encrypt(bytearray(0x10)))
if len(data) & 0xF:
k1 = shift_left_xor_rb(k1)
data = data + b'\x80'
data = data + bytearray((0x10 - (len(data) & 0xF)) & 0xF)
num_blocks = (len(data) + 0xF) >> 4
last_block = sxor(bytearray(AES.new(key, AES.MODE_ECB).decrypt(desired_mac)), bytearray(k1))
if len(data) > 0x0:
last_block = sxor(last_block, bytearray(AES.new(key, AES.MODE_CBC, bytearray(0x10)).encrypt(data)[-0x10:]))
return last_block
def sign_encrypt_code(code, sig_key, enc_key, iv, desired_mac, version):
# Pad with 0x20 of zeroes.
code = code + bytearray(0x20)
code_len = len(code)
code_len += 0xFFF
code_len &= ~0xFFF
code = code + bytearray(code_len - len(code))
# Insert version
code = code[:8] + pk('<I', version) + code[12:]
# Add empty trustzone, warmboot segments.
code = code + bytearray(0x1FE0 - 0x10)
pk11_hdr = b'PK11' + pk('<IIIIIII', 0x1000, 0, 0, code_len - 0x20, 0, 0x1000, 0)
pk11 = pk11_hdr + code
enc_pk11 = AES.new(enc_key, AES.MODE_CBC, iv).encrypt(pk11)
enc_pk11 = pk('<IIII', len(pk11) + 0x10, 0, 0, 0) + iv + enc_pk11
enc_pk11 = enc_pk11 + get_last_block_for_desired_mac(sig_key, enc_pk11, desired_mac)
enc_pk11 = enc_pk11 + CMAC.new(sig_key, enc_pk11, AES).digest()
return enc_pk11
def main(argc, argv):
if argc != 3:
print('Usage: %s input output' % argv[0])
return 1
with open(argv[1], 'rb') as f:
code = f.read()
if len(code) & 0xF:
code = code + bytearray(0x10 - (len(code) & 0xF))
fn, fext = os.path.splitext(argv[2])
for key in range(KEYS.NUM_KEYS):
with open(fn + ('_%02X' % key) + fext, 'wb') as f:
f.write(sign_encrypt_code(code, KEYS.HOVI_SIG_KEY_PRD[key], KEYS.HOVI_ENC_KEY_PRD[key], KEYS.IV[key], b'THANKS_NVIDIA_<3', key))
with open(fn + ('_dev_%02X' % key) + fext, 'wb') as f:
f.write(sign_encrypt_code(code, KEYS.HOVI_SIG_KEY_DEV[key], KEYS.HOVI_ENC_KEY_DEV[key], KEYS.IV_DEV[key], b'THANKS_NVIDIA_<3', key))
return 0
if __name__ == '__main__':
sys.exit(main(len(sys.argv), sys.argv))

View File

@ -1,96 +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/>.
*/
#ifndef FUSEE_APB_MISC_H
#define FUSEE_APB_MISC_H
#include <stdint.h>
#define APB_MISC_BASE 0x70000000
#define APB_PADCTL_BASE 0x70000810
#define MAKE_APB_MISC_REG(n) MAKE_REG32(APB_MISC_BASE + n)
#define MAKE_APB_PADCTL_REG(n) MAKE_REG32(APB_PADCTL_BASE + n)
#define APB_MISC_PP_PINMUX_GLOBAL_0 MAKE_APB_MISC_REG(0x40)
#define APB_MISC_GP_DSI_PAD_CONTROL_0 MAKE_APB_MISC_REG(0xAC0)
#define APB_MISC_GP_WIFI_EN_CFGPADCTRL_0 MAKE_APB_MISC_REG(0xB64)
#define APB_MISC_GP_WIFI_RST_CFGPADCTRL_0 MAKE_APB_MISC_REG(0xB68)
#define SDMMC1_PAD_CAL_DRVUP_SHIFT (20)
#define SDMMC1_PAD_CAL_DRVDN_SHIFT (12)
#define SDMMC1_CLK_CFG_CAL_DRVDN_SLWR_SHIFT (28)
#define SDMMC1_CLK_CFG_CAL_DRVDN_SLWF_SHIFT (30)
#define SDMMC1_PAD_CAL_DRVUP_MASK (0x7Fu << SDMMC1_PAD_CAL_DRVUP_SHIFT)
#define SDMMC1_PAD_CAL_DRVDN_MASK (0x7Fu << SDMMC1_PAD_CAL_DRVDN_SHIFT)
#define SDMMC1_CLK_CFG_CAL_DRVDN_SLWR_MASK (0x03u << SDMMC1_CLK_CFG_CAL_DRVDN_SLWR_SHIFT)
#define SDMMC1_CLK_CFG_CAL_DRVDN_SLWF_MASK (0x03u << SDMMC1_CLK_CFG_CAL_DRVDN_SLWF_SHIFT)
#define EMMC2_PAD_DRVUP_COMP_SHIFT (8)
#define EMMC2_PAD_DRVDN_COMP_SHIFT (2)
#define EMMC2_PAD_DRVUP_COMP_MASK (0x3Fu << EMMC2_PAD_DRVUP_COMP_SHIFT)
#define EMMC2_PAD_DRVDN_COMP_MASK (0x3Fu << EMMC2_PAD_DRVDN_COMP_SHIFT)
#define SDMMC2_PAD_CAL_DRVUP_SHIFT (20)
#define SDMMC2_PAD_CAL_DRVDN_SHIFT (12)
#define SDMMC2_PAD_CAL_DRVUP_MASK (0x7Fu << SDMMC2_PAD_CAL_DRVUP_SHIFT)
#define SDMMC2_PAD_CAL_DRVDN_MASK (0x7Fu << SDMMC2_PAD_CAL_DRVDN_SHIFT)
#define EMMC4_PAD_DRVUP_COMP_SHIFT (8)
#define EMMC4_PAD_DRVDN_COMP_SHIFT (2)
#define EMMC4_PAD_DRVUP_COMP_MASK (0x3Fu << EMMC4_PAD_DRVUP_COMP_SHIFT)
#define EMMC4_PAD_DRVDN_COMP_MASK (0x3Fu << EMMC4_PAD_DRVDN_COMP_SHIFT)
#define PADCTL_SDMMC1_DEEP_LOOPBACK (1 << 0)
#define PADCTL_SDMMC3_DEEP_LOOPBACK (1 << 0)
#define PADCTL_SDMMC2_ENABLE_DATA_IN (0xFF << 8)
#define PADCTL_SDMMC2_ENABLE_CLK_IN (0x3 << 4)
#define PADCTL_SDMMC2_DEEP_LOOPBACK (1 << 0)
#define PADCTL_SDMMC4_ENABLE_DATA_IN (0xFF << 8)
#define PADCTL_SDMMC4_ENABLE_CLK_IN (0x3 << 4)
#define PADCTL_SDMMC4_DEEP_LOOPBACK (1 << 0)
#define PADCTL_SDMMC1_CD_SOURCE (1 << 0)
#define PADCTL_SDMMC1_WP_SOURCE (1 << 1)
#define PADCTL_SDMMC3_CD_SOURCE (1 << 2)
#define PADCTL_SDMMC3_WP_SOURCE (1 << 3)
typedef struct {
uint32_t asdbgreg; /* 0x810 */
uint32_t _0x814[0x31];
uint32_t sdmmc1_clk_lpbk_control; /* 0x8D4 */
uint32_t sdmmc3_clk_lpbk_control; /* 0x8D8 */
uint32_t emmc2_pad_cfg_control; /* 0x8DC */
uint32_t emmc4_pad_cfg_control; /* 0x8E0 */
uint32_t _0x8E4[0x6E];
uint32_t sdmmc1_pad_cfgpadctrl; /* 0xA98 */
uint32_t emmc2_pad_cfgpadctrl; /* 0xA9C */
uint32_t emmc2_pad_drv_type_cfgpadctrl; /* 0xAA0 */
uint32_t emmc2_pad_pupd_cfgpadctrl; /* 0xAA4 */
uint32_t _0xAA8[0x03];
uint32_t sdmmc3_pad_cfgpadctrl; /* 0xAB0 */
uint32_t emmc4_pad_cfgpadctrl; /* 0xAB4 */
uint32_t emmc4_pad_drv_type_cfgpadctrl; /* 0xAB8 */
uint32_t emmc4_pad_pupd_cfgpadctrl; /* 0xABC */
uint32_t _0xAC0[0x2E];
uint32_t vgpio_gpio_mux_sel; /* 0xB74 */
uint32_t qspi_sck_lpbk_control; /* 0xB78 */
} tegra_padctl_t;
static inline volatile tegra_padctl_t *padctl_get_regs(void)
{
return (volatile tegra_padctl_t *)APB_PADCTL_BASE;
}
#endif

View File

@ -1,82 +0,0 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer
* 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 <stdint.h>
#include "btn.h"
#include "i2c.h"
#include "gpio.h"
#include "timers.h"
uint32_t btn_read()
{
uint32_t res = 0;
if (!gpio_read(GPIO_BUTTON_VOL_DOWN))
res |= BTN_VOL_DOWN;
if (!gpio_read(GPIO_BUTTON_VOL_UP))
res |= BTN_VOL_UP;
uint32_t val = 0;
if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x15, &val, 1))
{
if (val & 0x4)
res |= BTN_POWER;
}
return res;
}
uint32_t btn_wait()
{
uint32_t res = 0, btn = btn_read();
int pwr = 0;
if (btn & BTN_POWER)
{
pwr = 1;
btn &= ~BTN_POWER;
}
do
{
res = btn_read();
if (!(res & BTN_POWER) && pwr)
pwr = 0;
else if (pwr)
res &= ~BTN_POWER;
} while (btn == res);
return res;
}
uint32_t btn_wait_timeout(uint32_t time_ms, uint32_t mask)
{
uint32_t timeout = get_time_ms() + time_ms;
uint32_t res = btn_read() & mask;
do
{
if (!(res & mask))
res = btn_read() & mask;
} while (get_time_ms() < timeout);
return res;
}

View File

@ -1,30 +0,0 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer
* 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/>.
*/
#ifndef FUSEE_BTN_H_
#define FUSEE_BTN_H_
#define BTN_POWER 0x1
#define BTN_VOL_DOWN 0x2
#define BTN_VOL_UP 0x4
uint32_t btn_read();
uint32_t btn_wait();
uint32_t btn_wait_timeout(uint32_t time_ms, uint32_t mask);
#endif

View File

@ -1,142 +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 "car.h"
#include "timers.h"
#include "utils.h"
static inline uint32_t get_clk_source_reg(CarDevice dev) {
switch (dev) {
case CARDEVICE_UARTA: return 0x178;
case CARDEVICE_UARTB: return 0x17C;
case CARDEVICE_UARTC: return 0x1A0;
case CARDEVICE_I2C1: return 0x124;
case CARDEVICE_I2C5: return 0x128;
case CARDEVICE_TZRAM: return 0;
case CARDEVICE_SE: return 0x42C;
case CARDEVICE_HOST1X: return 0x180;
case CARDEVICE_TSEC: return 0x1F4;
case CARDEVICE_SOR_SAFE: return 0;
case CARDEVICE_SOR0: return 0;
case CARDEVICE_SOR1: return 0x410;
case CARDEVICE_KFUSE: return 0;
case CARDEVICE_CL_DVFS: return 0;
case CARDEVICE_CORESIGHT: return 0x1D4;
case CARDEVICE_MSELECT: return 0x3B4;
case CARDEVICE_ACTMON: return 0x3E8;
case CARDEVICE_BPMP: return 0;
default: generic_panic();
}
}
static inline uint32_t get_clk_source_val(CarDevice dev) {
switch (dev) {
case CARDEVICE_UARTA: return 0;
case CARDEVICE_UARTB: return 0;
case CARDEVICE_UARTC: return 0;
case CARDEVICE_I2C1: return 6;
case CARDEVICE_I2C5: return 6;
case CARDEVICE_TZRAM: return 0;
case CARDEVICE_SE: return 0;
case CARDEVICE_HOST1X: return 4;
case CARDEVICE_TSEC: return 0;
case CARDEVICE_SOR_SAFE: return 0;
case CARDEVICE_SOR0: return 0;
case CARDEVICE_SOR1: return 0;
case CARDEVICE_KFUSE: return 0;
case CARDEVICE_CL_DVFS: return 0;
case CARDEVICE_CORESIGHT: return 0;
case CARDEVICE_MSELECT: return 0;
case CARDEVICE_ACTMON: return 6;
case CARDEVICE_BPMP: return 0;
default: generic_panic();
}
}
static inline uint32_t get_clk_source_div(CarDevice dev) {
switch (dev) {
case CARDEVICE_UARTA: return 0;
case CARDEVICE_UARTB: return 0;
case CARDEVICE_UARTC: return 0;
case CARDEVICE_I2C1: return 0;
case CARDEVICE_I2C5: return 0;
case CARDEVICE_TZRAM: return 0;
case CARDEVICE_SE: return 0;
case CARDEVICE_HOST1X: return 3;
case CARDEVICE_TSEC: return 2;
case CARDEVICE_SOR_SAFE: return 0;
case CARDEVICE_SOR0: return 0;
case CARDEVICE_SOR1: return 2;
case CARDEVICE_KFUSE: return 0;
case CARDEVICE_CL_DVFS: return 0;
case CARDEVICE_CORESIGHT: return 4;
case CARDEVICE_MSELECT: return 6;
case CARDEVICE_ACTMON: return 0;
case CARDEVICE_BPMP: return 0;
default: generic_panic();
}
}
static uint32_t g_clk_reg_offsets[NUM_CAR_BANKS] = {0x010, 0x014, 0x018, 0x360, 0x364, 0x280, 0x298};
static uint32_t g_rst_reg_offsets[NUM_CAR_BANKS] = {0x004, 0x008, 0x00C, 0x358, 0x35C, 0x28C, 0x2A4};
void clk_enable(CarDevice dev) {
uint32_t clk_source_reg;
if ((clk_source_reg = get_clk_source_reg(dev))) {
MAKE_CAR_REG(clk_source_reg) = (get_clk_source_val(dev) << 29) | get_clk_source_div(dev);
}
MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F);
}
void clk_disable(CarDevice dev) {
MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F));
}
void rst_enable(CarDevice dev) {
MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F);
}
void rst_disable(CarDevice dev) {
MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F));
}
void clkrst_enable(CarDevice dev) {
clk_enable(dev);
rst_disable(dev);
}
void clkrst_disable(CarDevice dev) {
rst_enable(dev);
clk_disable(dev);
}
void clkrst_reboot(CarDevice dev) {
clkrst_disable(dev);
if (dev == CARDEVICE_KFUSE) {
/* Workaround for KFUSE clock. */
clk_enable(dev);
udelay(100);
rst_disable(dev);
udelay(200);
} else {
clkrst_enable(dev);
}
}
void clkrst_enable_fuse_regs(bool enable) {
volatile tegra_car_t *car = car_get_regs();
car->misc_clk_enb = ((car->misc_clk_enb & 0xEFFFFFFF) | ((enable & 1) << 28));
}

View File

@ -1,510 +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/>.
*/
#ifndef FUSEE_CAR_H
#define FUSEE_CAR_H
#include <stdint.h>
#include <stdbool.h>
#define CAR_BASE 0x60006000
#define MAKE_CAR_REG(n) MAKE_REG32(CAR_BASE + n)
#define CLK_L_SDMMC1 (1 << 14)
#define CLK_L_SDMMC2 (1 << 9)
#define CLK_U_SDMMC3 (1 << 5)
#define CLK_L_SDMMC4 (1 << 15)
#define CLK_SOURCE_MASK (0b111 << 29)
#define CLK_SOURCE_FIRST (0b000 << 29)
#define CLK_DIVIDER_MASK (0xff << 0)
#define CLK_DIVIDER_UNITY (0x00 << 0)
#define NUM_CAR_BANKS 7
/* Clock and reset devices. */
typedef enum {
CARDEVICE_BPMP = ((0 << 5) | 0x1),
CARDEVICE_UARTA = ((0 << 5) | 0x6),
CARDEVICE_UARTB = ((0 << 5) | 0x7),
CARDEVICE_I2C1 = ((0 << 5) | 0xC),
CARDEVICE_USBD = ((0 << 5) | 0x16),
CARDEVICE_HOST1X = ((0 << 5) | 0x1C),
CARDEVICE_AHBDMA = ((1 << 5) | 0x1),
CARDEVICE_APBDMA = ((1 << 5) | 0x2),
CARDEVICE_KFUSE = ((1 << 5) | 0x8),
CARDEVICE_I2C5 = ((1 << 5) | 0xF),
CARDEVICE_UARTC = ((1 << 5) | 0x17),
CARDEVICE_USB2 = ((1 << 5) | 0x1A),
CARDEVICE_CORESIGHT = ((2 << 5) | 0x9),
CARDEVICE_TSEC = ((2 << 5) | 0x13),
CARDEVICE_MSELECT = ((3 << 5) | 0x8),
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
CARDEVICE_SE = ((3 << 5) | 0x1F),
CARDEVICE_CL_DVFS = ((4 << 5) | 0x1B),
CARDEVICE_SOR0 = ((5 << 5) | 0x16),
CARDEVICE_SOR1 = ((5 << 5) | 0x17),
CARDEVICE_SOR_SAFE = ((6 << 5) | 0x1E),
} CarDevice;
/* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */
typedef struct {
uint32_t rst_src; /* _RST_SOURCE_0, 0x00 */
/* _RST_DEVICES_L/H/U_0 0x4-0xc */
uint32_t rst_dev_l;
uint32_t rst_dev_h;
uint32_t rst_dev_u;
/* _CLK_OUT_ENB_L/H/U_0 0x10-0x18 */
uint32_t clk_out_enb_l;
uint32_t clk_out_enb_h;
uint32_t clk_out_enb_u;
uint32_t _0x1C;
uint32_t cclk_brst_pol; /* _CCLK_BURST_POLICY_0, 0x20 */
uint32_t super_cclk_div; /* _SUPER_CCLK_DIVIDER_0, 0x24 */
uint32_t sclk_brst_pol; /* _SCLK_BURST_POLICY_0, 0x28 */
uint32_t super_sclk_div; /* _SUPER_SCLK_DIVIDER_0, 0x2c */
uint32_t clk_sys_rate; /* _CLK_SYSTEM_RATE_0, 0x30 */
uint32_t prog_dly_clk; /* _PROG_DLY_CLK_0, 0x34 */
uint32_t aud_sync_clk_rate; /* _AUDIO_SYNC_CLK_RATE_0, 0x38 */
uint32_t _0x3C;
uint32_t cop_clk_skip_plcy; /* _COP_CLK_SKIP_POLICY_0, 0x40 */
uint32_t clk_mask_arm; /* _CLK_MASK_ARM_0, 0x44 */
uint32_t misc_clk_enb; /* _MISC_CLK_ENB_0, 0x48 */
uint32_t clk_cpu_cmplx; /* _CLK_CPU_CMPLX_0, 0x4c */
uint32_t osc_ctrl; /* _OSC_CTRL_0, 0x50 */
uint32_t pll_lfsr; /* _PLL_LFSR_0, 0x54 */
uint32_t osc_freq_det; /* _OSC_FREQ_DET_0, 0x58 */
uint32_t osc_freq_det_stat; /* _OSC_FREQ_DET_STATUS_0, 0x5c */
uint32_t _0x60[2];
uint32_t plle_ss_cntl; /* _PLLE_SS_CNTL_0, 0x68 */
uint32_t plle_misc1; /* _PLLE_MISC1_0, 0x6c */
uint32_t _0x70[4];
/* PLLC 0x80-0x8c */
uint32_t pllc_base;
uint32_t pllc_out;
uint32_t pllc_misc0;
uint32_t pllc_misc1;
/* PLLM 0x90-0x9c */
uint32_t pllm_base;
uint32_t pllm_out;
uint32_t pllm_misc1;
uint32_t pllm_misc2;
/* PLLP 0xa0-0xac */
uint32_t pllp_base;
uint32_t pllp_outa;
uint32_t pllp_outb;
uint32_t pllp_misc;
/* PLLA 0xb0-0xbc */
uint32_t plla_base;
uint32_t plla_out;
uint32_t plla_misc0;
uint32_t plla_misc1;
/* PLLU 0xc0-0xcc */
uint32_t pllu_base;
uint32_t pllu_out;
uint32_t pllu_misc1;
uint32_t pllu_misc2;
/* PLLD 0xd0-0xdc */
uint32_t plld_base;
uint32_t plld_out;
uint32_t plld_misc1;
uint32_t plld_misc2;
/* PLLX 0xe0-0xe4 */
uint32_t pllx_base;
uint32_t pllx_misc;
/* PLLE 0xe8-0xf4 */
uint32_t plle_base;
uint32_t plle_misc;
uint32_t plle_ss_cntl1;
uint32_t plle_ss_cntl2;
uint32_t lvl2_clk_gate_ovra; /* _LVL2_CLK_GATE_OVRA_0, 0xf8 */
uint32_t lvl2_clk_gate_ovrb; /* _LVL2_CLK_GATE_OVRB_0, 0xfc */
uint32_t clk_source_i2s2; /* _CLK_SOURCE_I2S2_0, 0x100 */
uint32_t clk_source_i2s3; /* _CLK_SOURCE_I2S3_0, 0x104 */
uint32_t clk_source_spdif_out; /* _CLK_SOURCE_SPDIF_OUT_0, 0x108 */
uint32_t clk_source_spdif_in; /* _CLK_SOURCE_SPDIF_IN_0, 0x10c */
uint32_t clk_source_pwm; /* _CLK_SOURCE_PWM_0, 0x110 */
uint32_t _0x114;
uint32_t clk_source_spi2; /* _CLK_SOURCE_SPI2_0, 0x118 */
uint32_t clk_source_spi3; /* _CLK_SOURCE_SPI3_0, 0x11c */
uint32_t _0x120;
uint32_t clk_source_i2c1; /* _CLK_SOURCE_I2C1_0, 0x124 */
uint32_t clk_source_i2c5; /* _CLK_SOURCE_I2C5_0, 0x128 */
uint32_t _0x12c[2];
uint32_t clk_source_spi1; /* _CLK_SOURCE_SPI1_0, 0x134 */
uint32_t clk_source_disp1; /* _CLK_SOURCE_DISP1_0, 0x138 */
uint32_t clk_source_disp2; /* _CLK_SOURCE_DISP2_0, 0x13c */
uint32_t _0x140;
uint32_t clk_source_isp; /* _CLK_SOURCE_ISP_0, 0x144 */
uint32_t clk_source_vi; /* _CLK_SOURCE_VI_0, 0x148 */
uint32_t _0x14c;
uint32_t clk_source_sdmmc1; /* _CLK_SOURCE_SDMMC1_0, 0x150 */
uint32_t clk_source_sdmmc2; /* _CLK_SOURCE_SDMMC2_0, 0x154 */
uint32_t _0x158[3];
uint32_t clk_source_sdmmc4; /* _CLK_SOURCE_SDMMC4_0, 0x164 */
uint32_t _0x168[4];
uint32_t clk_source_uarta; /* _CLK_SOURCE_UARTA_0, 0x178 */
uint32_t clk_source_uartb; /* _CLK_SOURCE_UARTB_0, 0x17c */
uint32_t clk_source_host1x; /* _CLK_SOURCE_HOST1X_0, 0x180 */
uint32_t _0x184[5];
uint32_t clk_source_i2c2; /* _CLK_SOURCE_I2C2_0, 0x198 */
uint32_t clk_source_emc; /* _CLK_SOURCE_EMC_0, 0x19c */
uint32_t clk_source_uartc; /* _CLK_SOURCE_UARTC_0, 0x1a0 */
uint32_t _0x1a4;
uint32_t clk_source_vi_sensor; /* _CLK_SOURCE_VI_SENSOR_0, 0x1a8 */
uint32_t _0x1ac[2];
uint32_t clk_source_spi4; /* _CLK_SOURCE_SPI4_0, 0x1b4 */
uint32_t clk_source_i2c3; /* _CLK_SOURCE_I2C3_0, 0x1b8 */
uint32_t clk_source_sdmmc3; /* _CLK_SOURCE_SDMMC3_0, 0x1bc */
uint32_t clk_source_uartd; /* _CLK_SOURCE_UARTD_0, 0x1c0 */
uint32_t _0x1c4[2];
uint32_t clk_source_owr; /* _CLK_SOURCE_OWR_0, 0x1cc */
uint32_t _0x1d0;
uint32_t clk_source_csite; /* _CLK_SOURCE_CSITE_0, 0x1d4 */
uint32_t clk_source_i2s1; /* _CLK_SOURCE_I2S1_0, 0x1d8 */
uint32_t clk_source_dtv; /* _CLK_SOURCE_DTV_0, 0x1dc */
uint32_t _0x1e0[5];
uint32_t clk_source_tsec; /* _CLK_SOURCE_TSEC_0, 0x1f4 */
uint32_t _0x1f8;
uint32_t clk_spare2; /* _CLK_SPARE2_0, 0x1fc */
uint32_t _0x200[32];
uint32_t clk_out_enb_x; /* _CLK_OUT_ENB_X_0, 0x280 */
uint32_t clk_enb_x_set; /* _CLK_ENB_X_SET_0, 0x284 */
uint32_t clk_enb_x_clr; /* _CLK_ENB_X_CLR_0, 0x288 */
uint32_t rst_devices_x; /* _RST_DEVICES_X_0, 0x28c */
uint32_t rst_dev_x_set; /* _RST_DEV_X_SET_0, 0x290 */
uint32_t rst_dev_x_clr; /* _RST_DEV_X_CLR_0, 0x294 */
uint32_t clk_out_enb_y; /* _CLK_OUT_ENB_Y_0, 0x298 */
uint32_t clk_enb_y_set; /* _CLK_ENB_Y_SET_0, 0x29c */
uint32_t clk_enb_y_clr; /* _CLK_ENB_Y_CLR_0, 0x2a0 */
uint32_t rst_devices_y; /* _RST_DEVICES_Y_0, 0x2a4 */
uint32_t rst_dev_y_set; /* _RST_DEV_Y_SET_0, 0x2a8 */
uint32_t rst_dev_y_clr; /* _RST_DEV_Y_CLR_0, 0x2ac */
uint32_t _0x2b0[17];
uint32_t dfll_base; /* _DFLL_BASE_0, 0x2f4 */
uint32_t _0x2f8[2];
/* _RST_DEV_L/H/U_SET_0 0x300-0x314 */
uint32_t rst_dev_l_set;
uint32_t rst_dev_l_clr;
uint32_t rst_dev_h_set;
uint32_t rst_dev_h_clr;
uint32_t rst_dev_u_set;
uint32_t rst_dev_u_clr;
uint32_t _0x318[2];
/* _CLK_ENB_L/H/U_CLR_0 0x320-0x334 */
uint32_t clk_enb_l_set;
uint32_t clk_enb_l_clr;
uint32_t clk_enb_h_set;
uint32_t clk_enb_h_clr;
uint32_t clk_enb_u_set;
uint32_t clk_enb_u_clr;
uint32_t _0x338;
uint32_t ccplex_pg_sm_ovrd; /* _CCPLEX_PG_SM_OVRD_0, 0x33c */
uint32_t rst_cpu_cmplx_set; /* _RST_CPU_CMPLX_SET_0, 0x340 */
uint32_t rst_cpu_cmplx_clr; /* _RST_CPU_CMPLX_CLR_0, 0x344 */
/* Additional (T30) registers */
uint32_t clk_cpu_cmplx_set; /* _CLK_CPU_CMPLX_SET_0, 0x348 */
uint32_t clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET_0, 0x34c */
uint32_t _0x350[2];
uint32_t rst_dev_v; /* _RST_DEVICES_V_0, 0x358 */
uint32_t rst_dev_w; /* _RST_DEVICES_W_0, 0x35c */
uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V_0, 0x360 */
uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_W_0, 0x364 */
uint32_t cclkg_brst_pol; /* _CCLKG_BURST_POLICY_0, 0x368 */
uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36c */
uint32_t cclklp_brst_pol; /* _CCLKLP_BURST_POLICY_0, 0x370 */
uint32_t super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER_0, 0x374 */
uint32_t clk_cpug_cmplx; /* _CLK_CPUG_CMPLX_0, 0x378 */
uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37c */
uint32_t cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL_0, 0x380 */
uint32_t cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1_0, 0x384 */
uint32_t cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2_0, 0x388 */
uint32_t _0x38c[5];
uint32_t lvl2_clk_gate_ovrc; /* _LVL2_CLK_GATE_OVRC, 0x3a0 */
uint32_t lvl2_clk_gate_ovrd; /* _LVL2_CLK_GATE_OVRD, 0x3a4 */
uint32_t _0x3a8[2];
uint32_t _0x3b0;
uint32_t clk_source_mselect; /* _CLK_SOURCE_MSELECT_0, 0x3b4 */
uint32_t clk_source_tsensor; /* _CLK_SOURCE_TSENSOR_0, 0x3b8 */
uint32_t clk_source_i2s4; /* _CLK_SOURCE_I2S4_0, 0x3bc */
uint32_t clk_source_i2s5; /* _CLK_SOURCE_I2S5_0, 0x3c0 */
uint32_t clk_source_i2c4; /* _CLK_SOURCE_I2C4_0, 0x3c4 */
uint32_t _0x3c8[2];
uint32_t clk_source_ahub; /* _CLK_SOURCE_AHUB_0, 0x3d0 */
uint32_t _0x3d4[4];
uint32_t clk_source_hda2codec_2x; /* _CLK_SOURCE_HDA2CODEC_2X_0, 0x3e4 */
uint32_t clk_source_actmon; /* _CLK_SOURCE_ACTMON_0, 0x3e8 */
uint32_t clk_source_extperiph1; /* _CLK_SOURCE_EXTPERIPH1_0, 0x3ec */
uint32_t clk_source_extperiph2; /* _CLK_SOURCE_EXTPERIPH2_0, 0x3f0 */
uint32_t clk_source_extperiph3; /* _CLK_SOURCE_EXTPERIPH3_0, 0x3f4 */
uint32_t _0x3f8;
uint32_t clk_source_i2c_slow; /* _CLK_SOURCE_I2C_SLOW_0, 0x3fc */
uint32_t clk_source_sys; /* _CLK_SOURCE_SYS_0, 0x400 */
uint32_t clk_source_ispb; /* _CLK_SOURCE_ISPB_0, 0x404 */
uint32_t _0x408[2];
uint32_t clk_source_sor1; /* _CLK_SOURCE_SOR1_0, 0x410 */
uint32_t clk_source_sor0; /* _CLK_SOURCE_SOR0_0, 0x414 */
uint32_t _0x418[2];
uint32_t clk_source_sata_oob; /* _CLK_SOURCE_SATA_OOB_0, 0x420 */
uint32_t clk_source_sata; /* _CLK_SOURCE_SATA_0, 0x424 */
uint32_t clk_source_hda; /* _CLK_SOURCE_HDA_0, 0x428 */
uint32_t clk_source_se; /* _CLK_SOURCE_SE_0, 0x42c */
/* _RST_DEV_V/W_SET_0 0x430-0x43c */
uint32_t rst_dev_v_set;
uint32_t rst_dev_v_clr;
uint32_t rst_dev_w_set;
uint32_t rst_dev_w_clr;
/* _CLK_ENB_V/W_CLR_0 0x440-0x44c */
uint32_t clk_enb_v_set;
uint32_t clk_enb_v_clr;
uint32_t clk_enb_w_set;
uint32_t clk_enb_w_clr;
/* Additional (T114+) registers */
uint32_t rst_cpug_cmplx_set; /* _RST_CPUG_CMPLX_SET_0, 0x450 */
uint32_t rst_cpug_cmplx_clr; /* _RST_CPUG_CMPLX_CLR_0, 0x454 */
uint32_t rst_cpulp_cmplx_set; /* _RST_CPULP_CMPLX_SET_0, 0x458 */
uint32_t rst_cpulp_cmplx_clr; /* _RST_CPULP_CMPLX_CLR_0, 0x45c */
uint32_t clk_cpug_cmplx_set; /* _CLK_CPUG_CMPLX_SET_0, 0x460 */
uint32_t clk_cpug_cmplx_clr; /* _CLK_CPUG_CMPLX_CLR_0, 0x464 */
uint32_t clk_cpulp_cmplx_set; /* _CLK_CPULP_CMPLX_SET_0, 0x468 */
uint32_t clk_cpulp_cmplx_clr; /* _CLK_CPULP_CMPLX_CLR_0, 0x46c */
uint32_t cpu_cmplx_status; /* _CPU_CMPLX_STATUS_0, 0x470 */
uint32_t _0x474;
uint32_t intstatus; /* _INTSTATUS_0, 0x478 */
uint32_t intmask; /* _INTMASK_0, 0x47c */
uint32_t utmip_pll_cfg0; /* _UTMIP_PLL_CFG0_0, 0x480 */
uint32_t utmip_pll_cfg1; /* _UTMIP_PLL_CFG1_0, 0x484 */
uint32_t utmip_pll_cfg2; /* _UTMIP_PLL_CFG2_0, 0x488 */
uint32_t plle_aux; /* _PLLE_AUX_0, 0x48c */
uint32_t sata_pll_cfg0; /* _SATA_PLL_CFG0_0, 0x490 */
uint32_t sata_pll_cfg1; /* _SATA_PLL_CFG1_0, 0x494 */
uint32_t pcie_pll_cfg0; /* _PCIE_PLL_CFG0_0, 0x498 */
uint32_t prog_audio_dly_clk; /* _PROG_AUDIO_DLY_CLK_0, 0x49c */
uint32_t audio_sync_clk_i2s0; /* _AUDIO_SYNC_CLK_I2S0_0, 0x4a0 */
uint32_t audio_sync_clk_i2s1; /* _AUDIO_SYNC_CLK_I2S1_0, 0x4a4 */
uint32_t audio_sync_clk_i2s2; /* _AUDIO_SYNC_CLK_I2S2_0, 0x4a8 */
uint32_t audio_sync_clk_i2s3; /* _AUDIO_SYNC_CLK_I2S3_0, 0x4ac */
uint32_t audio_sync_clk_i2s4; /* _AUDIO_SYNC_CLK_I2S4_0, 0x4b0 */
uint32_t audio_sync_clk_spdif; /* _AUDIO_SYNC_CLK_SPDIF_0, 0x4b4 */
uint32_t plld2_base; /* _PLLD2_BASE_0, 0x4b8 */
uint32_t plld2_misc; /* _PLLD2_MISC_0, 0x4bc */
uint32_t utmip_pll_cfg3; /* _UTMIP_PLL_CFG3_0, 0x4c0 */
uint32_t pllrefe_base; /* _PLLREFE_BASE_0, 0x4c4 */
uint32_t pllrefe_misc; /* _PLLREFE_MISC_0, 0x4c8 */
uint32_t pllrefe_out; /* _PLLREFE_OUT_0, 0x4cc */
uint32_t cpu_finetrim_byp; /* _CPU_FINETRIM_BYP_0, 0x4d0 */
uint32_t cpu_finetrim_select; /* _CPU_FINETRIM_SELECT_0, 0x4d4 */
uint32_t cpu_finetrim_dr; /* _CPU_FINETRIM_DR_0, 0x4d8 */
uint32_t cpu_finetrim_df; /* _CPU_FINETRIM_DF_0, 0x4dc */
uint32_t cpu_finetrim_f; /* _CPU_FINETRIM_F_0, 0x4e0 */
uint32_t cpu_finetrim_r; /* _CPU_FINETRIM_R_0, 0x4e4 */
uint32_t pllc2_base; /* _PLLC2_BASE_0, 0x4e8 */
uint32_t pllc2_misc0; /* _PLLC2_MISC_0_0, 0x4ec */
uint32_t pllc2_misc1; /* _PLLC2_MISC_1_0, 0x4f0 */
uint32_t pllc2_misc2; /* _PLLC2_MISC_2_0, 0x4f4 */
uint32_t pllc2_misc3; /* _PLLC2_MISC_3_0, 0x4f8 */
uint32_t pllc3_base; /* _PLLC3_BASE_0, 0x4fc */
uint32_t pllc3_misc0; /* _PLLC3_MISC_0_0, 0x500 */
uint32_t pllc3_misc1; /* _PLLC3_MISC_1_0, 0x504 */
uint32_t pllc3_misc2; /* _PLLC3_MISC_2_0, 0x508 */
uint32_t pllc3_misc3; /* _PLLC3_MISC_3_0, 0x50c */
uint32_t pllx_misc1; /* _PLLX_MISC_1_0, 0x510 */
uint32_t pllx_misc2; /* _PLLX_MISC_2_0, 0x514 */
uint32_t pllx_misc3; /* _PLLX_MISC_3_0, 0x518 */
uint32_t xusbio_pll_cfg0; /* _XUSBIO_PLL_CFG0_0, 0x51c */
uint32_t xusbio_pll_cfg1; /* _XUSBIO_PLL_CFG0_1, 0x520 */
uint32_t plle_aux1; /* _PLLE_AUX1_0, 0x524 */
uint32_t pllp_reshift; /* _PLLP_RESHIFT_0, 0x528 */
uint32_t utmipll_hw_pwrdn_cfg0; /* _UTMIPLL_HW_PWRDN_CFG0_0, 0x52c */
uint32_t pllu_hw_pwrdn_cfg0; /* _PLLU_HW_PWRDN_CFG0_0, 0x530 */
uint32_t xusb_pll_cfg0; /* _XUSB_PLL_CFG0_0, 0x534 */
uint32_t _0x538;
uint32_t clk_cpu_misc; /* _CLK_CPU_MISC_0, 0x53c */
uint32_t clk_cpug_misc; /* _CLK_CPUG_MISC_0, 0x540 */
uint32_t clk_cpulp_misc; /* _CLK_CPULP_MISC_0, 0x544 */
uint32_t pllx_hw_ctrl_cfg; /* _PLLX_HW_CTRL_CFG_0, 0x548 */
uint32_t pllx_sw_ramp_cfg; /* _PLLX_SW_RAMP_CFG_0, 0x54c */
uint32_t pllx_hw_ctrl_status; /* _PLLX_HW_CTRL_STATUS_0, 0x550 */
uint32_t lvl2_clk_gate_ovre; /* _LVL2_CLK_GATE_OVRE, 0x554 */
uint32_t super_gr3d_clk_div; /* _SUPER_GR3D_CLK_DIVIDER_0, 0x558 */
uint32_t spare_reg0; /* _SPARE_REG0_0, 0x55c */
uint32_t audio_sync_clk_dmic1; /* _AUDIO_SYNC_CLK_DMIC1_0, 0x560 */
uint32_t audio_sync_clk_dmic2; /* _AUDIO_SYNC_CLK_DMIC2_0, 0x564 */
uint32_t _0x568[2];
uint32_t plld2_ss_cfg; /* _PLLD2_SS_CFG, 0x570 */
uint32_t plld2_ss_ctrl1; /* _PLLD2_SS_CTRL1_0, 0x574 */
uint32_t plld2_ss_ctrl2; /* _PLLD2_SS_CTRL2_0, 0x578 */
uint32_t _0x57c[5];
uint32_t plldp_base; /* _PLLDP_BASE, 0x590*/
uint32_t plldp_misc; /* _PLLDP_MISC, 0x594 */
uint32_t plldp_ss_cfg; /* _PLLDP_SS_CFG, 0x598 */
uint32_t plldp_ss_ctrl1; /* _PLLDP_SS_CTRL1_0, 0x59c */
uint32_t plldp_ss_ctrl2; /* _PLLDP_SS_CTRL2_0, 0x5a0 */
uint32_t pllc4_base; /* _PLLC4_BASE_0, 0x5a4 */
uint32_t pllc4_misc; /* _PLLC4_MISC_0, 0x5a8 */
uint32_t _0x5ac[6];
uint32_t clk_spare0; /* _CLK_SPARE0_0, 0x5c4 */
uint32_t clk_spare1; /* _CLK_SPARE1_0, 0x5c8 */
uint32_t gpu_isob_ctrl; /* _GPU_ISOB_CTRL_0, 0x5cc */
uint32_t pllc_misc2; /* _PLLC_MISC_2_0, 0x5d0 */
uint32_t pllc_misc3; /* _PLLC_MISC_3_0, 0x5d4 */
uint32_t plla_misc2; /* _PLLA_MISC2_0, 0x5d8 */
uint32_t _0x5dc[2];
uint32_t pllc4_out; /* _PLLC4_OUT_0, 0x5e4 */
uint32_t pllmb_base; /* _PLLMB_BASE_0, 0x5e8 */
uint32_t pllmb_misc1; /* _PLLMB_MISC1_0, 0x5ec */
uint32_t pllx_misc4; /* _PLLX_MISC_4_0, 0x5f0 */
uint32_t pllx_misc5; /* _PLLX_MISC_5_0, 0x5f4 */
uint32_t _0x5f8[2];
uint32_t clk_source_xusb_core_host; /* _CLK_SOURCE_XUSB_CORE_HOST_0, 0x600 */
uint32_t clk_source_xusb_falcon; /* _CLK_SOURCE_XUSB_FALCON_0, 0x604 */
uint32_t clk_source_xusb_fs; /* _CLK_SOURCE_XUSB_FS_0, 0x608 */
uint32_t clk_source_xusb_core_dev; /* _CLK_SOURCE_XUSB_CORE_DEV_0, 0x60c */
uint32_t clk_source_xusb_ss; /* _CLK_SOURCE_XUSB_SS_0, 0x610 */
uint32_t clk_source_cilab; /* _CLK_SOURCE_CILAB_0, 0x614 */
uint32_t clk_source_cilcd; /* _CLK_SOURCE_CILCD_0, 0x618 */
uint32_t clk_source_cilef; /* _CLK_SOURCE_CILEF_0, 0x61c */
uint32_t clk_source_dsia_lp; /* _CLK_SOURCE_DSIA_LP_0, 0x620 */
uint32_t clk_source_dsib_lp; /* _CLK_SOURCE_DSIB_LP_0, 0x624 */
uint32_t clk_source_entropy; /* _CLK_SOURCE_ENTROPY_0, 0x628 */
uint32_t clk_source_dvfs_ref; /* _CLK_SOURCE_DVFS_REF_0, 0x62c */
uint32_t clk_source_dvfs_soc; /* _CLK_SOURCE_DVFS_SOC_0, 0x630 */
uint32_t _0x634[3];
uint32_t clk_source_emc_latency; /* _CLK_SOURCE_EMC_LATENCY_0, 0x640 */
uint32_t clk_source_soc_therm; /* _CLK_SOURCE_SOC_THERM_0, 0x644 */
uint32_t _0x648;
uint32_t clk_source_dmic1; /* _CLK_SOURCE_DMIC1_0, 0x64c */
uint32_t clk_source_dmic2; /* _CLK_SOURCE_DMIC2_0, 0x650 */
uint32_t _0x654;
uint32_t clk_source_vi_sensor2; /* _CLK_SOURCE_VI_SENSOR2_0, 0x658 */
uint32_t clk_source_i2c6; /* _CLK_SOURCE_I2C6_0, 0x65c */
uint32_t clk_source_mipibif; /* _CLK_SOURCE_MIPIBIF_0, 0x660 */
uint32_t clk_source_emc_dll; /* _CLK_SOURCE_EMC_DLL_0, 0x664 */
uint32_t _0x668;
uint32_t clk_source_uart_fst_mipi_cal; /* _CLK_SOURCE_UART_FST_MIPI_CAL_0, 0x66c */
uint32_t _0x670[2];
uint32_t clk_source_vic; /* _CLK_SOURCE_VIC_0, 0x678 */
uint32_t pllp_outc; /* _PLLP_OUTC_0, 0x67c */
uint32_t pllp_misc1; /* _PLLP_MISC1_0, 0x680 */
uint32_t _0x684[2];
uint32_t emc_div_clk_shaper_ctrl; /* _EMC_DIV_CLK_SHAPER_CTRL_0, 0x68c */
uint32_t emc_pllc_shaper_ctrl; /* _EMC_PLLC_SHAPER_CTRL_0, 0x690 */
uint32_t clk_source_sdmmc_legacy_tm; /* _CLK_SOURCE_SDMMC_LEGACY_TM_0, 0x694 */
uint32_t clk_source_nvdec; /* _CLK_SOURCE_NVDEC_0, 0x698 */
uint32_t clk_source_nvjpg; /* _CLK_SOURCE_NVJPG_0, 0x69c */
uint32_t clk_source_nvenc; /* _CLK_SOURCE_NVENC_0, 0x6a0 */
uint32_t plla1_base; /* _PLLA1_BASE_0, 0x6a4 */
uint32_t plla1_misc0; /* _PLLA1_MISC_0_0, 0x6a8 */
uint32_t plla1_misc1; /* _PLLA1_MISC_1_0, 0x6ac */
uint32_t plla1_misc2; /* _PLLA1_MISC_2_0, 0x6b0 */
uint32_t plla1_misc3; /* _PLLA1_MISC_3_0, 0x6b4 */
uint32_t audio_sync_clk_dmic3; /* _AUDIO_SYNC_CLK_DMIC3_0, 0x6b8 */
uint32_t clk_source_dmic3; /* _CLK_SOURCE_DMIC3_0, 0x6bc */
uint32_t clk_source_ape; /* _CLK_SOURCE_APE_0, 0x6c0 */
uint32_t clk_source_qspi; /* _CLK_SOURCE_QSPI_0, 0x6c4 */
uint32_t clk_source_vi_i2c; /* _CLK_SOURCE_VI_I2C_0, 0x6c8 */
uint32_t clk_source_usb2_hsic_trk; /* _CLK_SOURCE_USB2_HSIC_TRK_0, 0x6cc */
uint32_t clk_source_pex_sata_usb_rx_byp; /* _CLK_SOURCE_PEX_SATA_USB_RX_BYP_0, 0x6d0 */
uint32_t clk_source_maud; /* _CLK_SOURCE_MAUD_0, 0x6d4 */
uint32_t clk_source_tsecb; /* _CLK_SOURCE_TSECB_0, 0x6d8 */
uint32_t clk_cpug_misc1; /* _CLK_CPUG_MISC1_0, 0x6dc */
uint32_t aclk_burst_policy; /* _ACLK_BURST_POLICY_0, 0x6e0 */
uint32_t super_aclk_divider; /* _SUPER_ACLK_DIVIDER_0, 0x6e4 */
uint32_t nvenc_super_clk_divider; /* _NVENC_SUPER_CLK_DIVIDER_0, 0x6e8 */
uint32_t vi_super_clk_divider; /* _VI_SUPER_CLK_DIVIDER_0, 0x6ec */
uint32_t vic_super_clk_divider; /* _VIC_SUPER_CLK_DIVIDER_0, 0x6f0 */
uint32_t nvdec_super_clk_divider; /* _NVDEC_SUPER_CLK_DIVIDER_0, 0x6f4 */
uint32_t isp_super_clk_divider; /* _ISP_SUPER_CLK_DIVIDER_0, 0x6f8 */
uint32_t ispb_super_clk_divider; /* _ISPB_SUPER_CLK_DIVIDER_0, 0x6fc */
uint32_t nvjpg_super_clk_divider; /* _NVJPG_SUPER_CLK_DIVIDER_0, 0x700 */
uint32_t se_super_clk_divider; /* _SE_SUPER_CLK_DIVIDER_0, 0x704 */
uint32_t tsec_super_clk_divider; /* _TSEC_SUPER_CLK_DIVIDER_0, 0x708 */
uint32_t tsecb_super_clk_divider; /* _TSECB_SUPER_CLK_DIVIDER_0, 0x70c */
uint32_t clk_source_uartape; /* _CLK_SOURCE_UARTAPE_0, 0x710 */
uint32_t clk_cpug_misc2; /* _CLK_CPUG_MISC2_0, 0x714 */
uint32_t clk_source_dbgapb; /* _CLK_SOURCE_DBGAPB_0, 0x718 */
uint32_t clk_ccplex_cc4_ret_clk_enb; /* _CLK_CCPLEX_CC4_RET_CLK_ENB_0, 0x71c */
uint32_t actmon_cpu_clk; /* _ACTMON_CPU_CLK_0, 0x720 */
uint32_t clk_source_emc_safe; /* _CLK_SOURCE_EMC_SAFE_0, 0x724 */
uint32_t sdmmc2_pllc4_out0_shaper_ctrl; /* _SDMMC2_PLLC4_OUT0_SHAPER_CTRL_0, 0x728 */
uint32_t sdmmc2_pllc4_out1_shaper_ctrl; /* _SDMMC2_PLLC4_OUT1_SHAPER_CTRL_0, 0x72c */
uint32_t sdmmc2_pllc4_out2_shaper_ctrl; /* _SDMMC2_PLLC4_OUT2_SHAPER_CTRL_0, 0x730 */
uint32_t sdmmc2_div_clk_shaper_ctrl; /* _SDMMC2_DIV_CLK_SHAPER_CTRL_0, 0x734 */
uint32_t sdmmc4_pllc4_out0_shaper_ctrl; /* _SDMMC4_PLLC4_OUT0_SHAPER_CTRL_0, 0x738 */
uint32_t sdmmc4_pllc4_out1_shaper_ctrl; /* _SDMMC4_PLLC4_OUT1_SHAPER_CTRL_0, 0x73c */
uint32_t sdmmc4_pllc4_out2_shaper_ctrl; /* _SDMMC4_PLLC4_OUT2_SHAPER_CTRL_0, 0x740 */
uint32_t sdmmc4_div_clk_shaper_ctrl; /* _SDMMC4_DIV_CLK_SHAPER_CTRL_0, 0x744 */
} tegra_car_t;
static inline volatile tegra_car_t *car_get_regs(void) {
return (volatile tegra_car_t *)CAR_BASE;
}
void clk_enable(CarDevice dev);
void clk_disable(CarDevice dev);
void rst_enable(CarDevice dev);
void rst_disable(CarDevice dev);
void clkrst_enable(CarDevice dev);
void clkrst_disable(CarDevice dev);
void clkrst_reboot(CarDevice dev);
void clkrst_enable_fuse_regs(bool enable);
#endif

View File

@ -1,51 +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 "chainloader.h"
int g_chainloader_argc = 0;
char g_chainloader_arg_data[CHAINLOADER_ARG_DATA_MAX_SIZE] = {0};
chainloader_entry_t g_chainloader_entries[CHAINLOADER_MAX_ENTRIES] = {0}; /* keep them sorted */
size_t g_chainloader_num_entries = 0;
uintptr_t g_chainloader_entrypoint = 0;
#pragma GCC optimize (3)
static void *xmemmove(void *dst, const void *src, size_t len)
{
const uint8_t *src8 = (const uint8_t *)src;
uint8_t *dst8 = (uint8_t *)dst;
if (dst8 < src8) {
for (size_t i = 0; i < len; i++) {
dst8[i] = src8[i];
}
} else if (dst8 > src8) {
for (size_t i = len; len > 0; len--)
dst8[i - 1] = src8[i - 1];
}
return dst;
}
void relocate_and_chainload_main(void) {
for(size_t i = 0; i < g_chainloader_num_entries; i++) {
chainloader_entry_t *entry = &g_chainloader_entries[i];
xmemmove((void *)entry->load_address, (const void *)entry->src_address, entry->size);
}
((void (*)(int, void *))g_chainloader_entrypoint)(g_chainloader_argc, g_chainloader_arg_data);
}

View File

@ -1,42 +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/>.
*/
#ifndef FUSEE_CHAINLOADER_H
#define FUSEE_CHAINLOADER_H
#include <stddef.h>
#include <stdint.h>
#define CHAINLOADER_ARG_DATA_MAX_SIZE 0x5400
#define CHAINLOADER_MAX_ENTRIES 128
typedef struct chainloader_entry_t {
uintptr_t load_address;
uintptr_t src_address;
size_t size;
size_t num;
} chainloader_entry_t;
extern int g_chainloader_argc;
extern chainloader_entry_t g_chainloader_entries[CHAINLOADER_MAX_ENTRIES]; /* keep them sorted */
extern size_t g_chainloader_num_entries;
extern uintptr_t g_chainloader_entrypoint;
extern char g_chainloader_arg_data[CHAINLOADER_ARG_DATA_MAX_SIZE];
void relocate_and_chainload(void);
#endif

View File

@ -1,178 +0,0 @@
/*
* Copyright (c) 2018 naehrwert
* 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 <stdint.h>
#include "cluster.h"
#include "flow.h"
#include "sysreg.h"
#include "i2c.h"
#include "car.h"
#include "mc.h"
#include "timers.h"
#include "pmc.h"
#include "max77620.h"
void _cluster_enable_power()
{
/* Reboot I2C5. */
clkrst_reboot(CARDEVICE_I2C5);
i2c_init(I2C_5);
uint8_t val = 0;
i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_AME_GPIO, &val, 1);
val &= 0xDF;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_AME_GPIO, &val, 1);
val = 0x09;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_GPIO5, &val, 1);
/* Enable power. */
val = 0x20;
i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x02, &val, 1);
val = 0x8D;
i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x03, &val, 1);
val = 0xB7;
i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x00, &val, 1);
val = 0xB7;
i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x01, &val, 1);
}
int _cluster_pmc_enable_partition(uint32_t part, uint32_t toggle)
{
volatile tegra_pmc_t *pmc = pmc_get_regs();
/* Check if the partition has already been turned on. */
if (pmc->pwrgate_status & part)
return 1;
uint32_t i = 5001;
while (pmc->pwrgate_toggle & 0x100)
{
udelay(1);
i--;
if (i < 1)
return 0;
}
pmc->pwrgate_toggle = (toggle | 0x100);
i = 5001;
while (i > 0)
{
if (pmc->pwrgate_status & part)
break;
udelay(1);
i--;
}
return 1;
}
void cluster_boot_cpu0(uint32_t entry)
{
volatile tegra_car_t *car = car_get_regs();
/* Set ACTIVE_CLUSER to FAST. */
FLOW_CTLR_BPMP_CLUSTER_CONTROL_0 &= 0xFFFFFFFE;
_cluster_enable_power();
if (!(car->pllx_base & 0x40000000))
{
car->pllx_misc3 &= 0xFFFFFFF7;
udelay(2);
car->pllx_base = 0x80404E02;
car->pllx_base = 0x404E02;
car->pllx_misc = ((car->pllx_misc & 0xFFFBFFFF) | 0x40000);
car->pllx_base = 0x40404E02;
}
while (!(car->pllx_base & 0x8000000)) {
/* Wait. */
}
/* Configure MSELECT source and enable clock. */
car->clk_source_mselect = ((car->clk_source_mselect & 0x1FFFFF00) | 6);
car->clk_out_enb_v = ((car->clk_out_enb_v & 0xFFFFFFF7) | 8);
/* Configure initial CPU clock frequency and enable clock. */
car->cclk_brst_pol = 0x20008888;
car->super_cclk_div = 0x80000000;
car->clk_enb_v_set = 1;
clkrst_reboot(CARDEVICE_CORESIGHT);
/* CAR2PMC_CPU_ACK_WIDTH should be set to 0. */
car->cpu_softrst_ctrl2 &= 0xFFFFF000;
/* Enable CPU rail. */
_cluster_pmc_enable_partition(1, 0);
/* Enable cluster 0 non-CPU. */
_cluster_pmc_enable_partition(0x8000, 15);
/* Enable CE0. */
_cluster_pmc_enable_partition(0x4000, 14);
/* Request and wait for RAM repair. */
FLOW_CTLR_RAM_REPAIR_0 = 1;
while (!(FLOW_CTLR_RAM_REPAIR_0 & 2)) {
/* Wait. */
}
MAKE_EXCP_VEC_REG(0x100) = 0;
/* Check for reset vector lock. */
if (SB_CSR_0 & 2) {
generic_panic();
}
/* Set reset vector. */
SB_AA64_RESET_LOW_0 = (entry | 1);
SB_AA64_RESET_HIGH_0 = 0;
/* Non-secure reset vector write disable. */
SB_CSR_0 = 2;
(void)SB_CSR_0;
/* Validate reset vector lock + RESET_LOW/HIGH values. */
if (!(SB_CSR_0 & 2)) {
generic_panic();
}
/* TODO: Should we even bother taking as a parameter? */
if (SB_AA64_RESET_LOW_0 != (0x4003D000 | 1) || SB_AA64_RESET_HIGH_0 != 0) {
generic_panic();
}
/* Set CPU_STRICT_TZ_APERTURE_CHECK. */
/* NOTE: [4.0.0+] This was added, but it breaks Exosphère. */
/* MAKE_MC_REG(MC_TZ_SECURITY_CTRL) = 1; */
/* Clear MSELECT reset. */
car->rst_dev_v &= 0xFFFFFFF7;
/* Clear NONCPU reset. */
car->rst_cpug_cmplx_clr = 0x20000000;
/* Clear CPU{0,1,2,3} POR and CORE, CX0, L2, and DBG reset.*/
/* NOTE: [5.0.0+] This was changed so only CPU0 reset is cleared. */
/* car->rst_cpug_cmplx_clr = 0x411F000F; */
car->rst_cpug_cmplx_clr = 0x41010001;
}

View File

@ -1,23 +0,0 @@
/*
* Copyright (c) 2018 naehrwert
* 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/>.
*/
#ifndef FUSEE_CLUSTER_H_
#define FUSEE_CLUSTER_H_
void cluster_boot_cpu0(uint32_t entry);
#endif

View File

@ -1,465 +0,0 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer
* 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 <string.h>
#include "di.h"
#include "fuse.h"
#include "timers.h"
#include "i2c.h"
#include "pmc.h"
#include "max77620.h"
#include "gpio.h"
#include "pinmux.h"
#include "car.h"
#include "apb_misc.h"
#include "di.inl"
static uint32_t g_lcd_vendor = 0;
/* Determine the current SoC for Mariko specific code. */
static bool is_soc_mariko() {
return (fuse_get_soc_type() == 1);
}
static void do_dsi_sleep_or_register_writes(const dsi_sleep_or_register_write_t *writes, uint32_t num_writes) {
for (uint32_t i = 0; i < num_writes; i++) {
if (writes[i].kind == 1) {
udelay(1000 * writes[i].offset);
} else {
*(volatile uint32_t *)(DSI_BASE + sizeof(uint32_t) * writes[i].offset) = writes[i].value;
}
}
}
static void do_register_writes(uint32_t base_address, const register_write_t *writes, uint32_t num_writes) {
for (uint32_t i = 0; i < num_writes; i++) {
*(volatile uint32_t *)(base_address + writes[i].offset) = writes[i].value;
}
}
static void dsi_wait(uint32_t timeout, uint32_t offset, uint32_t mask, uint32_t delay) {
uint32_t end = get_time_us() + timeout;
while ((get_time_us() < end) && (MAKE_DSI_REG(offset) & mask)) {
/* Wait. */
}
udelay(delay);
}
void display_init(void) {
volatile tegra_car_t *car = car_get_regs();
volatile tegra_pmc_t *pmc = pmc_get_regs();
volatile tegra_pinmux_t *pinmux = pinmux_get_regs();
bool is_mariko = is_soc_mariko();
uint32_t hardware_type = fuse_get_hardware_type();
/* Power on. */
if (is_mariko) {
uint8_t val = 0x3A;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_SD2, &val, 1);
val = 0x71;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_SD2_CFG, &val, 1);
val = 0xD0;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_LDO0_CFG, &val, 1);
} else {
uint8_t val = 0xD0;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_LDO0_CFG, &val, 1);
}
/* Enable MIPI CAL, DSI, DISP1, HOST1X, UART_FST_MIPI_CAL, DSIA LP clocks. */
car->rst_dev_h_clr = 0x1010000;
car->clk_enb_h_set = 0x1010000;
car->rst_dev_l_clr = 0x18000000;
car->clk_enb_l_set = 0x18000000;
car->clk_enb_x_set = 0x20000;
car->clk_source_uart_fst_mipi_cal = 0xA;
car->clk_enb_w_set = 0x80000;
car->clk_source_dsia_lp = 0xA;
/* DPD idle. */
pmc->io_dpd_req = 0x40000000;
pmc->io_dpd2_req = 0x40000000;
/* Configure pins. */
pinmux->nfc_en &= ~PINMUX_TRISTATE;
pinmux->nfc_int &= ~PINMUX_TRISTATE;
pinmux->lcd_bl_pwm &= ~PINMUX_TRISTATE;
pinmux->lcd_bl_en &= ~PINMUX_TRISTATE;
pinmux->lcd_rst &= ~PINMUX_TRISTATE;
if (is_mariko && (hardware_type == 5)) {
/* HardwareType_Five only configures GPIO_LCD_BL_RST. */
gpio_configure_mode(GPIO_LCD_BL_RST, GPIO_MODE_GPIO);
gpio_configure_direction(GPIO_LCD_BL_RST, GPIO_DIRECTION_OUTPUT);
} else {
/* Configure Backlight +-5V GPIOs. */
gpio_configure_mode(GPIO_LCD_BL_P5V, GPIO_MODE_GPIO);
gpio_configure_mode(GPIO_LCD_BL_N5V, GPIO_MODE_GPIO);
gpio_configure_direction(GPIO_LCD_BL_P5V, GPIO_DIRECTION_OUTPUT);
gpio_configure_direction(GPIO_LCD_BL_N5V, GPIO_DIRECTION_OUTPUT);
/* Enable Backlight +5V. */
gpio_write(GPIO_LCD_BL_P5V, GPIO_LEVEL_HIGH);
udelay(10000);
/* Enable Backlight -5V. */
gpio_write(GPIO_LCD_BL_N5V, GPIO_LEVEL_HIGH);
udelay(10000);
/* Configure Backlight PWM, EN and RST GPIOs. */
gpio_configure_mode(GPIO_LCD_BL_PWM, GPIO_MODE_GPIO);
gpio_configure_mode(GPIO_LCD_BL_EN, GPIO_MODE_GPIO);
gpio_configure_mode(GPIO_LCD_BL_RST, GPIO_MODE_GPIO);
gpio_configure_direction(GPIO_LCD_BL_PWM, GPIO_DIRECTION_OUTPUT);
gpio_configure_direction(GPIO_LCD_BL_EN, GPIO_DIRECTION_OUTPUT);
gpio_configure_direction(GPIO_LCD_BL_RST, GPIO_DIRECTION_OUTPUT);
/* Enable Backlight EN. */
gpio_write(GPIO_LCD_BL_EN, GPIO_LEVEL_HIGH);
}
/* Configure display interface and display. */
MAKE_MIPI_CAL_REG(MIPI_CAL_MIPI_BIAS_PAD_CFG2) = 0;
if (is_mariko) {
MAKE_MIPI_CAL_REG(MIPI_CAL_MIPI_BIAS_PAD_CFG0) = 0;
APB_MISC_GP_DSI_PAD_CONTROL_0 = 0;
}
if (is_mariko) {
do_register_writes(CAR_BASE, display_config_plld_01_mariko, 4);
} else {
do_register_writes(CAR_BASE, display_config_plld_01_erista, 4);
}
do_register_writes(DI_BASE, display_config_dc_01, 94);
do_register_writes(DSI_BASE, display_config_dsi_01_init_01, 8);
if (is_mariko) {
do_register_writes(DSI_BASE, display_config_dsi_01_init_02_mariko, 1);
} else {
do_register_writes(DSI_BASE, display_config_dsi_01_init_02_erista, 1);
}
do_register_writes(DSI_BASE, display_config_dsi_01_init_03, 14);
if (is_mariko) {
do_register_writes(DSI_BASE, display_config_dsi_01_init_04_mariko, 7);
} else {
do_register_writes(DSI_BASE, display_config_dsi_01_init_04_erista, 0);
}
do_register_writes(DSI_BASE, display_config_dsi_01_init_05, 10);
if (is_mariko) {
do_register_writes(DSI_BASE, display_config_dsi_phy_timing_mariko, 1);
} else {
do_register_writes(DSI_BASE, display_config_dsi_phy_timing_erista, 1);
}
do_register_writes(DSI_BASE, display_config_dsi_01_init_06, 12);
if (is_mariko) {
do_register_writes(DSI_BASE, display_config_dsi_phy_timing_mariko, 1);
} else {
do_register_writes(DSI_BASE, display_config_dsi_phy_timing_erista, 1);
}
do_register_writes(DSI_BASE, display_config_dsi_01_init_07, 14);
udelay(10000);
/* Enable Backlight RST. */
gpio_write(GPIO_LCD_BL_RST, GPIO_LEVEL_HIGH);
udelay(60000);
if (is_mariko && (hardware_type == 5)) {
MAKE_DSI_REG(DSI_BTA_TIMING) = 0x40103;
} else {
MAKE_DSI_REG(DSI_BTA_TIMING) = 0x50204;
}
MAKE_DSI_REG(DSI_WR_DATA) = 0x337;
MAKE_DSI_REG(DSI_TRIGGER) = DSI_TRIGGER_HOST;
dsi_wait(250000, DSI_TRIGGER, (DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO), 5);
MAKE_DSI_REG(DSI_WR_DATA) = 0x406;
MAKE_DSI_REG(DSI_TRIGGER) = DSI_TRIGGER_HOST;
dsi_wait(250000, DSI_TRIGGER, (DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO), 5);
MAKE_DSI_REG(DSI_HOST_CONTROL) = (DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_IMM_BTA | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC);
dsi_wait(150000, DSI_HOST_CONTROL, DSI_HOST_CONTROL_IMM_BTA, 5000);
/* Parse LCD vendor. */
uint32_t host_response[3];
for (uint32_t i = 0; i < 3; i++) {
host_response[i] = MAKE_DSI_REG(DSI_RD_DATA);
}
/* The last word from host response is:
Bits 0-7: FAB
Bits 8-15: REV
Bits 16-23: Minor REV
*/
if ((host_response[2] & 0xFF) == 0x10) {
g_lcd_vendor = 0;
} else {
g_lcd_vendor = (host_response[2] >> 8) & 0xFF00;
}
g_lcd_vendor = (g_lcd_vendor & 0xFFFFFF00) | (host_response[2] & 0xFF);
/* LCD vendor specific configuration. */
switch (g_lcd_vendor) {
case 0x10: /* Japan Display Inc screens. */
do_dsi_sleep_or_register_writes(display_config_jdi_specific_init_01, 48);
break;
case 0xF20: /* Innolux nx-abca2 screens. */
do_dsi_sleep_or_register_writes(display_config_innolux_nx_abca2_specific_init_01, 14);
break;
case 0xF30: /* AUO nx-abca2 screens. */
do_dsi_sleep_or_register_writes(display_config_auo_nx_abca2_specific_init_01, 14);
break;
case 0x2050: /* Unknown nx-abcd screens. */
do_dsi_sleep_or_register_writes(display_config_50_nx_abcd_specific_init_01, 13);
break;
case 0x1020: /* Innolux nx-abcc screens. */
case 0x1030: /* AUO nx-abcc screens. */
case 0x1040: /* Unknown nx-abcc screens. */
default:
do_dsi_sleep_or_register_writes(display_config_innolux_auo_40_nx_abcc_specific_init_01, 5);
break;
}
udelay(20000);
if (is_mariko) {
do_register_writes(CAR_BASE, display_config_plld_02_mariko, 3);
} else {
do_register_writes(CAR_BASE, display_config_plld_02_erista, 3);
}
do_register_writes(DSI_BASE, display_config_dsi_01_init_08, 1);
if (is_mariko) {
do_register_writes(DSI_BASE, display_config_dsi_phy_timing_mariko, 1);
} else {
do_register_writes(DSI_BASE, display_config_dsi_phy_timing_erista, 1);
}
do_register_writes(DSI_BASE, display_config_dsi_01_init_09, 19);
MAKE_DI_REG(DC_DISP_DISP_CLOCK_CONTROL) = 4;
do_register_writes(DSI_BASE, display_config_dsi_01_init_10, 10);
udelay(10000);
if (is_mariko) {
do_register_writes(MIPI_CAL_BASE, display_config_mipi_cal_01, 4);
do_register_writes(MIPI_CAL_BASE, display_config_mipi_cal_02_mariko, 2);
do_register_writes(DSI_BASE, display_config_dsi_01_init_11_mariko, 7);
do_register_writes(MIPI_CAL_BASE, display_config_mipi_cal_03_mariko, 6);
do_register_writes(MIPI_CAL_BASE, display_config_mipi_cal_04, 10);
do_register_writes(MIPI_CAL_BASE, display_config_mipi_cal_02_mariko, 2);
do_register_writes(DSI_BASE, display_config_dsi_01_init_11_mariko, 7);
do_register_writes(MIPI_CAL_BASE, display_config_mipi_cal_03_mariko, 6);
do_register_writes(MIPI_CAL_BASE, display_config_mipi_cal_04, 10);
} else {
do_register_writes(MIPI_CAL_BASE, display_config_mipi_cal_01, 4);
do_register_writes(MIPI_CAL_BASE, display_config_mipi_cal_02_erista, 2);
do_register_writes(DSI_BASE, display_config_dsi_01_init_11_erista, 4);
do_register_writes(MIPI_CAL_BASE, display_config_mipi_cal_03_erista, 6);
do_register_writes(MIPI_CAL_BASE, display_config_mipi_cal_04, 10);
}
udelay(10000);
do_register_writes(DI_BASE, display_config_dc_02, 113);
}
void display_end(void) {
volatile tegra_car_t *car = car_get_regs();
volatile tegra_pinmux_t *pinmux = pinmux_get_regs();
bool is_mariko = is_soc_mariko();
/* Disable Backlight. */
display_backlight(false);
MAKE_DSI_REG(DSI_VIDEO_MODE_CONTROL) = 1;
MAKE_DSI_REG(DSI_WR_DATA) = 0x2805;
/* Wait 5 frames. */
uint32_t start_val = MAKE_HOST1X_REG(0x30A4);
while (MAKE_HOST1X_REG(0x30A4) < start_val + 5) {
/* Wait. */
}
MAKE_DI_REG(DC_CMD_STATE_ACCESS) = (READ_MUX | WRITE_MUX);
MAKE_DSI_REG(DSI_VIDEO_MODE_CONTROL) = 0;
do_register_writes(DI_BASE, display_config_dc_01_fini_01, 13);
udelay(40000);
if (is_mariko) {
do_register_writes(CAR_BASE, display_config_plld_01_mariko, 4);
} else {
do_register_writes(CAR_BASE, display_config_plld_01_erista, 4);
}
do_register_writes(DSI_BASE, display_config_dsi_01_fini_01, 2);
if (is_mariko) {
do_register_writes(DSI_BASE, display_config_dsi_phy_timing_mariko, 1);
} else {
do_register_writes(DSI_BASE, display_config_dsi_phy_timing_erista, 1);
}
do_register_writes(DSI_BASE, display_config_dsi_01_fini_02, 13);
if (g_lcd_vendor != 0x2050) {
udelay(10000);
}
/* LCD vendor specific shutdown. */
switch (g_lcd_vendor) {
case 0x10: /* Japan Display Inc screens. */
do_dsi_sleep_or_register_writes(display_config_jdi_specific_fini_01, 22);
break;
case 0xF30: /* AUO nx-abca2 screens. */
do_dsi_sleep_or_register_writes(display_config_auo_nx_abca2_specific_fini_01, 38);
break;
case 0x1020: /* Innolux nx-abcc screens. */
do_dsi_sleep_or_register_writes(display_config_innolux_nx_abcc_specific_fini_01, 10);
break;
case 0x1030: /* AUO nx-abcc screens. */
do_dsi_sleep_or_register_writes(display_config_auo_nx_abcc_specific_fini_01, 10);
break;
case 0x1040: /* Unknown nx-abcc screens. */
do_dsi_sleep_or_register_writes(display_config_40_nx_abcc_specific_fini_01, 10);
break;
default:
break;
}
MAKE_DSI_REG(DSI_WR_DATA) = 0x1005;
MAKE_DSI_REG(DSI_TRIGGER) = DSI_TRIGGER_HOST;
udelay((g_lcd_vendor == 0x2050) ? 120000 : 50000);
/* Disable Backlight RST. */
gpio_write(GPIO_LCD_BL_RST, GPIO_LEVEL_LOW);
if (g_lcd_vendor == 0x2050) {
udelay(30000);
} else {
udelay(10000);
/* Disable Backlight -5V. */
gpio_write(GPIO_LCD_BL_N5V, GPIO_LEVEL_LOW);
udelay(10000);
/* Disable Backlight +5V. */
gpio_write(GPIO_LCD_BL_P5V, GPIO_LEVEL_LOW);
udelay(10000);
}
/* Disable clocks. */
car->rst_dev_h_set = 0x1010000;
car->clk_enb_h_clr = 0x1010000;
car->rst_dev_l_set = 0x18000000;
car->clk_enb_l_clr = 0x18000000;
MAKE_DSI_REG(DSI_PAD_CONTROL_0) = (DSI_PAD_CONTROL_VS1_PULLDN_CLK | DSI_PAD_CONTROL_VS1_PULLDN(0xF) | DSI_PAD_CONTROL_VS1_PDIO_CLK | DSI_PAD_CONTROL_VS1_PDIO(0xF));
MAKE_DSI_REG(DSI_POWER_CONTROL) = 0;
if (!is_mariko) {
/* Backlight PWM. */
gpio_configure_mode(GPIO_LCD_BL_PWM, GPIO_MODE_SFIO);
pinmux->lcd_bl_pwm = ((pinmux->lcd_bl_pwm & ~PINMUX_TRISTATE) | PINMUX_TRISTATE);
pinmux->lcd_bl_pwm = (((pinmux->lcd_bl_pwm >> 2) << 2) | 1);
}
}
void display_backlight(bool enable) {
if (g_lcd_vendor == 0x2050) {
int brightness = enable ? 100 : 0;
/* Enable FRAME_END_INT */
MAKE_DI_REG(DC_CMD_INT_ENABLE) = 2;
/* Configure DSI_LINE_TYPE as FOUR */
MAKE_DSI_REG(DSI_VIDEO_MODE_CONTROL) = 1;
MAKE_DSI_REG(DSI_VIDEO_MODE_CONTROL) = 9;
/* Set and wait for FRAME_END_INT */
MAKE_DI_REG(DC_CMD_INT_STATUS) = 2;
while ((MAKE_DI_REG(DC_CMD_INT_STATUS) & 2) != 0) {
/* Wait */
}
/* Configure display brightness. */
const uint32_t brightness_val = ((0x7FF * brightness) / 100);
MAKE_DSI_REG(DSI_WR_DATA) = 0x339;
MAKE_DSI_REG(DSI_WR_DATA) = (brightness_val & 0x700) | ((brightness_val & 0xFF) << 16) | 0x51;
/* Set and wait for FRAME_END_INT */
MAKE_DI_REG(DC_CMD_INT_STATUS) = 2;
while ((MAKE_DI_REG(DC_CMD_INT_STATUS) & 2) != 0) {
/* Wait */
}
/* Set client sync point block reset. */
MAKE_DSI_REG(DSI_INCR_SYNCPT_CNTRL) = 1;
udelay(300000);
/* Clear client sync point block resest. */
MAKE_DSI_REG(DSI_INCR_SYNCPT_CNTRL) = 0;
udelay(300000);
/* Clear DSI_LINE_TYPE config. */
MAKE_DSI_REG(DSI_VIDEO_MODE_CONTROL) = 0;
/* Disable FRAME_END_INT */
MAKE_DI_REG(DC_CMD_INT_ENABLE) = 0;
MAKE_DI_REG(DC_CMD_INT_STATUS) = 2;
} else {
/* Enable Backlight PWM. */
gpio_write(GPIO_LCD_BL_PWM, enable ? GPIO_LEVEL_HIGH : GPIO_LEVEL_LOW);
}
}
void display_color_screen(uint32_t color) {
do_register_writes(DI_BASE, display_config_solid_color, 8);
/* Configure display to show single color. */
MAKE_DI_REG(DC_WIN_AD_WIN_OPTIONS) = 0;
MAKE_DI_REG(DC_WIN_BD_WIN_OPTIONS) = 0;
MAKE_DI_REG(DC_WIN_CD_WIN_OPTIONS) = 0;
MAKE_DI_REG(DC_DISP_BLEND_BACKGROUND_COLOR) = color;
MAKE_DI_REG(DC_CMD_STATE_CONTROL) = ((MAKE_DI_REG(DC_CMD_STATE_CONTROL) & 0xFFFFFFFE) | GENERAL_ACT_REQ);
udelay(35000);
display_backlight(true);
}
uint32_t *display_init_framebuffer(void *address) {
static register_write_t conf[sizeof(display_config_frame_buffer)/sizeof(register_write_t)] = {0};
if (conf[0].value == 0) {
for (uint32_t i = 0; i < sizeof(display_config_frame_buffer)/sizeof(register_write_t); i++) {
conf[i] = display_config_frame_buffer[i];
}
}
uint32_t *lfb_addr = (uint32_t *)address;
conf[19].value = (uint32_t)address;
/* This configures the framebuffer @ address with a resolution of 1280x720 (line stride 768). */
do_register_writes(DI_BASE, conf, 32);
udelay(35000);
return lfb_addr;
}

View File

@ -1,400 +0,0 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer
* 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/>.
*/
#ifndef FUSEE_DI_H_
#define FUSEE_DI_H_
#include <stdint.h>
#include <stdbool.h>
#define HOST1X_BASE 0x50000000
#define DI_BASE 0x54200000
#define DSI_BASE 0x54300000
#define VIC_BASE 0x54340000
#define MIPI_CAL_BASE 0x700E3000
#define MAKE_HOST1X_REG(n) MAKE_REG32(HOST1X_BASE + n)
#define MAKE_DI_REG(n) MAKE_REG32(DI_BASE + n * 4)
#define MAKE_DSI_REG(n) MAKE_REG32(DSI_BASE + n * 4)
#define MAKE_MIPI_CAL_REG(n) MAKE_REG32(MIPI_CAL_BASE + n)
#define MAKE_VIC_REG(n) MAKE_REG32(VIC_BASE + n)
/* Clock and reset registers. */
#define CLK_RST_CONTROLLER_CLK_SOURCE_DISP1 0x138
#define CLK_RST_CONTROLLER_PLLD_BASE 0xD0
#define CLK_RST_CONTROLLER_PLLD_MISC1 0xD8
#define CLK_RST_CONTROLLER_PLLD_MISC 0xDC
/* Display registers. */
#define DC_CMD_GENERAL_INCR_SYNCPT 0x00
#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x01
#define SYNCPT_CNTRL_NO_STALL (1 << 8)
#define SYNCPT_CNTRL_SOFT_RESET (1 << 0)
#define DC_CMD_CONT_SYNCPT_VSYNC 0x28
#define SYNCPT_VSYNC_ENABLE (1 << 8)
#define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031
#define DC_CMD_DISPLAY_COMMAND 0x32
#define DISP_CTRL_MODE_STOP (0 << 5)
#define DISP_CTRL_MODE_C_DISPLAY (1 << 5)
#define DISP_CTRL_MODE_NC_DISPLAY (2 << 5)
#define DISP_CTRL_MODE_MASK (3 << 5)
#define DC_CMD_DISPLAY_POWER_CONTROL 0x36
#define PW0_ENABLE (1 << 0)
#define PW1_ENABLE (1 << 2)
#define PW2_ENABLE (1 << 4)
#define PW3_ENABLE (1 << 6)
#define PW4_ENABLE (1 << 8)
#define PM0_ENABLE (1 << 16)
#define PM1_ENABLE (1 << 18)
#define DC_CMD_INT_STATUS 0x37
#define DC_CMD_INT_MASK 0x38
#define DC_CMD_INT_ENABLE 0x39
#define DC_CMD_STATE_ACCESS 0x40
#define READ_MUX (1 << 0)
#define WRITE_MUX (1 << 2)
#define DC_CMD_STATE_CONTROL 0x41
#define GENERAL_ACT_REQ (1 << 0)
#define WIN_A_ACT_REQ (1 << 1)
#define WIN_B_ACT_REQ (1 << 2)
#define WIN_C_ACT_REQ (1 << 3)
#define CURSOR_ACT_REQ (1 << 7)
#define GENERAL_UPDATE (1 << 8)
#define WIN_A_UPDATE (1 << 9)
#define WIN_B_UPDATE (1 << 10)
#define WIN_C_UPDATE (1 << 11)
#define CURSOR_UPDATE (1 << 15)
#define NC_HOST_TRIG (1 << 24)
#define DC_CMD_DISPLAY_WINDOW_HEADER 0x42
#define WINDOW_A_SELECT (1 << 4)
#define WINDOW_B_SELECT (1 << 5)
#define WINDOW_C_SELECT (1 << 6)
#define DC_CMD_REG_ACT_CONTROL 0x043
#define DC_COM_CRC_CONTROL 0x300
#define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x))
#define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x))
#define DC_COM_DSC_TOP_CTL 0x33E
#define DC_DISP_DISP_WIN_OPTIONS 0x402
#define HDMI_ENABLE (1 << 30)
#define DSI_ENABLE (1 << 29)
#define SOR1_TIMING_CYA (1 << 27)
#define SOR1_ENABLE (1 << 26)
#define SOR_ENABLE (1 << 25)
#define CURSOR_ENABLE (1 << 16)
#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403
#define DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER 0x404
#define DC_DISP_DISP_TIMING_OPTIONS 0x405
#define DC_DISP_REF_TO_SYNC 0x406
#define DC_DISP_SYNC_WIDTH 0x407
#define DC_DISP_BACK_PORCH 0x408
#define DC_DISP_ACTIVE 0x409
#define DC_DISP_FRONT_PORCH 0x40A
#define DC_DISP_DISP_CLOCK_CONTROL 0x42E
#define PIXEL_CLK_DIVIDER_PCD1 (0 << 8)
#define PIXEL_CLK_DIVIDER_PCD1H (1 << 8)
#define PIXEL_CLK_DIVIDER_PCD2 (2 << 8)
#define PIXEL_CLK_DIVIDER_PCD3 (3 << 8)
#define PIXEL_CLK_DIVIDER_PCD4 (4 << 8)
#define PIXEL_CLK_DIVIDER_PCD6 (5 << 8)
#define PIXEL_CLK_DIVIDER_PCD8 (6 << 8)
#define PIXEL_CLK_DIVIDER_PCD9 (7 << 8)
#define PIXEL_CLK_DIVIDER_PCD12 (8 << 8)
#define PIXEL_CLK_DIVIDER_PCD16 (9 << 8)
#define PIXEL_CLK_DIVIDER_PCD18 (10 << 8)
#define PIXEL_CLK_DIVIDER_PCD24 (11 << 8)
#define PIXEL_CLK_DIVIDER_PCD13 (12 << 8)
#define SHIFT_CLK_DIVIDER(x) ((x) & 0xff)
#define DC_DISP_DISP_INTERFACE_CONTROL 0x42F
#define DISP_DATA_FORMAT_DF1P1C (0 << 0)
#define DISP_DATA_FORMAT_DF1P2C24B (1 << 0)
#define DISP_DATA_FORMAT_DF1P2C18B (2 << 0)
#define DISP_DATA_FORMAT_DF1P2C16B (3 << 0)
#define DISP_DATA_FORMAT_DF2S (4 << 0)
#define DISP_DATA_FORMAT_DF3S (5 << 0)
#define DISP_DATA_FORMAT_DFSPI (6 << 0)
#define DISP_DATA_FORMAT_DF1P3C24B (7 << 0)
#define DISP_DATA_FORMAT_DF1P3C18B (8 << 0)
#define DISP_ALIGNMENT_MSB (0 << 8)
#define DISP_ALIGNMENT_LSB (1 << 8)
#define DISP_ORDER_RED_BLUE (0 << 9)
#define DISP_ORDER_BLUE_RED (1 << 9)
#define DC_DISP_DISP_COLOR_CONTROL 0x430
#define DITHER_CONTROL_MASK (3 << 8)
#define DITHER_CONTROL_DISABLE (0 << 8)
#define DITHER_CONTROL_ORDERED (2 << 8)
#define DITHER_CONTROL_ERRDIFF (3 << 8)
#define BASE_COLOR_SIZE_MASK (0xf << 0)
#define BASE_COLOR_SIZE_666 (0 << 0)
#define BASE_COLOR_SIZE_111 (1 << 0)
#define BASE_COLOR_SIZE_222 (2 << 0)
#define BASE_COLOR_SIZE_333 (3 << 0)
#define BASE_COLOR_SIZE_444 (4 << 0)
#define BASE_COLOR_SIZE_555 (5 << 0)
#define BASE_COLOR_SIZE_565 (6 << 0)
#define BASE_COLOR_SIZE_332 (7 << 0)
#define BASE_COLOR_SIZE_888 (8 << 0)
#define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431
#define SC1_H_QUALIFIER_NONE (1 << 16)
#define SC0_H_QUALIFIER_NONE (1 << 0)
#define DC_DISP_DATA_ENABLE_OPTIONS 0x432
#define DE_SELECT_ACTIVE_BLANK (0 << 0)
#define DE_SELECT_ACTIVE (1 << 0)
#define DE_SELECT_ACTIVE_IS (2 << 0)
#define DE_CONTROL_ONECLK (0 << 2)
#define DE_CONTROL_NORMAL (1 << 2)
#define DE_CONTROL_EARLY_EXT (2 << 2)
#define DE_CONTROL_EARLY (3 << 2)
#define DE_CONTROL_ACTIVE_BLANK (4 << 2)
#define DC_DISP_DC_MCCIF_FIFOCTRL 0x480
#define DC_DISP_BLEND_BACKGROUND_COLOR 0x4E4
#define DC_WIN_CSC_YOF 0x611
#define DC_WIN_CSC_KYRGB 0x612
#define DC_WIN_CSC_KUR 0x613
#define DC_WIN_CSC_KVR 0x614
#define DC_WIN_CSC_KUG 0x615
#define DC_WIN_CSC_KVG 0x616
#define DC_WIN_CSC_KUB 0x617
#define DC_WIN_CSC_KVB 0x618
#define DC_WIN_AD_WIN_OPTIONS 0xB80
#define DC_WIN_BD_WIN_OPTIONS 0xD80
#define DC_WIN_CD_WIN_OPTIONS 0xF80
/* The following registers are A/B/C shadows of the 0xB80/0xD80/0xF80 registers (see DISPLAY_WINDOW_HEADER). */
#define DC_WIN_WIN_OPTIONS 0x700
#define H_DIRECTION (1 << 0)
#define V_DIRECTION (1 << 2)
#define COLOR_EXPAND (1 << 6)
#define CSC_ENABLE (1 << 18)
#define WIN_ENABLE (1 << 30)
#define DC_WIN_COLOR_DEPTH 0x703
#define WIN_COLOR_DEPTH_P1 0x0
#define WIN_COLOR_DEPTH_P2 0x1
#define WIN_COLOR_DEPTH_P4 0x2
#define WIN_COLOR_DEPTH_P8 0x3
#define WIN_COLOR_DEPTH_B4G4R4A4 0x4
#define WIN_COLOR_DEPTH_B5G5R5A 0x5
#define WIN_COLOR_DEPTH_B5G6R5 0x6
#define WIN_COLOR_DEPTH_AB5G5R5 0x7
#define WIN_COLOR_DEPTH_B8G8R8A8 0xC
#define WIN_COLOR_DEPTH_R8G8B8A8 0xD
#define WIN_COLOR_DEPTH_B6x2G6x2R6x2A8 0xE
#define WIN_COLOR_DEPTH_R6x2G6x2B6x2A8 0xF
#define WIN_COLOR_DEPTH_YCbCr422 0x10
#define WIN_COLOR_DEPTH_YUV422 0x11
#define WIN_COLOR_DEPTH_YCbCr420P 0x12
#define WIN_COLOR_DEPTH_YUV420P 0x13
#define WIN_COLOR_DEPTH_YCbCr422P 0x14
#define WIN_COLOR_DEPTH_YUV422P 0x15
#define WIN_COLOR_DEPTH_YCbCr422R 0x16
#define WIN_COLOR_DEPTH_YUV422R 0x17
#define WIN_COLOR_DEPTH_YCbCr422RA 0x18
#define WIN_COLOR_DEPTH_YUV422RA 0x19
#define DC_WIN_BUFFER_CONTROL 0x702
#define DC_WIN_POSITION 0x704
#define DC_WIN_SIZE 0x705
#define H_SIZE(x) (((x) & 0x1fff) << 0)
#define V_SIZE(x) (((x) & 0x1fff) << 16)
#define DC_WIN_PRESCALED_SIZE 0x706
#define H_PRESCALED_SIZE(x) (((x) & 0x7fff) << 0)
#define V_PRESCALED_SIZE(x) (((x) & 0x1fff) << 16)
#define DC_WIN_H_INITIAL_DDA 0x707
#define DC_WIN_V_INITIAL_DDA 0x708
#define DC_WIN_DDA_INC 0x709
#define H_DDA_INC(x) (((x) & 0xffff) << 0)
#define V_DDA_INC(x) (((x) & 0xffff) << 16)
#define DC_WIN_LINE_STRIDE 0x70A
#define DC_WIN_DV_CONTROL 0x70E
#define DC_WINBUF_BLEND_LAYER_CONTROL 0x716
/* The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). */
#define DC_WINBUF_START_ADDR 0x800
#define DC_WINBUF_ADDR_H_OFFSET 0x806
#define DC_WINBUF_ADDR_V_OFFSET 0x808
#define DC_WINBUF_SURFACE_KIND 0x80B
/* Display serial interface registers. */
#define DSI_INCR_SYNCPT_CNTRL 0x1
#define DSI_RD_DATA 0x9
#define DSI_WR_DATA 0xA
#define DSI_POWER_CONTROL 0xB
#define DSI_POWER_CONTROL_ENABLE 1
#define DSI_INT_ENABLE 0xC
#define DSI_INT_STATUS 0xD
#define DSI_INT_MASK 0xE
#define DSI_HOST_CONTROL 0xF
#define DSI_HOST_CONTROL_FIFO_RESET (1 << 21)
#define DSI_HOST_CONTROL_CRC_RESET (1 << 20)
#define DSI_HOST_CONTROL_TX_TRIG_SOL (0 << 12)
#define DSI_HOST_CONTROL_TX_TRIG_FIFO (1 << 12)
#define DSI_HOST_CONTROL_TX_TRIG_HOST (2 << 12)
#define DSI_HOST_CONTROL_RAW (1 << 6)
#define DSI_HOST_CONTROL_HS (1 << 5)
#define DSI_HOST_CONTROL_FIFO_SEL (1 << 4)
#define DSI_HOST_CONTROL_IMM_BTA (1 << 3)
#define DSI_HOST_CONTROL_PKT_BTA (1 << 2)
#define DSI_HOST_CONTROL_CS (1 << 1)
#define DSI_HOST_CONTROL_ECC (1 << 0)
#define DSI_CONTROL 0x10
#define DSI_CONTROL_HS_CLK_CTRL (1 << 20)
#define DSI_CONTROL_CHANNEL(c) (((c) & 0x3) << 16)
#define DSI_CONTROL_FORMAT(f) (((f) & 0x3) << 12)
#define DSI_CONTROL_TX_TRIG(x) (((x) & 0x3) << 8)
#define DSI_CONTROL_LANES(n) (((n) & 0x3) << 4)
#define DSI_CONTROL_DCS_ENABLE (1 << 3)
#define DSI_CONTROL_SOURCE(s) (((s) & 0x1) << 2)
#define DSI_CONTROL_VIDEO_ENABLE (1 << 1)
#define DSI_CONTROL_HOST_ENABLE (1 << 0)
#define DSI_SOL_DELAY 0x11
#define DSI_MAX_THRESHOLD 0x12
#define DSI_TRIGGER 0x13
#define DSI_TRIGGER_HOST (1 << 1)
#define DSI_TRIGGER_VIDEO (1 << 0)
#define DSI_TX_CRC 0x14
#define DSI_STATUS 0x15
#define DSI_INIT_SEQ_CONTROL 0x1A
#define DSI_INIT_SEQ_DATA_0 0x1B
#define DSI_INIT_SEQ_DATA_1 0x1C
#define DSI_INIT_SEQ_DATA_2 0x1D
#define DSI_INIT_SEQ_DATA_3 0x1E
#define DSI_PKT_SEQ_0_LO 0x23
#define DSI_PKT_SEQ_0_HI 0x24
#define DSI_PKT_SEQ_1_LO 0x25
#define DSI_PKT_SEQ_1_HI 0x26
#define DSI_PKT_SEQ_2_LO 0x27
#define DSI_PKT_SEQ_2_HI 0x28
#define DSI_PKT_SEQ_3_LO 0x29
#define DSI_PKT_SEQ_3_HI 0x2A
#define DSI_PKT_SEQ_4_LO 0x2B
#define DSI_PKT_SEQ_4_HI 0x2C
#define DSI_PKT_SEQ_5_LO 0x2D
#define DSI_PKT_SEQ_5_HI 0x2E
#define DSI_DCS_CMDS 0x33
#define DSI_PKT_LEN_0_1 0x34
#define DSI_PKT_LEN_2_3 0x35
#define DSI_PKT_LEN_4_5 0x36
#define DSI_PKT_LEN_6_7 0x37
#define DSI_PHY_TIMING_0 0x3C
#define DSI_PHY_TIMING_1 0x3D
#define DSI_PHY_TIMING_2 0x3E
#define DSI_BTA_TIMING 0x3F
#define DSI_TIMEOUT_0 0x44
#define DSI_TIMEOUT_LRX(x) (((x) & 0xffff) << 16)
#define DSI_TIMEOUT_HTX(x) (((x) & 0xffff) << 0)
#define DSI_TIMEOUT_1 0x45
#define DSI_TIMEOUT_PR(x) (((x) & 0xffff) << 16)
#define DSI_TIMEOUT_TA(x) (((x) & 0xffff) << 0)
#define DSI_TO_TALLY 0x46
#define DSI_PAD_CONTROL_0 0x4B
#define DSI_PAD_CONTROL_VS1_PULLDN_CLK (1 << 24)
#define DSI_PAD_CONTROL_VS1_PULLDN(x) (((x) & 0xf) << 16)
#define DSI_PAD_CONTROL_VS1_PDIO_CLK (1 << 8)
#define DSI_PAD_CONTROL_VS1_PDIO(x) (((x) & 0xf) << 0)
#define DSI_PAD_CONTROL_CD 0x4C
#define DSI_VIDEO_MODE_CONTROL 0x4E
#define DSI_PAD_CONTROL_1 0x4F
#define DSI_PAD_CONTROL_2 0x50
#define DSI_PAD_CONTROL_3 0x51
#define DSI_PAD_PREEMP_PD_CLK(x) (((x) & 0x3) << 12)
#define DSI_PAD_PREEMP_PU_CLK(x) (((x) & 0x3) << 8)
#define DSI_PAD_PREEMP_PD(x) (((x) & 0x3) << 4)
#define DSI_PAD_PREEMP_PU(x) (((x) & 0x3) << 0)
#define DSI_PAD_CONTROL_4 0x52
#define DSI_PAD_CONTROL_5_MARIKO 0x53
#define DSI_PAD_CONTROL_6_MARIKO 0x54
#define DSI_PAD_CONTROL_7_MARIKO 0x55
#define DSI_INIT_SEQ_DATA_15 0x5F
#define DSI_INIT_SEQ_DATA_15_MARIKO 0x62
/* MIPI calibration registers. */
#define MIPI_CAL_MIPI_CAL_CTRL 0x0
#define MIPI_CAL_MIPI_CAL_AUTOCAL_CTRL0 0x4
#define MIPI_CAL_CIL_MIPI_CAL_STATUS 0x8
#define MIPI_CAL_CIL_MIPI_CAL_STATUS_2 0xC
#define MIPI_CAL_CILA_MIPI_CAL_CONFIG 0x14
#define MIPI_CAL_CILB_MIPI_CAL_CONFIG 0x18
#define MIPI_CAL_CILC_MIPI_CAL_CONFIG 0x1C
#define MIPI_CAL_CILD_MIPI_CAL_CONFIG 0x20
#define MIPI_CAL_CILE_MIPI_CAL_CONFIG 0x24
#define MIPI_CAL_CILF_MIPI_CAL_CONFIG 0x28
#define MIPI_CAL_DSIA_MIPI_CAL_CONFIG 0x38
#define MIPI_CAL_DSIB_MIPI_CAL_CONFIG 0x3C
#define MIPI_CAL_DSIC_MIPI_CAL_CONFIG 0x40
#define MIPI_CAL_DSID_MIPI_CAL_CONFIG 0x44
#define MIPI_CAL_MIPI_BIAS_PAD_CFG0 0x58
#define MIPI_CAL_MIPI_BIAS_PAD_CFG1 0x5C
#define MIPI_CAL_MIPI_BIAS_PAD_CFG2 0x60
#define MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2 0x64
#define MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2 0x68
#define MIPI_CAL_DSIC_MIPI_CAL_CONFIG_2 0x70
#define MIPI_CAL_DSID_MIPI_CAL_CONFIG_2 0x74
void display_init(void);
void display_end(void);
/* Switches screen backlight ON/OFF. */
void display_backlight(bool enable);
/* Show one single color on the display. */
void display_color_screen(uint32_t color);
/* Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */
uint32_t *display_init_framebuffer(void *address);
#endif

View File

@ -1,773 +0,0 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer
* 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/>.
*/
typedef struct {
uint32_t offset;
uint32_t value;
} register_write_t;
typedef struct {
uint16_t kind;
uint16_t offset;
uint32_t value;
} dsi_sleep_or_register_write_t;
static const uint32_t display_config_frame_buffer_address = 0xC0000000;
static const register_write_t display_config_plld_01_erista[4] = {
{CLK_RST_CONTROLLER_CLK_SOURCE_DISP1, 0x40000000},
{CLK_RST_CONTROLLER_PLLD_BASE, 0x4830A001},
{CLK_RST_CONTROLLER_PLLD_MISC1, 0x00000020},
{CLK_RST_CONTROLLER_PLLD_MISC, 0x002D0AAA},
};
static const register_write_t display_config_plld_01_mariko[4] = {
{CLK_RST_CONTROLLER_CLK_SOURCE_DISP1, 0x40000000},
{CLK_RST_CONTROLLER_PLLD_BASE, 0x4830A001},
{CLK_RST_CONTROLLER_PLLD_MISC1, 0x00000000},
{CLK_RST_CONTROLLER_PLLD_MISC, 0x002DFC00},
};
static const register_write_t display_config_dc_01[94] = {
{sizeof(uint32_t) * DC_CMD_STATE_ACCESS, 0},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{sizeof(uint32_t) * DC_CMD_REG_ACT_CONTROL, 0x54},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{sizeof(uint32_t) * DC_DISP_DC_MCCIF_FIFOCTRL, 0},
{sizeof(uint32_t) * DC_DISP_DISP_MEM_HIGH_PRIORITY, 0},
{sizeof(uint32_t) * DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_POWER_CONTROL, PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | PW4_ENABLE | PM0_ENABLE | PM1_ENABLE},
{sizeof(uint32_t) * DC_CMD_GENERAL_INCR_SYNCPT_CNTRL, SYNCPT_CNTRL_NO_STALL},
{sizeof(uint32_t) * DC_CMD_CONT_SYNCPT_VSYNC, SYNCPT_VSYNC_ENABLE | 0x9},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
{sizeof(uint32_t) * DC_CMD_STATE_ACCESS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{sizeof(uint32_t) * DC_WIN_DV_CONTROL, 0},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{sizeof(uint32_t) * DC_WIN_CSC_YOF, 0xF0},
{sizeof(uint32_t) * DC_WIN_CSC_KYRGB, 0x12A},
{sizeof(uint32_t) * DC_WIN_CSC_KUR, 0},
{sizeof(uint32_t) * DC_WIN_CSC_KVR, 0x198},
{sizeof(uint32_t) * DC_WIN_CSC_KUG, 0x39B},
{sizeof(uint32_t) * DC_WIN_CSC_KVG, 0x32F},
{sizeof(uint32_t) * DC_WIN_CSC_KUB, 0x204},
{sizeof(uint32_t) * DC_WIN_CSC_KVB, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{sizeof(uint32_t) * DC_WIN_DV_CONTROL, 0},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{sizeof(uint32_t) * DC_WIN_CSC_YOF, 0xF0},
{sizeof(uint32_t) * DC_WIN_CSC_KYRGB, 0x12A},
{sizeof(uint32_t) * DC_WIN_CSC_KUR, 0},
{sizeof(uint32_t) * DC_WIN_CSC_KVR, 0x198},
{sizeof(uint32_t) * DC_WIN_CSC_KUG, 0x39B},
{sizeof(uint32_t) * DC_WIN_CSC_KVG, 0x32F},
{sizeof(uint32_t) * DC_WIN_CSC_KUB, 0x204},
{sizeof(uint32_t) * DC_WIN_CSC_KVB, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{sizeof(uint32_t) * DC_WIN_DV_CONTROL, 0},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{sizeof(uint32_t) * DC_WIN_CSC_YOF, 0xF0},
{sizeof(uint32_t) * DC_WIN_CSC_KYRGB, 0x12A},
{sizeof(uint32_t) * DC_WIN_CSC_KUR, 0},
{sizeof(uint32_t) * DC_WIN_CSC_KVR, 0x198},
{sizeof(uint32_t) * DC_WIN_CSC_KUG, 0x39B},
{sizeof(uint32_t) * DC_WIN_CSC_KVG, 0x32F},
{sizeof(uint32_t) * DC_WIN_CSC_KUB, 0x204},
{sizeof(uint32_t) * DC_WIN_CSC_KVB, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888},
{sizeof(uint32_t) * DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C},
{sizeof(uint32_t) * DC_COM_PIN_OUTPUT_POLARITY(1), 0x1000000},
{sizeof(uint32_t) * DC_COM_PIN_OUTPUT_POLARITY(3), 0},
{sizeof(uint32_t) * DC_DISP_BLEND_BACKGROUND_COLOR, 0},
{sizeof(uint32_t) * DC_COM_CRC_CONTROL, 0},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{sizeof(uint32_t) * DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{sizeof(uint32_t) * DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{sizeof(uint32_t) * DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF},
{sizeof(uint32_t) * DC_CMD_DISPLAY_COMMAND_OPTION0, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_DISP_DISP_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_COMMAND, 0},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
};
static const register_write_t display_config_dsi_01_init_01[8] = {
{sizeof(uint32_t) * DSI_WR_DATA, 0x0},
{sizeof(uint32_t) * DSI_INT_ENABLE, 0x0},
{sizeof(uint32_t) * DSI_INT_STATUS, 0x0},
{sizeof(uint32_t) * DSI_INT_MASK, 0x0},
{sizeof(uint32_t) * DSI_INIT_SEQ_DATA_0, 0x0},
{sizeof(uint32_t) * DSI_INIT_SEQ_DATA_1, 0x0},
{sizeof(uint32_t) * DSI_INIT_SEQ_DATA_2, 0x0},
{sizeof(uint32_t) * DSI_INIT_SEQ_DATA_3, 0x0},
};
static const register_write_t display_config_dsi_01_init_02_erista[1] = {
{sizeof(uint32_t) * DSI_INIT_SEQ_DATA_15, 0x0},
};
static const register_write_t display_config_dsi_01_init_02_mariko[1] = {
{sizeof(uint32_t) * DSI_INIT_SEQ_DATA_15_MARIKO, 0x0},
};
static const register_write_t display_config_dsi_01_init_03[14] = {
{sizeof(uint32_t) * DSI_DCS_CMDS, 0},
{sizeof(uint32_t) * DSI_PKT_SEQ_0_LO, 0},
{sizeof(uint32_t) * DSI_PKT_SEQ_1_LO, 0},
{sizeof(uint32_t) * DSI_PKT_SEQ_2_LO, 0},
{sizeof(uint32_t) * DSI_PKT_SEQ_3_LO, 0},
{sizeof(uint32_t) * DSI_PKT_SEQ_4_LO, 0},
{sizeof(uint32_t) * DSI_PKT_SEQ_5_LO, 0},
{sizeof(uint32_t) * DSI_PKT_SEQ_0_HI, 0},
{sizeof(uint32_t) * DSI_PKT_SEQ_1_HI, 0},
{sizeof(uint32_t) * DSI_PKT_SEQ_2_HI, 0},
{sizeof(uint32_t) * DSI_PKT_SEQ_3_HI, 0},
{sizeof(uint32_t) * DSI_PKT_SEQ_4_HI, 0},
{sizeof(uint32_t) * DSI_PKT_SEQ_5_HI, 0},
{sizeof(uint32_t) * DSI_CONTROL, 0},
};
static const register_write_t display_config_dsi_01_init_04_erista[0] = {
/* No register writes. */
};
static const register_write_t display_config_dsi_01_init_04_mariko[7] = {
{sizeof(uint32_t) * DSI_PAD_CONTROL_1, 0},
{sizeof(uint32_t) * DSI_PAD_CONTROL_2, 0},
{sizeof(uint32_t) * DSI_PAD_CONTROL_3, 0},
{sizeof(uint32_t) * DSI_PAD_CONTROL_4, 0},
{sizeof(uint32_t) * DSI_PAD_CONTROL_5_MARIKO, 0},
{sizeof(uint32_t) * DSI_PAD_CONTROL_6_MARIKO, 0},
{sizeof(uint32_t) * DSI_PAD_CONTROL_7_MARIKO, 0},
};
static const register_write_t display_config_dsi_01_init_05[10] = {
{sizeof(uint32_t) * DSI_PAD_CONTROL_CD, 0},
{sizeof(uint32_t) * DSI_SOL_DELAY, 0x18},
{sizeof(uint32_t) * DSI_MAX_THRESHOLD, 0x1E0},
{sizeof(uint32_t) * DSI_TRIGGER, 0},
{sizeof(uint32_t) * DSI_INIT_SEQ_CONTROL, 0},
{sizeof(uint32_t) * DSI_PKT_LEN_0_1, 0},
{sizeof(uint32_t) * DSI_PKT_LEN_2_3, 0},
{sizeof(uint32_t) * DSI_PKT_LEN_4_5, 0},
{sizeof(uint32_t) * DSI_PKT_LEN_6_7, 0},
{sizeof(uint32_t) * DSI_PAD_CONTROL_1, 0},
};
static const register_write_t display_config_dsi_01_init_06[12] = {
{sizeof(uint32_t) * DSI_PHY_TIMING_1, 0x40A0E05},
{sizeof(uint32_t) * DSI_PHY_TIMING_2, 0x30109},
{sizeof(uint32_t) * DSI_BTA_TIMING, 0x190A14},
{sizeof(uint32_t) * DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)},
{sizeof(uint32_t) * DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x765) | DSI_TIMEOUT_TA(0x2000)},
{sizeof(uint32_t) * DSI_TO_TALLY, 0},
{sizeof(uint32_t) * DSI_PAD_CONTROL_0, DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0)},
{sizeof(uint32_t) * DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{sizeof(uint32_t) * DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{sizeof(uint32_t) * DSI_POWER_CONTROL, 0},
{sizeof(uint32_t) * DSI_POWER_CONTROL, 0},
{sizeof(uint32_t) * DSI_PAD_CONTROL_1, 0},
};
static const register_write_t display_config_dsi_01_init_07[14] = {
{sizeof(uint32_t) * DSI_PHY_TIMING_1, 0x40A0E05},
{sizeof(uint32_t) * DSI_PHY_TIMING_2, 0x30118},
{sizeof(uint32_t) * DSI_BTA_TIMING, 0x190A14},
{sizeof(uint32_t) * DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)},
{sizeof(uint32_t) * DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)},
{sizeof(uint32_t) * DSI_TO_TALLY, 0},
{sizeof(uint32_t) * DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
{sizeof(uint32_t) * DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE},
{sizeof(uint32_t) * DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{sizeof(uint32_t) * DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{sizeof(uint32_t) * DSI_MAX_THRESHOLD, 0x40},
{sizeof(uint32_t) * DSI_TRIGGER, 0},
{sizeof(uint32_t) * DSI_TX_CRC, 0},
{sizeof(uint32_t) * DSI_INIT_SEQ_CONTROL, 0},
};
static const register_write_t display_config_dsi_phy_timing_erista[1] = {
{sizeof(uint32_t) * DSI_PHY_TIMING_0, 0x6070601},
};
static const register_write_t display_config_dsi_phy_timing_mariko[1] = {
{sizeof(uint32_t) * DSI_PHY_TIMING_0, 0x6070603},
};
static const dsi_sleep_or_register_write_t display_config_jdi_specific_init_01[48] = {
{0, DSI_WR_DATA, 0x439},
{0, DSI_WR_DATA, 0x9483FFB9},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{0, DSI_WR_DATA, 0xBD15},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{0, DSI_WR_DATA, 0x1939},
{0, DSI_WR_DATA, 0xAAAAAAD8},
{0, DSI_WR_DATA, 0xAAAAAAEB},
{0, DSI_WR_DATA, 0xAAEBAAAA},
{0, DSI_WR_DATA, 0xAAAAAAAA},
{0, DSI_WR_DATA, 0xAAAAAAEB},
{0, DSI_WR_DATA, 0xAAEBAAAA},
{0, DSI_WR_DATA, 0xAA},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{0, DSI_WR_DATA, 0x1BD15},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{0, DSI_WR_DATA, 0x2739},
{0, DSI_WR_DATA, 0xFFFFFFD8},
{0, DSI_WR_DATA, 0xFFFFFFFF},
{0, DSI_WR_DATA, 0xFFFFFFFF},
{0, DSI_WR_DATA, 0xFFFFFFFF},
{0, DSI_WR_DATA, 0xFFFFFFFF},
{0, DSI_WR_DATA, 0xFFFFFFFF},
{0, DSI_WR_DATA, 0xFFFFFFFF},
{0, DSI_WR_DATA, 0xFFFFFFFF},
{0, DSI_WR_DATA, 0xFFFFFFFF},
{0, DSI_WR_DATA, 0xFFFFFF},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{0, DSI_WR_DATA, 0x2BD15},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{0, DSI_WR_DATA, 0xF39},
{0, DSI_WR_DATA, 0xFFFFFFD8},
{0, DSI_WR_DATA, 0xFFFFFFFF},
{0, DSI_WR_DATA, 0xFFFFFFFF},
{0, DSI_WR_DATA, 0xFFFFFF},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{0, DSI_WR_DATA, 0xBD15},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{0, DSI_WR_DATA, 0x6D915},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{0, DSI_WR_DATA, 0x439},
{0, DSI_WR_DATA, 0xB9},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{0, DSI_WR_DATA, 0x1105},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{1, 0xB4, 0},
{0, DSI_WR_DATA, 0x2905},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
};
static const dsi_sleep_or_register_write_t display_config_innolux_nx_abca2_specific_init_01[14] = {
{0, DSI_WR_DATA, 0x1105},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{1, 0xB4, 0},
{0, DSI_WR_DATA, 0x439},
{0, DSI_WR_DATA, 0x9483FFB9},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{1, 0x5, 0},
{0, DSI_WR_DATA, 0x739},
{0, DSI_WR_DATA, 0x751548B1},
{0, DSI_WR_DATA, 0x143209},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{1, 0x5, 0},
{0, DSI_WR_DATA, 0x2905},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
};
static const dsi_sleep_or_register_write_t display_config_auo_nx_abca2_specific_init_01[14] = {
{0, DSI_WR_DATA, 0x1105},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{1, 0xB4, 0},
{0, DSI_WR_DATA, 0x439},
{0, DSI_WR_DATA, 0x9483FFB9},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{1, 0x5, 0},
{0, DSI_WR_DATA, 0x739},
{0, DSI_WR_DATA, 0x711148B1},
{0, DSI_WR_DATA, 0x143209},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{1, 0x5, 0},
{0, DSI_WR_DATA, 0x2905},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
};
static const dsi_sleep_or_register_write_t display_config_innolux_auo_40_nx_abcc_specific_init_01[5] = {
{0, DSI_WR_DATA, 0x1105},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{1, 0x78, 0},
{0, DSI_WR_DATA, 0x2905},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
};
static const dsi_sleep_or_register_write_t display_config_50_nx_abcd_specific_init_01[13] = {
{0, DSI_WR_DATA, 0x1105},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{1, 0xB4, 0},
{0, DSI_WR_DATA, 0xA015},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{0, DSI_WR_DATA, 0x205315},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{0, DSI_WR_DATA, 0x339},
{0, DSI_WR_DATA, 0xFF0751},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{1, 0x5, 0},
{0, DSI_WR_DATA, 0x2905},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
};
static const register_write_t display_config_plld_02_erista[3] = {
{CLK_RST_CONTROLLER_PLLD_BASE, 0x4810c001},
{CLK_RST_CONTROLLER_PLLD_MISC1, 0x00000020},
{CLK_RST_CONTROLLER_PLLD_MISC, 0x002D0AAA},
};
static const register_write_t display_config_plld_02_mariko[3] = {
{CLK_RST_CONTROLLER_PLLD_BASE, 0x4810c001},
{CLK_RST_CONTROLLER_PLLD_MISC1, 0x00000000},
{CLK_RST_CONTROLLER_PLLD_MISC, 0x002DFC00},
};
static const register_write_t display_config_dsi_01_init_08[1] = {
{sizeof(uint32_t) * DSI_PAD_CONTROL_1, 0},
};
static const register_write_t display_config_dsi_01_init_09[19] = {
{sizeof(uint32_t) * DSI_PHY_TIMING_1, 0x40A0E05},
{sizeof(uint32_t) * DSI_PHY_TIMING_2, 0x30172},
{sizeof(uint32_t) * DSI_BTA_TIMING, 0x190A14},
{sizeof(uint32_t) * DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xA40)},
{sizeof(uint32_t) * DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x5A2F) | DSI_TIMEOUT_TA(0x2000)},
{sizeof(uint32_t) * DSI_TO_TALLY, 0},
{sizeof(uint32_t) * DSI_PKT_SEQ_0_LO, 0x40000208},
{sizeof(uint32_t) * DSI_PKT_SEQ_2_LO, 0x40000308},
{sizeof(uint32_t) * DSI_PKT_SEQ_4_LO, 0x40000308},
{sizeof(uint32_t) * DSI_PKT_SEQ_1_LO, 0x40000308},
{sizeof(uint32_t) * DSI_PKT_SEQ_3_LO, 0x3F3B2B08},
{sizeof(uint32_t) * DSI_PKT_SEQ_3_HI, 0x2CC},
{sizeof(uint32_t) * DSI_PKT_SEQ_5_LO, 0x3F3B2B08},
{sizeof(uint32_t) * DSI_PKT_SEQ_5_HI, 0x2CC},
{sizeof(uint32_t) * DSI_PKT_LEN_0_1, 0xCE0000},
{sizeof(uint32_t) * DSI_PKT_LEN_2_3, 0x87001A2},
{sizeof(uint32_t) * DSI_PKT_LEN_4_5, 0x190},
{sizeof(uint32_t) * DSI_PKT_LEN_6_7, 0x190},
{sizeof(uint32_t) * DSI_HOST_CONTROL, 0},
};
static const register_write_t display_config_dsi_01_init_10[10] = {
{sizeof(uint32_t) * DSI_TRIGGER, 0},
{sizeof(uint32_t) * DSI_CONTROL, 0},
{sizeof(uint32_t) * DSI_SOL_DELAY, 6},
{sizeof(uint32_t) * DSI_MAX_THRESHOLD, 0x1E0},
{sizeof(uint32_t) * DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{sizeof(uint32_t) * DSI_CONTROL, DSI_CONTROL_HS_CLK_CTRL | DSI_CONTROL_FORMAT(3) | DSI_CONTROL_LANES(3) | DSI_CONTROL_VIDEO_ENABLE},
{sizeof(uint32_t) * DSI_HOST_CONTROL, DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_FIFO_SEL| DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
{sizeof(uint32_t) * DSI_CONTROL, DSI_CONTROL_HS_CLK_CTRL | DSI_CONTROL_FORMAT(3) | DSI_CONTROL_LANES(3) | DSI_CONTROL_VIDEO_ENABLE},
{sizeof(uint32_t) * DSI_HOST_CONTROL, DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
{sizeof(uint32_t) * DSI_HOST_CONTROL, DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}
};
static const register_write_t display_config_dsi_01_init_11_erista[4] = {
{sizeof(uint32_t) * DSI_PAD_CONTROL_1, 0},
{sizeof(uint32_t) * DSI_PAD_CONTROL_2, 0},
{sizeof(uint32_t) * DSI_PAD_CONTROL_3, DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) | DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3)},
{sizeof(uint32_t) * DSI_PAD_CONTROL_4, 0}
};
static const register_write_t display_config_dsi_01_init_11_mariko[7] = {
{sizeof(uint32_t) * DSI_PAD_CONTROL_1, 0},
{sizeof(uint32_t) * DSI_PAD_CONTROL_2, 0},
{sizeof(uint32_t) * DSI_PAD_CONTROL_3, 0},
{sizeof(uint32_t) * DSI_PAD_CONTROL_4, 0x77777},
{sizeof(uint32_t) * DSI_PAD_CONTROL_5_MARIKO, 0x77777},
{sizeof(uint32_t) * DSI_PAD_CONTROL_6_MARIKO, DSI_PAD_PREEMP_PD_CLK(0x1) | DSI_PAD_PREEMP_PU_CLK(0x1) | DSI_PAD_PREEMP_PD(0x01) | DSI_PAD_PREEMP_PU(0x1)},
{sizeof(uint32_t) * DSI_PAD_CONTROL_7_MARIKO, 0},
};
static const register_write_t display_config_mipi_cal_01[4] = {
{MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0},
{MIPI_CAL_CIL_MIPI_CAL_STATUS, 0xF3F10000},
{MIPI_CAL_MIPI_BIAS_PAD_CFG0, 1},
{MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0},
};
static const register_write_t display_config_mipi_cal_02_erista[2] = {
{MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0x10010},
{MIPI_CAL_MIPI_BIAS_PAD_CFG1, 0x300},
};
static const register_write_t display_config_mipi_cal_02_mariko[2] = {
{MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0x10010},
{MIPI_CAL_MIPI_BIAS_PAD_CFG1, 0},
};
static const register_write_t display_config_mipi_cal_03_erista[6] = {
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG, 0x200200},
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG, 0x200200},
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2, 0x200002},
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0x200002},
{MIPI_CAL_CILA_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_CILB_MIPI_CAL_CONFIG, 0},
};
static const register_write_t display_config_mipi_cal_03_mariko[6] = {
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG, 0x200006},
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG, 0x200006},
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2, 0x260000},
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0x260000},
{MIPI_CAL_CILA_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_CILB_MIPI_CAL_CONFIG, 0},
};
static const register_write_t display_config_mipi_cal_04[10] = {
{MIPI_CAL_CILC_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_CILD_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_CILE_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_CILF_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_DSIC_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_DSID_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0},
{MIPI_CAL_DSIC_MIPI_CAL_CONFIG_2, 0},
{MIPI_CAL_DSID_MIPI_CAL_CONFIG_2, 0},
{MIPI_CAL_MIPI_CAL_CTRL, 0x2A000001},
};
static const register_write_t display_config_dc_02[113] = {
{sizeof(uint32_t) * DC_CMD_STATE_ACCESS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{sizeof(uint32_t) * DC_WIN_DV_CONTROL, 0},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{sizeof(uint32_t) * DC_WIN_CSC_YOF, 0xF0},
{sizeof(uint32_t) * DC_WIN_CSC_KYRGB, 0x12A},
{sizeof(uint32_t) * DC_WIN_CSC_KUR, 0},
{sizeof(uint32_t) * DC_WIN_CSC_KVR, 0x198},
{sizeof(uint32_t) * DC_WIN_CSC_KUG, 0x39B},
{sizeof(uint32_t) * DC_WIN_CSC_KVG, 0x32F},
{sizeof(uint32_t) * DC_WIN_CSC_KUB, 0x204},
{sizeof(uint32_t) * DC_WIN_CSC_KVB, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{sizeof(uint32_t) * DC_WIN_DV_CONTROL, 0},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{sizeof(uint32_t) * DC_WIN_CSC_YOF, 0xF0},
{sizeof(uint32_t) * DC_WIN_CSC_KYRGB, 0x12A},
{sizeof(uint32_t) * DC_WIN_CSC_KUR, 0},
{sizeof(uint32_t) * DC_WIN_CSC_KVR, 0x198},
{sizeof(uint32_t) * DC_WIN_CSC_KUG, 0x39B},
{sizeof(uint32_t) * DC_WIN_CSC_KVG, 0x32F},
{sizeof(uint32_t) * DC_WIN_CSC_KUB, 0x204},
{sizeof(uint32_t) * DC_WIN_CSC_KVB, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{sizeof(uint32_t) * DC_WIN_DV_CONTROL, 0},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{sizeof(uint32_t) * DC_WIN_CSC_YOF, 0xF0},
{sizeof(uint32_t) * DC_WIN_CSC_KYRGB, 0x12A},
{sizeof(uint32_t) * DC_WIN_CSC_KUR, 0},
{sizeof(uint32_t) * DC_WIN_CSC_KVR, 0x198},
{sizeof(uint32_t) * DC_WIN_CSC_KUG, 0x39B},
{sizeof(uint32_t) * DC_WIN_CSC_KVG, 0x32F},
{sizeof(uint32_t) * DC_WIN_CSC_KUB, 0x204},
{sizeof(uint32_t) * DC_WIN_CSC_KVB, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888},
{sizeof(uint32_t) * DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C},
{sizeof(uint32_t) * DC_COM_PIN_OUTPUT_POLARITY(1), 0x1000000},
{sizeof(uint32_t) * DC_COM_PIN_OUTPUT_POLARITY(3), 0},
{sizeof(uint32_t) * DC_DISP_BLEND_BACKGROUND_COLOR, 0},
{sizeof(uint32_t) * DC_COM_CRC_CONTROL, 0},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{sizeof(uint32_t) * DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{sizeof(uint32_t) * DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{sizeof(uint32_t) * DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF},
{sizeof(uint32_t) * DC_CMD_DISPLAY_COMMAND_OPTION0, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_DISP_DISP_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_COMMAND, 0},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
{sizeof(uint32_t) * DC_CMD_STATE_ACCESS, 0},
{sizeof(uint32_t) * DC_DISP_DISP_TIMING_OPTIONS, 0},
{sizeof(uint32_t) * DC_DISP_REF_TO_SYNC, (1 << 16)},
{sizeof(uint32_t) * DC_DISP_SYNC_WIDTH, 0x10048},
{sizeof(uint32_t) * DC_DISP_BACK_PORCH, 0x90048},
{sizeof(uint32_t) * DC_DISP_ACTIVE, 0x50002D0},
{sizeof(uint32_t) * DC_DISP_FRONT_PORCH, 0xA0088},
{sizeof(uint32_t) * DC_DISP_SHIFT_CLOCK_OPTIONS, SC1_H_QUALIFIER_NONE | SC0_H_QUALIFIER_NONE},
{sizeof(uint32_t) * DC_COM_PIN_OUTPUT_ENABLE(1), 0},
{sizeof(uint32_t) * DC_DISP_DATA_ENABLE_OPTIONS, DE_SELECT_ACTIVE | DE_CONTROL_NORMAL},
{sizeof(uint32_t) * DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C},
{sizeof(uint32_t) * DC_DISP_DISP_CLOCK_CONTROL, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_COMMAND_OPTION0, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_DISP_DISP_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{sizeof(uint32_t) * DC_CMD_STATE_ACCESS, READ_MUX | WRITE_MUX},
{sizeof(uint32_t) * DC_DISP_FRONT_PORCH, 0xA0088},
{sizeof(uint32_t) * DC_CMD_STATE_ACCESS, 0},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{sizeof(uint32_t) * DC_CMD_GENERAL_INCR_SYNCPT, 0x301},
{sizeof(uint32_t) * DC_CMD_GENERAL_INCR_SYNCPT, 0x301},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{sizeof(uint32_t) * DC_CMD_STATE_ACCESS, 0},
{sizeof(uint32_t) * DC_DISP_DISP_CLOCK_CONTROL, PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4)},
{sizeof(uint32_t) * DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888},
{sizeof(uint32_t) * DC_CMD_DISPLAY_COMMAND_OPTION0, 0},
};
static const register_write_t display_config_frame_buffer[32] = {
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{sizeof(uint32_t) * DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_WIN_POSITION, 0},
{sizeof(uint32_t) * DC_WIN_H_INITIAL_DDA, 0},
{sizeof(uint32_t) * DC_WIN_V_INITIAL_DDA, 0},
{sizeof(uint32_t) * DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(2880)},
{sizeof(uint32_t) * DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)},
{sizeof(uint32_t) * DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)},
{sizeof(uint32_t) * DC_WIN_LINE_STRIDE, 0x6000C00},
{sizeof(uint32_t) * DC_WIN_BUFFER_CONTROL, 0},
{sizeof(uint32_t) * DC_WINBUF_SURFACE_KIND, 0},
{sizeof(uint32_t) * DC_WINBUF_START_ADDR, display_config_frame_buffer_address},
{sizeof(uint32_t) * DC_WINBUF_ADDR_H_OFFSET, 0},
{sizeof(uint32_t) * DC_WINBUF_ADDR_V_OFFSET, 0},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, WIN_ENABLE},
{sizeof(uint32_t) * DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ},
};
static const register_write_t display_config_solid_color[8] = {
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{sizeof(uint32_t) * DC_WIN_WIN_OPTIONS, 0},
{sizeof(uint32_t) * DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{sizeof(uint32_t) * DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY},
};
static const register_write_t display_config_dc_01_fini_01[13] = {
{sizeof(uint32_t) * DC_DISP_FRONT_PORCH, 0xA0088},
{sizeof(uint32_t) * DC_CMD_INT_MASK, 0},
{sizeof(uint32_t) * DC_CMD_STATE_ACCESS, 0},
{sizeof(uint32_t) * DC_CMD_INT_ENABLE, 0},
{sizeof(uint32_t) * DC_CMD_CONT_SYNCPT_VSYNC, 0},
{sizeof(uint32_t) * DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_STOP},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{sizeof(uint32_t) * DC_CMD_GENERAL_INCR_SYNCPT, 0x301},
{sizeof(uint32_t) * DC_CMD_GENERAL_INCR_SYNCPT, 0x301},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{sizeof(uint32_t) * DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
};
static const register_write_t display_config_dsi_01_fini_01[2] = {
{sizeof(uint32_t) * DSI_POWER_CONTROL, 0},
{sizeof(uint32_t) * DSI_PAD_CONTROL_1, 0},
};
static const register_write_t display_config_dsi_01_fini_02[13] = {
{sizeof(uint32_t) * DSI_PHY_TIMING_1, 0x40A0E05},
{sizeof(uint32_t) * DSI_PHY_TIMING_2, 0x30109},
{sizeof(uint32_t) * DSI_BTA_TIMING, 0x190A14},
{sizeof(uint32_t) * DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF) },
{sizeof(uint32_t) * DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x765) | DSI_TIMEOUT_TA(0x2000)},
{sizeof(uint32_t) * DSI_TO_TALLY, 0},
{sizeof(uint32_t) * DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
{sizeof(uint32_t) * DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE},
{sizeof(uint32_t) * DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{sizeof(uint32_t) * DSI_MAX_THRESHOLD, 0x40},
{sizeof(uint32_t) * DSI_TRIGGER, 0},
{sizeof(uint32_t) * DSI_TX_CRC, 0},
{sizeof(uint32_t) * DSI_INIT_SEQ_CONTROL, 0}
};
static const dsi_sleep_or_register_write_t display_config_jdi_specific_fini_01[22] = {
{0, DSI_WR_DATA, 0x439},
{0, DSI_WR_DATA, 0x9483FFB9},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{0, DSI_WR_DATA, 0x2139},
{0, DSI_WR_DATA, 0x191919D5},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{0, DSI_WR_DATA, 0xB39},
{0, DSI_WR_DATA, 0x4F0F41B1},
{0, DSI_WR_DATA, 0xF179A433},
{0, DSI_WR_DATA, 0x2D81},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{0, DSI_WR_DATA, 0x439},
{0, DSI_WR_DATA, 0xB9},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
};
static const dsi_sleep_or_register_write_t display_config_auo_nx_abca2_specific_fini_01[38] = {
{0, DSI_WR_DATA, 0x439},
{0, DSI_WR_DATA, 0x9483FFB9},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{0, DSI_WR_DATA, 0x2C39},
{0, DSI_WR_DATA, 0x191919D5},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{0, DSI_WR_DATA, 0x2C39},
{0, DSI_WR_DATA, 0x191919D6},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_WR_DATA, 0x19191919},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{0, DSI_WR_DATA, 0xB39},
{0, DSI_WR_DATA, 0x711148B1},
{0, DSI_WR_DATA, 0x71143209},
{0, DSI_WR_DATA, 0x114D31},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{0, DSI_WR_DATA, 0x439},
{0, DSI_WR_DATA, 0xB9},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{1, 0x5, 0},
};
static const dsi_sleep_or_register_write_t display_config_innolux_nx_abcc_specific_fini_01[10] = {
{0, DSI_WR_DATA, 0x439},
{0, DSI_WR_DATA, 0x9483FFB9},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{1, 0x5, 0},
{0, DSI_WR_DATA, 0xB39},
{0, DSI_WR_DATA, 0x751548B1},
{0, DSI_WR_DATA, 0x71143209},
{0, DSI_WR_DATA, 0x115631},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{1, 0x5, 0},
};
static const dsi_sleep_or_register_write_t display_config_auo_nx_abcc_specific_fini_01[10] = {
{0, DSI_WR_DATA, 0x439},
{0, DSI_WR_DATA, 0x9483FFB9},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{1, 0x5, 0},
{0, DSI_WR_DATA, 0xB39},
{0, DSI_WR_DATA, 0x711148B1},
{0, DSI_WR_DATA, 0x71143209},
{0, DSI_WR_DATA, 0x114D31},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{1, 0x5, 0},
};
static const dsi_sleep_or_register_write_t display_config_40_nx_abcc_specific_fini_01[10] = {
{0, DSI_WR_DATA, 0x439},
{0, DSI_WR_DATA, 0x9483FFB9},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{1, 0x5, 0},
{0, DSI_WR_DATA, 0xB39},
{0, DSI_WR_DATA, 0x731348B1},
{0, DSI_WR_DATA, 0x71243209},
{0, DSI_WR_DATA, 0x4C31},
{0, DSI_TRIGGER, DSI_TRIGGER_HOST},
{1, 0x5, 0},
};

File diff suppressed because it is too large Load Diff

View File

@ -1,118 +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 <inttypes.h>
#include "exception_handlers.h"
#include "utils.h"
#include "../../../fusee/common/log.h"
#include "../../../fusee/common/vsprintf.h"
#define CODE_DUMP_SIZE 0x30
#define STACK_DUMP_SIZE 0x30
extern const uint32_t exception_handler_table[];
static const char *exception_names[] = {
"Reset", "Undefined instruction", "SWI", "Prefetch abort", "Data abort", "Reserved", "IRQ", "FIQ",
};
static const char *register_names[] = {
"R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10", "R11", "R12",
"SP", "LR", "PC", "CPSR",
};
/* Adapted from https://gist.github.com/ccbrown/9722406 */
static void hexdump(const void* data, size_t size, uintptr_t addrbase, char* strbuf) {
const uint8_t *d = (const uint8_t *)data;
char ascii[17] = {0};
ascii[16] = '\0';
for (size_t i = 0; i < size; i++) {
if (i % 16 == 0) {
strbuf += sprintf(strbuf, "%0*" PRIXPTR ": | ", 2 * sizeof(addrbase), addrbase + i);
}
strbuf += sprintf(strbuf, "%02X ", d[i]);
if (d[i] >= ' ' && d[i] <= '~') {
ascii[i % 16] = d[i];
} else {
ascii[i % 16] = '.';
}
if ((i+1) % 8 == 0 || i+1 == size) {
strbuf += sprintf(strbuf, " ");
if ((i+1) % 16 == 0) {
strbuf += sprintf(strbuf, "| %s \n", ascii);
} else if (i+1 == size) {
ascii[(i+1) % 16] = '\0';
if ((i+1) % 16 <= 8) {
strbuf += sprintf(strbuf, " ");
}
for (size_t j = (i+1) % 16; j < 16; j++) {
strbuf += sprintf(strbuf, " ");
}
strbuf += sprintf(strbuf, "| %s \n", ascii);
}
}
}
}
void setup_exception_handlers(void) {
volatile uint32_t *bpmp_exception_handler_table = (volatile uint32_t *)0x6000F200;
for (int i = 0; i < 8; i++) {
if (exception_handler_table[i] != 0) {
bpmp_exception_handler_table[i] = exception_handler_table[i];
}
}
}
void exception_handler_main(uint32_t *registers, unsigned int exception_type) {
char exception_log[0x400] = {0};
uint8_t code_dump[CODE_DUMP_SIZE] = {0};
uint8_t stack_dump[STACK_DUMP_SIZE] = {0};
size_t code_dump_size = 0;
size_t stack_dump_size = 0;
uint32_t pc = registers[15];
uint32_t cpsr = registers[16];
uint32_t instr_addr = pc + ((cpsr & 0x20) ? 2 : 4) - CODE_DUMP_SIZE;
sprintf(exception_log, "An exception occurred!\n");
code_dump_size = safecpy(code_dump, (const void *)instr_addr, CODE_DUMP_SIZE);
stack_dump_size = safecpy(stack_dump, (const void *)registers[13], STACK_DUMP_SIZE);
sprintf(exception_log + strlen(exception_log), "\nException type: %s\n", exception_names[exception_type]);
sprintf(exception_log + strlen(exception_log), "\nRegisters:\n");
/* Print r0 to pc. */
for (int i = 0; i < 16; i += 2) {
sprintf(exception_log + strlen(exception_log), "%-7s%08"PRIX32" %-7s%08"PRIX32"\n",
register_names[i], registers[i], register_names[i+1], registers[i+1]);
}
/* Print cpsr. */
sprintf(exception_log + strlen(exception_log), "%-7s%08"PRIX32"\n", register_names[16], registers[16]);
/* Print code and stack regions. */
sprintf(exception_log + strlen(exception_log), "\nCode dump:\n");
hexdump(code_dump, code_dump_size, instr_addr, exception_log + strlen(exception_log));
sprintf(exception_log + strlen(exception_log), "\nStack dump:\n");
hexdump(stack_dump, stack_dump_size, registers[13], exception_log + strlen(exception_log));
sprintf(exception_log + strlen(exception_log), "\n");
/* Throw fatal error with the full exception log. */
fatal_error(exception_log);
}

View File

@ -1,28 +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/>.
*/
#ifndef FUSEE_EXCEPTION_HANDLERS_H
#define FUSEE_EXCEPTION_HANDLERS_H
#include <stdint.h>
#include <stddef.h>
/* Copies up to len bytes, stops and returns the read length on data fault. */
size_t safecpy(void *dst, const void *src, size_t len);
void setup_exception_handlers(void);
#endif

View File

@ -1,125 +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/>.
*/
.macro GEN_USUAL_HANDLER name, index, lr_arm_displ, lr_thumb_displ
_exception_handler_\name:
ldr sp, =_regs
stmia sp!, {r0-r7}
/* Adjust lr to make it point to the location where the exception occured. */
mrs r1, spsr
tst r1, #0x20
subeq lr, lr, #\lr_arm_displ
subne lr, lr, #\lr_thumb_displ
mov r0, sp
mov r1, #\index
b _exception_handler_common
.endm
.section .text.exception_handlers_asm, "ax", %progbits
.arm
.align 5
_exception_handler_common:
mrs r2, spsr
mrs r3, cpsr
/* Mask interrupts. */
orr r3, #0xC0
msr cpsr_cx, r3
/* Switch to the mode that triggered the interrupt, get the remaining regs, switch back. */
ands r4, r2, #0xF
moveq r4, #0xF /* usr => sys */
bic r5, r3, #0xF
orr r5, r4
msr cpsr_c, r5
stmia r0!, {r8-lr}
msr cpsr_c, r3
str lr, [r0], #4
str r2, [r0]
/* Finally, switch to system mode, setting interrupts and clearing the flags; set sp as well. */
msr cpsr_cxsf, #0xDF
ldr sp, =(_exception_handler_stack + 0x1000)
ldr r0, =_regs
bl exception_handler_main
b .
GEN_USUAL_HANDLER undefined_instruction, 1, 4, 2
GEN_USUAL_HANDLER swi, 2, 4, 2
GEN_USUAL_HANDLER prefetch_abort, 3, 4, 4
GEN_USUAL_HANDLER data_abort_normal, 4, 8, 8
GEN_USUAL_HANDLER fiq, 7, 4, 4
_exception_handler_data_abort:
/* Mask interrupts (abort mode). */
msr cpsr_cx, #0xD7
adr sp, safecpy+8
cmp lr, sp
blo _exception_handler_data_abort_normal
adr sp, _safecpy_end+8
cmp lr, sp
bhs _exception_handler_data_abort_normal
/* Set the flags, set r12 to 0 for safecpy, return from exception. */
msr spsr_f, #(1 << 30)
mov r12, #0
subs pc, lr, #4
.global safecpy
.type safecpy, %function
safecpy:
push {r4, lr}
mov r3, #0
movs r12, #1
_safecpy_loop:
ldrb r4, [r1, r3]
cmp r12, #0
beq _safecpy_loop_end
strb r4, [r0, r3]
add r3, #1
cmp r3, r2
blo _safecpy_loop
_safecpy_loop_end:
mov r0, r3
pop {r4, lr}
bx lr /* Need to do that separately on ARMv4. */
_safecpy_end:
.section .rodata.exception_handlers_asm, "a", %progbits
.align 2
.global exception_handler_table
exception_handler_table:
.word 0 /* Reset */
.word _exception_handler_undefined_instruction
.word _exception_handler_swi
.word _exception_handler_prefetch_abort
.word _exception_handler_data_abort
.word 0 /* Reserved */
.word 0 /* IRQ */
.word _exception_handler_fiq
.section .bss.exception_handlers_asm, "w", %nobits
.align 4
_exception_handler_stack: .skip 0x1000
_regs: .skip (4 * 17)

View File

@ -1,31 +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/>.
*/
#ifndef FUSEE_FLOW_CTLR_H
#define FUSEE_FLOW_CTLR_H
#include <stdint.h>
#define FLOW_CTLR_BASE 0x60007000
#define MAKE_FLOW_REG(n) MAKE_REG32(FLOW_CTLR_BASE + n)
#define FLOW_CTLR_HALT_COP_EVENTS_0 MAKE_FLOW_REG(0x004)
#define FLOW_CTLR_RAM_REPAIR_0 MAKE_FLOW_REG(0x040)
#define FLOW_CTLR_FLOW_DBG_QUAL_0 MAKE_FLOW_REG(0x050)
#define FLOW_CTLR_L2FLUSH_CONTROL_0 MAKE_FLOW_REG(0x094)
#define FLOW_CTLR_BPMP_CLUSTER_CONTROL_0 MAKE_FLOW_REG(0x098)
#endif

View File

@ -1,138 +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 "fs_utils.h"
#include "mc.h"
#include "../../../fusee/common/fatfs/ff.h"
#include "../../../fusee/common/log.h"
FATFS sd_fs;
static bool g_sd_mounted = false;
static bool g_sd_initialized = false;
static bool g_ahb_redirect_enabled = false;
sdmmc_t g_sd_sdmmc;
sdmmc_device_t g_sd_device;
bool mount_sd(void)
{
/* Already mounted. */
if (g_sd_mounted)
return true;
/* Enable AHB redirection if necessary. */
if (!g_ahb_redirect_enabled) {
mc_enable_ahb_redirect();
g_ahb_redirect_enabled = true;
}
if (!g_sd_initialized) {
/* Initialize SD. */
if (sdmmc_device_sd_init(&g_sd_device, &g_sd_sdmmc, SDMMC_BUS_WIDTH_4BIT, SDMMC_SPEED_SD_SDR104))
{
g_sd_initialized = true;
/* Mount SD. */
if (f_mount(&sd_fs, "", 1) == FR_OK) {
print(SCREEN_LOG_LEVEL_INFO, "Mounted SD card!\n");
g_sd_mounted = true;
}
}
else
fatal_error("Failed to initialize the SD card!.\n");
}
return g_sd_mounted;
}
void unmount_sd(void)
{
if (g_sd_mounted)
{
f_mount(NULL, "", 1);
sdmmc_device_finish(&g_sd_device);
g_sd_mounted = false;
}
/* Disable AHB redirection if necessary. */
if (g_ahb_redirect_enabled) {
mc_disable_ahb_redirect();
g_ahb_redirect_enabled = false;
}
}
uint32_t get_file_size(const char *filename)
{
/* SD card hasn't been mounted yet. */
if (!g_sd_mounted)
return 0;
/* Open the file for reading. */
FIL f;
if (f_open(&f, filename, FA_READ) != FR_OK)
return 0;
/* Get the file size. */
uint32_t file_size = f_size(&f);
/* Close the file. */
f_close(&f);
return file_size;
}
int read_from_file(void *dst, uint32_t dst_size, const char *filename)
{
/* SD card hasn't been mounted yet. */
if (!g_sd_mounted)
return 0;
/* Open the file for reading. */
FIL f;
if (f_open(&f, filename, FA_READ) != FR_OK)
return 0;
/* Sync. */
f_sync(&f);
/* Read from file. */
UINT br = 0;
int res = f_read(&f, dst, dst_size, &br);
f_close(&f);
return (res == FR_OK) ? (int)br : 0;
}
int write_to_file(void *src, uint32_t src_size, const char *filename)
{
/* SD card hasn't been mounted yet. */
if (!g_sd_mounted)
return 0;
/* Open the file for writing. */
FIL f;
if (f_open(&f, filename, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)
return 0;
/* Sync. */
f_sync(&f);
/* Write to file. */
UINT bw = 0;
int res = f_write(&f, src, src_size, &bw);
f_close(&f);
return (res == FR_OK) ? (int)bw : 0;
}

View File

@ -1,35 +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/>.
*/
#ifndef FUSEE_FS_UTILS_H
#define FUSEE_FS_UTILS_H
#include <stdbool.h>
#include <stdint.h>
#include "../../../fusee/common/sdmmc/sdmmc.h"
#include "utils.h"
extern sdmmc_t g_sd_sdmmc;
extern sdmmc_device_t g_sd_device;
bool mount_sd(void);
void unmount_sd(void);
uint32_t get_file_size(const char *filename);
int read_from_file(void *dst, uint32_t dst_size, const char *filename);
int write_to_file(void *src, uint32_t src_size, const char *filename);
#endif

View File

@ -1,346 +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 <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <vapours/ams_version.h>
#include "car.h"
#include "fuse.h"
#include "pmc.h"
#include "timers.h"
/* Initialize the fuse driver */
void fuse_init(void) {
/* Make all fuse registers visible, disable the private key and disable programming. */
clkrst_enable_fuse_regs(true);
/* fuse_disable_private_key(); */
fuse_disable_programming();
}
/* Disable access to the private key and set the TZ sticky bit. */
void fuse_disable_private_key(void) {
volatile tegra_fuse_t *fuse = fuse_get_regs();
fuse->FUSE_PRIVATEKEYDISABLE = 0x10;
}
/* Disable all fuse programming. */
void fuse_disable_programming(void) {
volatile tegra_fuse_t *fuse = fuse_get_regs();
fuse->FUSE_DISABLEREGPROGRAM = 1;
}
/* Enable power to the fuse hardware array. */
void fuse_enable_power(void) {
volatile tegra_pmc_t *pmc = pmc_get_regs();
pmc->fuse_control &= ~(0x200); /* Clear PMC_FUSE_CTRL_PS18_LATCH_CLEAR. */
mdelay(1);
pmc->fuse_control |= 0x100; /* Set PMC_FUSE_CTRL_PS18_LATCH_SET. */
mdelay(1);
}
/* Disable power to the fuse hardware array. */
void fuse_disable_power(void) {
volatile tegra_pmc_t *pmc = pmc_get_regs();
pmc->fuse_control &= ~(0x100); /* Clear PMC_FUSE_CTRL_PS18_LATCH_SET. */
mdelay(1);
pmc->fuse_control |= 0x200; /* Set PMC_FUSE_CTRL_PS18_LATCH_CLEAR. */
mdelay(1);
}
/* Wait for the fuse driver to go idle. */
static void fuse_wait_idle(void) {
volatile tegra_fuse_t *fuse = fuse_get_regs();
uint32_t ctrl_val = 0;
/* Wait for STATE_IDLE */
while ((ctrl_val & (0xF0000)) != 0x40000) {
ctrl_val = fuse->FUSE_FUSECTRL;
}
}
/* Read a fuse from the hardware array. */
uint32_t fuse_hw_read(uint32_t addr) {
volatile tegra_fuse_t *fuse = fuse_get_regs();
/* Wait for idle state. */
fuse_wait_idle();
/* Program the target address. */
fuse->FUSE_FUSEADDR = addr;
/* Enable read operation in control register. */
uint32_t ctrl_val = fuse->FUSE_FUSECTRL;
ctrl_val &= ~0x3;
ctrl_val |= 0x1; /* Set READ command. */
fuse->FUSE_FUSECTRL = ctrl_val;
/* Wait for idle state. */
fuse_wait_idle();
return fuse->FUSE_FUSERDATA;
}
/* Write a fuse in the hardware array. */
void fuse_hw_write(uint32_t value, uint32_t addr) {
volatile tegra_fuse_t *fuse = fuse_get_regs();
/* Wait for idle state. */
fuse_wait_idle();
/* Program the target address and value. */
fuse->FUSE_FUSEADDR = addr;
fuse->FUSE_FUSEWDATA = value;
/* Enable write operation in control register. */
uint32_t ctrl_val = fuse->FUSE_FUSECTRL;
ctrl_val &= ~0x3;
ctrl_val |= 0x2; /* Set WRITE command. */
fuse->FUSE_FUSECTRL = ctrl_val;
/* Wait for idle state. */
fuse_wait_idle();
}
/* Sense the fuse hardware array into the fuse cache. */
void fuse_hw_sense(void) {
volatile tegra_fuse_t *fuse = fuse_get_regs();
/* Wait for idle state. */
fuse_wait_idle();
/* Enable sense operation in control register */
uint32_t ctrl_val = fuse->FUSE_FUSECTRL;
ctrl_val &= ~0x3;
ctrl_val |= 0x3; /* Set SENSE_CTRL command */
fuse->FUSE_FUSECTRL = ctrl_val;
/* Wait for idle state. */
fuse_wait_idle();
}
/* Read the SKU info register. */
uint32_t fuse_get_sku_info(void) {
volatile tegra_fuse_chip_common_t *fuse_chip = fuse_chip_common_get_regs();
return fuse_chip->FUSE_SKU_INFO;
}
/* Read the bootrom patch version. */
uint32_t fuse_get_bootrom_patch_version(void) {
volatile tegra_fuse_chip_common_t *fuse_chip = fuse_chip_common_get_regs();
return fuse_chip->FUSE_SOC_SPEEDO_1_CALIB;
}
/* Read a spare bit register. */
uint32_t fuse_get_spare_bit(uint32_t index) {
uint32_t soc_type = fuse_get_soc_type();
if (soc_type == 0) {
if (index < 32) {
volatile tegra_fuse_chip_erista_t *fuse_chip = fuse_chip_erista_get_regs();
return fuse_chip->FUSE_SPARE_BIT[index];
}
} else if (soc_type == 1) {
if (index < 30) {
volatile tegra_fuse_chip_mariko_t *fuse_chip = fuse_chip_mariko_get_regs();
return fuse_chip->FUSE_SPARE_BIT[index];
}
}
return 0;
}
/* Read a reserved ODM register. */
uint32_t fuse_get_reserved_odm(uint32_t index) {
if (index < 8) {
volatile tegra_fuse_chip_common_t *fuse_chip = fuse_chip_common_get_regs();
return fuse_chip->FUSE_RESERVED_ODM0[index];
} else {
uint32_t soc_type = fuse_get_soc_type();
if (soc_type == 1) {
volatile tegra_fuse_chip_mariko_t *fuse_chip = fuse_chip_mariko_get_regs();
if (index < 22) {
return fuse_chip->FUSE_RESERVED_ODM8[index - 8];
} else if (index < 25) {
return fuse_chip->FUSE_RESERVED_ODM22[index - 22];
} else if (index < 26) {
return fuse_chip->FUSE_RESERVED_ODM25;
} else if (index < 29) {
return fuse_chip->FUSE_RESERVED_ODM26[index - 26];
} else if (index < 30) {
return fuse_chip->FUSE_RESERVED_ODM29;
}
}
}
return 0;
}
/* Get the DramId. */
uint32_t fuse_get_dram_id(void) {
return ((fuse_get_reserved_odm(4) >> 3) & 0x1F);
}
/* Derive the DeviceId. */
uint64_t fuse_get_device_id(void) {
volatile tegra_fuse_chip_common_t *fuse_chip = fuse_chip_common_get_regs();
uint64_t device_id = 0;
uint64_t y_coord = fuse_chip->FUSE_OPT_Y_COORDINATE & 0x1FF;
uint64_t x_coord = fuse_chip->FUSE_OPT_X_COORDINATE & 0x1FF;
uint64_t wafer_id = fuse_chip->FUSE_OPT_WAFER_ID & 0x3F;
uint32_t lot_code = fuse_chip->FUSE_OPT_LOT_CODE_0;
uint64_t fab_code = fuse_chip->FUSE_OPT_FAB_CODE & 0x3F;
uint64_t derived_lot_code = 0;
for (unsigned int i = 0; i < 5; i++) {
derived_lot_code = (derived_lot_code * 0x24) + ((lot_code >> (24 - 6*i)) & 0x3F);
}
derived_lot_code &= 0x03FFFFFF;
device_id |= y_coord << 0;
device_id |= x_coord << 9;
device_id |= wafer_id << 18;
device_id |= derived_lot_code << 24;
device_id |= fab_code << 50;
return device_id;
}
/* Derive the HardwareType with firmware specific checks. */
uint32_t fuse_get_hardware_type_with_firmware_check(uint32_t target_firmware) {
uint32_t fuse_reserved_odm4 = fuse_get_reserved_odm(4);
uint32_t hardware_type = (((fuse_reserved_odm4 >> 7) & 2) | ((fuse_reserved_odm4 >> 2) & 1));
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
volatile tegra_fuse_chip_common_t *fuse_chip = fuse_chip_common_get_regs();
uint32_t fuse_spare_bit9 = (fuse_chip->FUSE_SPARE_BIT[9] & 1);
switch (hardware_type) {
case 0x00: return (fuse_spare_bit9 == 0) ? 0 : 3;
case 0x01: return 0; /* HardwareType_Icosa */
case 0x02: return 1; /* HardwareType_Copper */
default: return 3; /* HardwareType_Undefined */
}
} else {
hardware_type |= ((fuse_reserved_odm4 >> 14) & 0x3C);
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_7_0_0) {
switch (hardware_type) {
case 0x01: return 0; /* HardwareType_Icosa */
case 0x02: return 1; /* HardwareType_Copper */
case 0x04: return 3; /* HardwareType_Iowa */
default: return 4; /* HardwareType_Undefined */
}
} else {
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_10_0_0) {
switch (hardware_type) {
case 0x01: return 0; /* HardwareType_Icosa */
case 0x02: return 4; /* HardwareType_Calcio */
case 0x04: return 3; /* HardwareType_Iowa */
case 0x08: return 2; /* HardwareType_Hoag */
default: return 0xF; /* HardwareType_Undefined */
}
} else {
switch (hardware_type) {
case 0x01: return 0; /* HardwareType_Icosa */
case 0x02: return 4; /* HardwareType_Calcio */
case 0x04: return 3; /* HardwareType_Iowa */
case 0x08: return 2; /* HardwareType_Hoag */
case 0x10: return 5; /* HardwareType_Five */
default: return 0xF; /* HardwareType_Undefined */
}
}
}
}
}
/* Derive the HardwareType. */
uint32_t fuse_get_hardware_type(void) {
return fuse_get_hardware_type_with_firmware_check(ATMOSPHERE_TARGET_FIRMWARE_CURRENT);
}
/* Derive the HardwareState. */
uint32_t fuse_get_hardware_state(void) {
uint32_t fuse_reserved_odm4 = fuse_get_reserved_odm(4);
uint32_t hardware_state = (((fuse_reserved_odm4 >> 7) & 4) | (fuse_reserved_odm4 & 3));
switch (hardware_state) {
case 0x03: return 0; /* HardwareState_Development */
case 0x04: return 1; /* HardwareState_Production */
default: return 2; /* HardwareState_Undefined */
}
}
/* Derive the 16-byte HardwareInfo and copy to output buffer. */
void fuse_get_hardware_info(void *dst) {
volatile tegra_fuse_chip_common_t *fuse_chip = fuse_chip_common_get_regs();
uint32_t hw_info[0x4];
uint32_t ops_reserved = fuse_chip->FUSE_OPT_OPS_RESERVED & 0x3F;
uint32_t y_coord = fuse_chip->FUSE_OPT_Y_COORDINATE & 0x1FF;
uint32_t x_coord = fuse_chip->FUSE_OPT_X_COORDINATE & 0x1FF;
uint32_t wafer_id = fuse_chip->FUSE_OPT_WAFER_ID & 0x3F;
uint32_t lot_code_0 = fuse_chip->FUSE_OPT_LOT_CODE_0;
uint32_t lot_code_1 = fuse_chip->FUSE_OPT_LOT_CODE_1 & 0x0FFFFFFF;
uint32_t fab_code = fuse_chip->FUSE_OPT_FAB_CODE & 0x3F;
uint32_t vendor_code = fuse_chip->FUSE_OPT_VENDOR_CODE & 0xF;
/* Hardware Info = OPS_RESERVED || Y_COORD || X_COORD || WAFER_ID || LOT_CODE || FAB_CODE || VENDOR_ID */
hw_info[0] = (uint32_t)((lot_code_1 << 30) | (wafer_id << 24) | (x_coord << 15) | (y_coord << 6) | (ops_reserved));
hw_info[1] = (uint32_t)((lot_code_0 << 26) | (lot_code_1 >> 2));
hw_info[2] = (uint32_t)((fab_code << 26) | (lot_code_0 >> 6));
hw_info[3] = (uint32_t)(vendor_code);
memcpy(dst, hw_info, 0x10);
}
/* Check if have a new ODM fuse format. */
bool fuse_is_new_format(void) {
return ((fuse_get_reserved_odm(4) & 0x800) && (fuse_get_reserved_odm(0) == 0x8E61ECAE) && (fuse_get_reserved_odm(1) == 0xF2BA3BB2));
}
/* Get the DeviceUniqueKeyGeneration. */
uint32_t fuse_get_device_unique_key_generation(void) {
if (fuse_is_new_format()) {
return (fuse_get_reserved_odm(2) & 0x1F);
} else {
return 0;
}
}
/* Get the SocType from the HardwareType. */
uint32_t fuse_get_soc_type(void) {
switch (fuse_get_hardware_type()) {
case 0:
case 1:
return 0; /* SocType_Erista */
case 3:
case 2:
case 4:
case 5:
return 1; /* SocType_Mariko */
default:
return 0xF; /* SocType_Undefined */
}
}
/* Get the Regulator type. */
uint32_t fuse_get_regulator(void) {
if (fuse_get_soc_type() == 1) {
return ((fuse_get_reserved_odm(28) & 1) + 1); /* Regulator_Mariko_Max77812_A or Regulator_Mariko_Max77812_B */
} else {
return 0; /* Regulator_Erista_Max77621 */
}
}

View File

@ -1,484 +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/>.
*/
#ifndef FUSEE_FUSE_H
#define FUSEE_FUSE_H
#define FUSE_BASE 0x7000F800
#define FUSE_CHIP_BASE (FUSE_BASE + 0x98)
#define MAKE_FUSE_REG(n) MAKE_REG32(FUSE_BASE + n)
#define MAKE_FUSE_CHIP_REG(n) MAKE_REG32(FUSE_CHIP_BASE + n)
typedef struct {
uint32_t FUSE_FUSECTRL;
uint32_t FUSE_FUSEADDR;
uint32_t FUSE_FUSERDATA;
uint32_t FUSE_FUSEWDATA;
uint32_t FUSE_FUSETIME_RD1;
uint32_t FUSE_FUSETIME_RD2;
uint32_t FUSE_FUSETIME_PGM1;
uint32_t FUSE_FUSETIME_PGM2;
uint32_t FUSE_PRIV2INTFC_START;
uint32_t FUSE_FUSEBYPASS;
uint32_t FUSE_PRIVATEKEYDISABLE;
uint32_t FUSE_DISABLEREGPROGRAM;
uint32_t FUSE_WRITE_ACCESS_SW;
uint32_t FUSE_PWR_GOOD_SW;
uint32_t _0x38;
uint32_t FUSE_PRIV2RESHIFT;
uint32_t _0x40[0x3];
uint32_t FUSE_FUSETIME_RD3;
uint32_t _0x50[0xC];
uint32_t FUSE_PRIVATE_KEY0_NONZERO;
uint32_t FUSE_PRIVATE_KEY1_NONZERO;
uint32_t FUSE_PRIVATE_KEY2_NONZERO;
uint32_t FUSE_PRIVATE_KEY3_NONZERO;
uint32_t FUSE_PRIVATE_KEY4_NONZERO;
uint32_t _0x94;
} tegra_fuse_t;
typedef struct {
uint32_t _0x98[0x1A];
uint32_t FUSE_PRODUCTION_MODE;
uint32_t FUSE_JTAG_SECUREID_VALID;
uint32_t FUSE_ODM_LOCK;
uint32_t FUSE_OPT_OPENGL_EN;
uint32_t FUSE_SKU_INFO;
uint32_t FUSE_CPU_SPEEDO_0_CALIB;
uint32_t FUSE_CPU_IDDQ_CALIB;
uint32_t _0x11C[0x3];
uint32_t FUSE_OPT_FT_REV;
uint32_t FUSE_CPU_SPEEDO_1_CALIB;
uint32_t FUSE_CPU_SPEEDO_2_CALIB;
uint32_t FUSE_SOC_SPEEDO_0_CALIB;
uint32_t FUSE_SOC_SPEEDO_1_CALIB;
uint32_t FUSE_SOC_SPEEDO_2_CALIB;
uint32_t FUSE_SOC_IDDQ_CALIB;
uint32_t _0x144;
uint32_t FUSE_FA;
uint32_t FUSE_RESERVED_PRODUCTION;
uint32_t FUSE_HDMI_LANE0_CALIB;
uint32_t FUSE_HDMI_LANE1_CALIB;
uint32_t FUSE_HDMI_LANE2_CALIB;
uint32_t FUSE_HDMI_LANE3_CALIB;
uint32_t FUSE_ENCRYPTION_RATE;
uint32_t FUSE_PUBLIC_KEY[0x8];
uint32_t FUSE_TSENSOR1_CALIB;
uint32_t FUSE_TSENSOR2_CALIB;
uint32_t _0x18C;
uint32_t FUSE_OPT_CP_REV;
uint32_t FUSE_OPT_PFG;
uint32_t FUSE_TSENSOR0_CALIB;
uint32_t FUSE_FIRST_BOOTROM_PATCH_SIZE;
uint32_t FUSE_SECURITY_MODE;
uint32_t FUSE_PRIVATE_KEY[0x5];
uint32_t FUSE_ARM_JTAG_DIS;
uint32_t FUSE_BOOT_DEVICE_INFO;
uint32_t FUSE_RESERVED_SW;
uint32_t FUSE_OPT_VP9_DISABLE;
uint32_t FUSE_RESERVED_ODM0[0x8];
uint32_t FUSE_OBS_DIS;
uint32_t _0x1EC;
uint32_t FUSE_USB_CALIB;
uint32_t FUSE_SKU_DIRECT_CONFIG;
uint32_t FUSE_KFUSE_PRIVKEY_CTRL;
uint32_t FUSE_PACKAGE_INFO;
uint32_t FUSE_OPT_VENDOR_CODE;
uint32_t FUSE_OPT_FAB_CODE;
uint32_t FUSE_OPT_LOT_CODE_0;
uint32_t FUSE_OPT_LOT_CODE_1;
uint32_t FUSE_OPT_WAFER_ID;
uint32_t FUSE_OPT_X_COORDINATE;
uint32_t FUSE_OPT_Y_COORDINATE;
uint32_t FUSE_OPT_SEC_DEBUG_EN;
uint32_t FUSE_OPT_OPS_RESERVED;
uint32_t _0x224;
uint32_t FUSE_GPU_IDDQ_CALIB;
uint32_t FUSE_TSENSOR3_CALIB;
uint32_t FUSE_CLOCK_BOUNDOUT0;
uint32_t FUSE_CLOCK_BOUNDOUT1;
uint32_t _0x238[0x3];
uint32_t FUSE_OPT_SAMPLE_TYPE;
uint32_t FUSE_OPT_SUBREVISION;
uint32_t FUSE_OPT_SW_RESERVED_0;
uint32_t FUSE_OPT_SW_RESERVED_1;
uint32_t FUSE_TSENSOR4_CALIB;
uint32_t FUSE_TSENSOR5_CALIB;
uint32_t FUSE_TSENSOR6_CALIB;
uint32_t FUSE_TSENSOR7_CALIB;
uint32_t FUSE_OPT_PRIV_SEC_EN;
uint32_t _0x268[0x5];
uint32_t FUSE_FUSE2TSEC_DEBUG_DISABLE;
uint32_t FUSE_TSENSOR_COMMON;
uint32_t FUSE_OPT_CP_BIN;
uint32_t FUSE_OPT_GPU_DISABLE;
uint32_t FUSE_OPT_FT_BIN;
uint32_t FUSE_OPT_DONE_MAP;
uint32_t _0x294;
uint32_t FUSE_APB2JTAG_DISABLE;
uint32_t FUSE_ODM_INFO;
uint32_t _0x2A0[0x2];
uint32_t FUSE_ARM_CRYPT_DE_FEATURE;
uint32_t _0x2AC[0x5];
uint32_t FUSE_WOA_SKU_FLAG;
uint32_t FUSE_ECO_RESERVE_1;
uint32_t FUSE_GCPLEX_CONFIG_FUSE;
uint32_t FUSE_PRODUCTION_MONTH;
uint32_t FUSE_RAM_REPAIR_INDICATOR;
uint32_t FUSE_TSENSOR9_CALIB;
uint32_t _0x2D8;
uint32_t FUSE_VMIN_CALIBRATION;
uint32_t FUSE_AGING_SENSOR_CALIBRATION;
uint32_t FUSE_DEBUG_AUTHENTICATION;
uint32_t FUSE_SECURE_PROVISION_INDEX;
uint32_t FUSE_SECURE_PROVISION_INFO;
uint32_t FUSE_OPT_GPU_DISABLE_CP1;
uint32_t FUSE_SPARE_ENDIS;
uint32_t FUSE_ECO_RESERVE_0;
uint32_t _0x2FC[0x2];
uint32_t FUSE_RESERVED_CALIB0;
uint32_t FUSE_RESERVED_CALIB1;
uint32_t FUSE_OPT_GPU_TPC0_DISABLE;
uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP1;
uint32_t FUSE_OPT_CPU_DISABLE;
uint32_t FUSE_OPT_CPU_DISABLE_CP1;
uint32_t FUSE_TSENSOR10_CALIB;
uint32_t FUSE_TSENSOR10_CALIB_AUX;
uint32_t _0x324[0x5];
uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP2;
uint32_t FUSE_OPT_GPU_TPC1_DISABLE;
uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP1;
uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP2;
uint32_t FUSE_OPT_CPU_DISABLE_CP2;
uint32_t FUSE_OPT_GPU_DISABLE_CP2;
uint32_t FUSE_USB_CALIB_EXT;
uint32_t FUSE_RESERVED_FIELD;
uint32_t _0x358[0x9];
uint32_t FUSE_SPARE_REALIGNMENT_REG;
uint32_t FUSE_SPARE_BIT[0x20];
} tegra_fuse_chip_common_t;
typedef struct {
uint32_t _0x98[0x1A];
uint32_t FUSE_PRODUCTION_MODE;
uint32_t FUSE_JTAG_SECUREID_VALID;
uint32_t FUSE_ODM_LOCK;
uint32_t FUSE_OPT_OPENGL_EN;
uint32_t FUSE_SKU_INFO;
uint32_t FUSE_CPU_SPEEDO_0_CALIB;
uint32_t FUSE_CPU_IDDQ_CALIB;
uint32_t _0x11C[0x3];
uint32_t FUSE_OPT_FT_REV;
uint32_t FUSE_CPU_SPEEDO_1_CALIB;
uint32_t FUSE_CPU_SPEEDO_2_CALIB;
uint32_t FUSE_SOC_SPEEDO_0_CALIB;
uint32_t FUSE_SOC_SPEEDO_1_CALIB;
uint32_t FUSE_SOC_SPEEDO_2_CALIB;
uint32_t FUSE_SOC_IDDQ_CALIB;
uint32_t _0x144;
uint32_t FUSE_FA;
uint32_t FUSE_RESERVED_PRODUCTION;
uint32_t FUSE_HDMI_LANE0_CALIB;
uint32_t FUSE_HDMI_LANE1_CALIB;
uint32_t FUSE_HDMI_LANE2_CALIB;
uint32_t FUSE_HDMI_LANE3_CALIB;
uint32_t FUSE_ENCRYPTION_RATE;
uint32_t FUSE_PUBLIC_KEY[0x8];
uint32_t FUSE_TSENSOR1_CALIB;
uint32_t FUSE_TSENSOR2_CALIB;
uint32_t _0x18C;
uint32_t FUSE_OPT_CP_REV;
uint32_t FUSE_OPT_PFG;
uint32_t FUSE_TSENSOR0_CALIB;
uint32_t FUSE_FIRST_BOOTROM_PATCH_SIZE;
uint32_t FUSE_SECURITY_MODE;
uint32_t FUSE_PRIVATE_KEY[0x5];
uint32_t FUSE_ARM_JTAG_DIS;
uint32_t FUSE_BOOT_DEVICE_INFO;
uint32_t FUSE_RESERVED_SW;
uint32_t FUSE_OPT_VP9_DISABLE;
uint32_t FUSE_RESERVED_ODM0[0x8];
uint32_t FUSE_OBS_DIS;
uint32_t _0x1EC;
uint32_t FUSE_USB_CALIB;
uint32_t FUSE_SKU_DIRECT_CONFIG;
uint32_t FUSE_KFUSE_PRIVKEY_CTRL;
uint32_t FUSE_PACKAGE_INFO;
uint32_t FUSE_OPT_VENDOR_CODE;
uint32_t FUSE_OPT_FAB_CODE;
uint32_t FUSE_OPT_LOT_CODE_0;
uint32_t FUSE_OPT_LOT_CODE_1;
uint32_t FUSE_OPT_WAFER_ID;
uint32_t FUSE_OPT_X_COORDINATE;
uint32_t FUSE_OPT_Y_COORDINATE;
uint32_t FUSE_OPT_SEC_DEBUG_EN;
uint32_t FUSE_OPT_OPS_RESERVED;
uint32_t FUSE_SATA_CALIB; /* Erista only. */
uint32_t FUSE_GPU_IDDQ_CALIB;
uint32_t FUSE_TSENSOR3_CALIB;
uint32_t FUSE_CLOCK_BOUNDOUT0;
uint32_t FUSE_CLOCK_BOUNDOUT1;
uint32_t _0x238[0x3];
uint32_t FUSE_OPT_SAMPLE_TYPE;
uint32_t FUSE_OPT_SUBREVISION;
uint32_t FUSE_OPT_SW_RESERVED_0;
uint32_t FUSE_OPT_SW_RESERVED_1;
uint32_t FUSE_TSENSOR4_CALIB;
uint32_t FUSE_TSENSOR5_CALIB;
uint32_t FUSE_TSENSOR6_CALIB;
uint32_t FUSE_TSENSOR7_CALIB;
uint32_t FUSE_OPT_PRIV_SEC_EN;
uint32_t FUSE_PKC_DISABLE; /* Erista only. */
uint32_t _0x26C[0x4];
uint32_t FUSE_FUSE2TSEC_DEBUG_DISABLE;
uint32_t FUSE_TSENSOR_COMMON;
uint32_t FUSE_OPT_CP_BIN;
uint32_t FUSE_OPT_GPU_DISABLE;
uint32_t FUSE_OPT_FT_BIN;
uint32_t FUSE_OPT_DONE_MAP;
uint32_t _0x294;
uint32_t FUSE_APB2JTAG_DISABLE;
uint32_t FUSE_ODM_INFO;
uint32_t _0x2A0[0x2];
uint32_t FUSE_ARM_CRYPT_DE_FEATURE;
uint32_t _0x2AC[0x5];
uint32_t FUSE_WOA_SKU_FLAG;
uint32_t FUSE_ECO_RESERVE_1;
uint32_t FUSE_GCPLEX_CONFIG_FUSE;
uint32_t FUSE_PRODUCTION_MONTH;
uint32_t FUSE_RAM_REPAIR_INDICATOR;
uint32_t FUSE_TSENSOR9_CALIB;
uint32_t _0x2D8;
uint32_t FUSE_VMIN_CALIBRATION;
uint32_t FUSE_AGING_SENSOR_CALIBRATION;
uint32_t FUSE_DEBUG_AUTHENTICATION;
uint32_t FUSE_SECURE_PROVISION_INDEX;
uint32_t FUSE_SECURE_PROVISION_INFO;
uint32_t FUSE_OPT_GPU_DISABLE_CP1;
uint32_t FUSE_SPARE_ENDIS;
uint32_t FUSE_ECO_RESERVE_0;
uint32_t _0x2FC[0x2];
uint32_t FUSE_RESERVED_CALIB0;
uint32_t FUSE_RESERVED_CALIB1;
uint32_t FUSE_OPT_GPU_TPC0_DISABLE;
uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP1;
uint32_t FUSE_OPT_CPU_DISABLE;
uint32_t FUSE_OPT_CPU_DISABLE_CP1;
uint32_t FUSE_TSENSOR10_CALIB;
uint32_t FUSE_TSENSOR10_CALIB_AUX;
uint32_t FUSE_OPT_RAM_SVOP_DP; /* Erista only. */
uint32_t FUSE_OPT_RAM_SVOP_PDP; /* Erista only. */
uint32_t FUSE_OPT_RAM_SVOP_REG; /* Erista only. */
uint32_t FUSE_OPT_RAM_SVOP_SP; /* Erista only. */
uint32_t FUSE_OPT_RAM_SVOP_SMPDP; /* Erista only. */
uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP2;
uint32_t FUSE_OPT_GPU_TPC1_DISABLE;
uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP1;
uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP2;
uint32_t FUSE_OPT_CPU_DISABLE_CP2;
uint32_t FUSE_OPT_GPU_DISABLE_CP2;
uint32_t FUSE_USB_CALIB_EXT;
uint32_t FUSE_RESERVED_FIELD;
uint32_t _0x358[0x9];
uint32_t FUSE_SPARE_REALIGNMENT_REG;
uint32_t FUSE_SPARE_BIT[0x20];
} tegra_fuse_chip_erista_t;
typedef struct {
uint32_t FUSE_RESERVED_ODM8[0xE]; /* Mariko only. */
uint32_t FUSE_KEK[0x4]; /* Mariko only. */
uint32_t FUSE_BEK[0x4]; /* Mariko only. */
uint32_t _0xF0; /* Mariko only. */
uint32_t _0xF4; /* Mariko only. */
uint32_t _0xF8; /* Mariko only. */
uint32_t _0xFC; /* Mariko only. */
uint32_t FUSE_PRODUCTION_MODE;
uint32_t FUSE_JTAG_SECUREID_VALID;
uint32_t FUSE_ODM_LOCK;
uint32_t FUSE_OPT_OPENGL_EN;
uint32_t FUSE_SKU_INFO;
uint32_t FUSE_CPU_SPEEDO_0_CALIB;
uint32_t FUSE_CPU_IDDQ_CALIB;
uint32_t FUSE_RESERVED_ODM22[0x3]; /* Mariko only. */
uint32_t FUSE_OPT_FT_REV;
uint32_t FUSE_CPU_SPEEDO_1_CALIB;
uint32_t FUSE_CPU_SPEEDO_2_CALIB;
uint32_t FUSE_SOC_SPEEDO_0_CALIB;
uint32_t FUSE_SOC_SPEEDO_1_CALIB;
uint32_t FUSE_SOC_SPEEDO_2_CALIB;
uint32_t FUSE_SOC_IDDQ_CALIB;
uint32_t FUSE_RESERVED_ODM25; /* Mariko only. */
uint32_t FUSE_FA;
uint32_t FUSE_RESERVED_PRODUCTION;
uint32_t FUSE_HDMI_LANE0_CALIB;
uint32_t FUSE_HDMI_LANE1_CALIB;
uint32_t FUSE_HDMI_LANE2_CALIB;
uint32_t FUSE_HDMI_LANE3_CALIB;
uint32_t FUSE_ENCRYPTION_RATE;
uint32_t FUSE_PUBLIC_KEY[0x8];
uint32_t FUSE_TSENSOR1_CALIB;
uint32_t FUSE_TSENSOR2_CALIB;
uint32_t FUSE_OPT_SECURE_SCC_DIS; /* Mariko only. */
uint32_t FUSE_OPT_CP_REV;
uint32_t FUSE_OPT_PFG;
uint32_t FUSE_TSENSOR0_CALIB;
uint32_t FUSE_FIRST_BOOTROM_PATCH_SIZE;
uint32_t FUSE_SECURITY_MODE;
uint32_t FUSE_PRIVATE_KEY[0x5];
uint32_t FUSE_ARM_JTAG_DIS;
uint32_t FUSE_BOOT_DEVICE_INFO;
uint32_t FUSE_RESERVED_SW;
uint32_t FUSE_OPT_VP9_DISABLE;
uint32_t FUSE_RESERVED_ODM0[0x8];
uint32_t FUSE_OBS_DIS;
uint32_t _0x1EC; /* Mariko only. */
uint32_t FUSE_USB_CALIB;
uint32_t FUSE_SKU_DIRECT_CONFIG;
uint32_t FUSE_KFUSE_PRIVKEY_CTRL;
uint32_t FUSE_PACKAGE_INFO;
uint32_t FUSE_OPT_VENDOR_CODE;
uint32_t FUSE_OPT_FAB_CODE;
uint32_t FUSE_OPT_LOT_CODE_0;
uint32_t FUSE_OPT_LOT_CODE_1;
uint32_t FUSE_OPT_WAFER_ID;
uint32_t FUSE_OPT_X_COORDINATE;
uint32_t FUSE_OPT_Y_COORDINATE;
uint32_t FUSE_OPT_SEC_DEBUG_EN;
uint32_t FUSE_OPT_OPS_RESERVED;
uint32_t _0x224; /* Mariko only. */
uint32_t FUSE_GPU_IDDQ_CALIB;
uint32_t FUSE_TSENSOR3_CALIB;
uint32_t FUSE_CLOCK_BOUNDOUT0;
uint32_t FUSE_CLOCK_BOUNDOUT1;
uint32_t FUSE_RESERVED_ODM26[0x3]; /* Mariko only. */
uint32_t FUSE_OPT_SAMPLE_TYPE;
uint32_t FUSE_OPT_SUBREVISION;
uint32_t FUSE_OPT_SW_RESERVED_0;
uint32_t FUSE_OPT_SW_RESERVED_1;
uint32_t FUSE_TSENSOR4_CALIB;
uint32_t FUSE_TSENSOR5_CALIB;
uint32_t FUSE_TSENSOR6_CALIB;
uint32_t FUSE_TSENSOR7_CALIB;
uint32_t FUSE_OPT_PRIV_SEC_EN;
uint32_t FUSE_BOOT_SECURITY_INFO; /* Mariko only. */
uint32_t _0x26C; /* Mariko only. */
uint32_t _0x270; /* Mariko only. */
uint32_t _0x274; /* Mariko only. */
uint32_t _0x278; /* Mariko only. */
uint32_t FUSE_FUSE2TSEC_DEBUG_DISABLE;
uint32_t FUSE_TSENSOR_COMMON;
uint32_t FUSE_OPT_CP_BIN;
uint32_t FUSE_OPT_GPU_DISABLE;
uint32_t FUSE_OPT_FT_BIN;
uint32_t FUSE_OPT_DONE_MAP;
uint32_t FUSE_RESERVED_ODM29; /* Mariko only. */
uint32_t FUSE_APB2JTAG_DISABLE;
uint32_t FUSE_ODM_INFO;
uint32_t _0x2A0[0x2];
uint32_t FUSE_ARM_CRYPT_DE_FEATURE;
uint32_t _0x2AC;
uint32_t _0x2B0; /* Mariko only. */
uint32_t _0x2B4; /* Mariko only. */
uint32_t _0x2B8; /* Mariko only. */
uint32_t _0x2BC; /* Mariko only. */
uint32_t FUSE_WOA_SKU_FLAG;
uint32_t FUSE_ECO_RESERVE_1;
uint32_t FUSE_GCPLEX_CONFIG_FUSE;
uint32_t FUSE_PRODUCTION_MONTH;
uint32_t FUSE_RAM_REPAIR_INDICATOR;
uint32_t FUSE_TSENSOR9_CALIB;
uint32_t _0x2D8;
uint32_t FUSE_VMIN_CALIBRATION;
uint32_t FUSE_AGING_SENSOR_CALIBRATION;
uint32_t FUSE_DEBUG_AUTHENTICATION;
uint32_t FUSE_SECURE_PROVISION_INDEX;
uint32_t FUSE_SECURE_PROVISION_INFO;
uint32_t FUSE_OPT_GPU_DISABLE_CP1;
uint32_t FUSE_SPARE_ENDIS;
uint32_t FUSE_ECO_RESERVE_0;
uint32_t _0x2FC[0x2];
uint32_t FUSE_RESERVED_CALIB0;
uint32_t FUSE_RESERVED_CALIB1;
uint32_t FUSE_OPT_GPU_TPC0_DISABLE;
uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP1;
uint32_t FUSE_OPT_CPU_DISABLE;
uint32_t FUSE_OPT_CPU_DISABLE_CP1;
uint32_t FUSE_TSENSOR10_CALIB;
uint32_t FUSE_TSENSOR10_CALIB_AUX;
uint32_t _0x324; /* Mariko only. */
uint32_t _0x328; /* Mariko only. */
uint32_t _0x32C; /* Mariko only. */
uint32_t _0x330; /* Mariko only. */
uint32_t _0x334; /* Mariko only. */
uint32_t FUSE_OPT_GPU_TPC0_DISABLE_CP2;
uint32_t FUSE_OPT_GPU_TPC1_DISABLE;
uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP1;
uint32_t FUSE_OPT_GPU_TPC1_DISABLE_CP2;
uint32_t FUSE_OPT_CPU_DISABLE_CP2;
uint32_t FUSE_OPT_GPU_DISABLE_CP2;
uint32_t FUSE_USB_CALIB_EXT;
uint32_t FUSE_RESERVED_FIELD;
uint32_t _0x358[0x9];
uint32_t FUSE_SPARE_REALIGNMENT_REG;
uint32_t FUSE_SPARE_BIT[0x1E];
} tegra_fuse_chip_mariko_t;
static inline volatile tegra_fuse_t *fuse_get_regs(void)
{
return (volatile tegra_fuse_t *)FUSE_BASE;
}
static inline volatile tegra_fuse_chip_common_t *fuse_chip_common_get_regs(void)
{
return (volatile tegra_fuse_chip_common_t *)FUSE_CHIP_BASE;
}
static inline volatile tegra_fuse_chip_erista_t *fuse_chip_erista_get_regs(void)
{
return (volatile tegra_fuse_chip_erista_t *)FUSE_CHIP_BASE;
}
static inline volatile tegra_fuse_chip_mariko_t *fuse_chip_mariko_get_regs(void)
{
return (volatile tegra_fuse_chip_mariko_t *)FUSE_CHIP_BASE;
}
void fuse_init(void);
void fuse_disable_programming(void);
void fuse_disable_private_key(void);
void fuse_enable_power(void);
void fuse_disable_power(void);
uint32_t fuse_get_sku_info(void);
uint32_t fuse_get_spare_bit(uint32_t index);
uint32_t fuse_get_reserved_odm(uint32_t index);
uint32_t fuse_get_bootrom_patch_version(void);
uint64_t fuse_get_device_id(void);
uint32_t fuse_get_dram_id(void);
uint32_t fuse_get_hardware_type_with_firmware_check(uint32_t target_firmware);
uint32_t fuse_get_hardware_type(void);
uint32_t fuse_get_retail_type(void);
void fuse_get_hardware_info(void *dst);
bool fuse_is_new_format(void);
uint32_t fuse_get_device_unique_key_generation(void);
uint32_t fuse_get_soc_type(void);
uint32_t fuse_get_regulator(void);
uint32_t fuse_hw_read(uint32_t addr);
void fuse_hw_write(uint32_t value, uint32_t addr);
void fuse_hw_sense(void);
#endif

View File

@ -1,78 +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 <string.h>
#include <stdint.h>
#include <errno.h>
#include "gpio.h"
#include "utils.h"
/* Set GPIO's value. */
static void gpio_register_set(uint32_t pin, bool do_set, uint32_t offset) {
volatile tegra_gpio_t *gpio = gpio_get_regs();
/* Retrieve the register set that corresponds to the given pin and offset. */
volatile uint32_t *cluster = (uint32_t *)((uintptr_t)&gpio->bank[(pin >> GPIO_BANK_SHIFT)] + offset);
/* Figure out the offset into the cluster, and the mask to be used. */
uint32_t port = ((pin >> GPIO_PORT_SHIFT) & GPIO_PORT_MASK);
uint32_t mask = (1 << (pin & GPIO_PIN_MASK));
/* Set or clear the bit, as appropriate. */
if (do_set)
cluster[port] |= mask;
else
cluster[port] &= ~mask;
/* Dummy read. */
cluster[port];
}
/* Get GPIO's value. */
static bool gpio_register_get(uint32_t pin, uint32_t offset) {
volatile tegra_gpio_t *gpio = gpio_get_regs();
/* Retrieve the register set that corresponds to the given pin and offset. */
volatile uint32_t *cluster = (uint32_t *)((uintptr_t)&gpio->bank[(pin >> GPIO_BANK_SHIFT)] + offset);
/* Figure out the offset into the cluster, and the mask to be used. */
uint32_t port = ((pin >> GPIO_PORT_SHIFT) & GPIO_PORT_MASK);
uint32_t mask = (1 << (pin & GPIO_PIN_MASK));
/* Convert the given value to a boolean. */
return !!(cluster[port] & mask);
}
/* Configure GPIO's mode. */
void gpio_configure_mode(uint32_t pin, uint32_t mode) {
gpio_register_set(pin, mode == GPIO_MODE_GPIO, offsetof(tegra_gpio_bank_t, config));
}
/* Configure GPIO's direction. */
void gpio_configure_direction(uint32_t pin, uint32_t dir) {
gpio_register_set(pin, dir == GPIO_DIRECTION_OUTPUT, offsetof(tegra_gpio_bank_t, direction));
}
/* Write to GPIO. */
void gpio_write(uint32_t pin, uint32_t value) {
gpio_register_set(pin, value == GPIO_LEVEL_HIGH, offsetof(tegra_gpio_bank_t, out));
}
/* Read from GPIO. */
uint32_t gpio_read(uint32_t pin) {
return gpio_register_get(pin, offsetof(tegra_gpio_bank_t, in));
}

View File

@ -1,127 +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/>.
*/
#ifndef FUSEE_GPIO_H
#define FUSEE_GPIO_H
#include <stdint.h>
#define GPIO_BASE 0x6000D000
#define MAKE_GPIO_REG(n) MAKE_REG32(GPIO_BASE + n)
#define TEGRA_GPIO_PORTS 4
#define TEGRA_GPIO_BANKS 8
#define GPIO_BANK_SHIFT 5
#define GPIO_PORT_SHIFT 3
#define GPIO_PORT_MASK 0x03
#define GPIO_PIN_MASK 0x07
typedef enum {
TEGRA_GPIO_PORT_A = 0,
TEGRA_GPIO_PORT_B = 1,
TEGRA_GPIO_PORT_C = 2,
TEGRA_GPIO_PORT_D = 3,
TEGRA_GPIO_PORT_E = 4,
TEGRA_GPIO_PORT_F = 5,
TEGRA_GPIO_PORT_G = 6,
TEGRA_GPIO_PORT_H = 7,
TEGRA_GPIO_PORT_I = 8,
TEGRA_GPIO_PORT_J = 9,
TEGRA_GPIO_PORT_K = 10,
TEGRA_GPIO_PORT_L = 11,
TEGRA_GPIO_PORT_M = 12,
TEGRA_GPIO_PORT_N = 13,
TEGRA_GPIO_PORT_O = 14,
TEGRA_GPIO_PORT_P = 15,
TEGRA_GPIO_PORT_Q = 16,
TEGRA_GPIO_PORT_R = 17,
TEGRA_GPIO_PORT_S = 18,
TEGRA_GPIO_PORT_T = 19,
TEGRA_GPIO_PORT_U = 20,
TEGRA_GPIO_PORT_V = 21,
TEGRA_GPIO_PORT_W = 22,
TEGRA_GPIO_PORT_X = 23,
TEGRA_GPIO_PORT_Y = 24,
TEGRA_GPIO_PORT_Z = 25,
TEGRA_GPIO_PORT_AA = 26,
TEGRA_GPIO_PORT_BB = 27,
TEGRA_GPIO_PORT_CC = 28,
TEGRA_GPIO_PORT_DD = 29,
TEGRA_GPIO_PORT_EE = 30,
TEGRA_GPIO_PORT_FF = 31,
} tegra_gpio_port;
typedef struct {
uint32_t config[TEGRA_GPIO_PORTS];
uint32_t direction[TEGRA_GPIO_PORTS];
uint32_t out[TEGRA_GPIO_PORTS];
uint32_t in[TEGRA_GPIO_PORTS];
uint32_t int_status[TEGRA_GPIO_PORTS];
uint32_t int_enable[TEGRA_GPIO_PORTS];
uint32_t int_level[TEGRA_GPIO_PORTS];
uint32_t int_clear[TEGRA_GPIO_PORTS];
uint32_t masked_config[TEGRA_GPIO_PORTS];
uint32_t masked_dir_out[TEGRA_GPIO_PORTS];
uint32_t masked_out[TEGRA_GPIO_PORTS];
uint32_t masked_in[TEGRA_GPIO_PORTS];
uint32_t masked_int_status[TEGRA_GPIO_PORTS];
uint32_t masked_int_enable[TEGRA_GPIO_PORTS];
uint32_t masked_int_level[TEGRA_GPIO_PORTS];
uint32_t masked_int_clear[TEGRA_GPIO_PORTS];
} tegra_gpio_bank_t;
typedef struct {
tegra_gpio_bank_t bank[TEGRA_GPIO_BANKS];
} tegra_gpio_t;
static inline volatile tegra_gpio_t *gpio_get_regs(void)
{
return (volatile tegra_gpio_t *)GPIO_BASE;
}
#define TEGRA_GPIO(port, offset) \
((TEGRA_GPIO_PORT_##port * 8) + offset)
/* Mode select */
#define GPIO_MODE_SFIO 0
#define GPIO_MODE_GPIO 1
/* Direction */
#define GPIO_DIRECTION_INPUT 0
#define GPIO_DIRECTION_OUTPUT 1
/* Level */
#define GPIO_LEVEL_LOW 0
#define GPIO_LEVEL_HIGH 1
/* Named GPIOs */
#define GPIO_BUTTON_VOL_DOWN TEGRA_GPIO(X, 7)
#define GPIO_BUTTON_VOL_UP TEGRA_GPIO(X, 6)
#define GPIO_MICROSD_CARD_DETECT TEGRA_GPIO(Z, 1)
#define GPIO_MICROSD_WRITE_PROTECT TEGRA_GPIO(Z, 4)
#define GPIO_MICROSD_SUPPLY_ENABLE TEGRA_GPIO(E, 4)
#define GPIO_LCD_BL_P5V TEGRA_GPIO(I, 0)
#define GPIO_LCD_BL_N5V TEGRA_GPIO(I, 1)
#define GPIO_LCD_BL_PWM TEGRA_GPIO(V, 0)
#define GPIO_LCD_BL_EN TEGRA_GPIO(V, 1)
#define GPIO_LCD_BL_RST TEGRA_GPIO(V, 2)
void gpio_configure_mode(uint32_t pin, uint32_t mode);
void gpio_configure_direction(uint32_t pin, uint32_t dir);
void gpio_write(uint32_t pin, uint32_t value);
uint32_t gpio_read(uint32_t pin);
#endif

View File

@ -1,327 +0,0 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer
* 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 "hwinit.h"
#include "apb_misc.h"
#include "car.h"
#include "di.h"
#include "fuse.h"
#include "gpio.h"
#include "i2c.h"
#include "max77620.h"
#include "mc.h"
#include "pinmux.h"
#include "pmc.h"
#include "se.h"
#include "sdram.h"
#include "sysctr0.h"
#include "sysreg.h"
#include "timers.h"
#include "uart.h"
/* Determine the current SoC for Mariko specific code. */
static bool is_soc_mariko() {
return (fuse_get_soc_type() == 1);
}
static void config_oscillators(void) {
volatile tegra_car_t *car = car_get_regs();
volatile tegra_pmc_t *pmc = pmc_get_regs();
car->spare_reg0 = ((car->spare_reg0 & 0xFFFFFFF3) | 4);
SYSCTR0_CNTFID0_0 = 19200000;
TIMERUS_USEC_CFG_0 = 0x45F;
car->osc_ctrl = 0x50000071;
pmc->osc_edpd_over = ((pmc->osc_edpd_over & 0xFFFFFF81) | 0xE);
pmc->osc_edpd_over = ((pmc->osc_edpd_over & 0xFFBFFFFF) | 0x400000);
pmc->cntrl2 = ((pmc->cntrl2 & 0xFFFFEFFF) | 0x1000);
pmc->scratch188 = ((pmc->scratch188 & 0xFCFFFFFF) | 0x2000000);
car->clk_sys_rate = 0x10;
car->pllmb_base &= 0xBFFFFFFF;
pmc->tsc_mult = ((pmc->tsc_mult & 0xFFFF0000) | 0x249F); /* 0x249F = 19200000 * (16 / 32.768 kHz) */
car->sclk_brst_pol = 0x20004444;
car->super_sclk_div = 0x80000000;
car->clk_sys_rate = 2;
}
static void config_gpios(void) {
volatile tegra_pinmux_t *pinmux = pinmux_get_regs();
bool is_mariko = is_soc_mariko();
if (is_mariko) {
uint32_t hardware_type = fuse_get_hardware_type();
/* Only for HardwareType_Iowa and HardwareType_Five. */
if ((hardware_type == 3) || (hardware_type == 5)) {
pinmux->uart2_tx = 0;
pinmux->uart3_tx = 0;
gpio_configure_mode(TEGRA_GPIO(G, 0), GPIO_MODE_GPIO);
gpio_configure_mode(TEGRA_GPIO(D, 1), GPIO_MODE_GPIO);
gpio_configure_direction(TEGRA_GPIO(G, 0), GPIO_DIRECTION_INPUT);
gpio_configure_direction(TEGRA_GPIO(D, 1), GPIO_DIRECTION_INPUT);
}
} else {
pinmux->uart2_tx = 0;
pinmux->uart3_tx = 0;
}
pinmux->pe6 = PINMUX_INPUT;
pinmux->ph6 = PINMUX_INPUT;
if (!is_mariko) {
gpio_configure_mode(TEGRA_GPIO(G, 0), GPIO_MODE_GPIO);
gpio_configure_mode(TEGRA_GPIO(D, 1), GPIO_MODE_GPIO);
}
gpio_configure_mode(TEGRA_GPIO(E, 6), GPIO_MODE_GPIO);
gpio_configure_mode(TEGRA_GPIO(H, 6), GPIO_MODE_GPIO);
if (!is_mariko) {
gpio_configure_direction(TEGRA_GPIO(G, 0), GPIO_DIRECTION_INPUT);
gpio_configure_direction(TEGRA_GPIO(D, 1), GPIO_DIRECTION_INPUT);
}
gpio_configure_direction(TEGRA_GPIO(E, 6), GPIO_DIRECTION_INPUT);
gpio_configure_direction(TEGRA_GPIO(H, 6), GPIO_DIRECTION_INPUT);
i2c_config(I2C_1);
i2c_config(I2C_5);
uart_config(UART_A);
/* Configure volume up/down buttons as inputs. */
gpio_configure_mode(GPIO_BUTTON_VOL_UP, GPIO_MODE_GPIO);
gpio_configure_mode(GPIO_BUTTON_VOL_DOWN, GPIO_MODE_GPIO);
gpio_configure_direction(GPIO_BUTTON_VOL_UP, GPIO_DIRECTION_INPUT);
gpio_configure_direction(GPIO_BUTTON_VOL_DOWN, GPIO_DIRECTION_INPUT);
if (is_mariko) {
/* Configure home button as input. */
gpio_configure_mode(TEGRA_GPIO(Y, 1), GPIO_MODE_GPIO);
gpio_configure_direction(TEGRA_GPIO(Y, 1), GPIO_DIRECTION_INPUT);
}
}
static void mbist_workaround(void) {
volatile tegra_car_t *car = car_get_regs();
car->clk_source_sor1 = ((car->clk_source_sor1 | 0x8000) & 0xFFFFBFFF);
car->plld_base |= 0x40800000u;
car->rst_dev_y_clr = 0x40;
car->rst_dev_x_clr = 0x40000;
car->rst_dev_l_clr = 0x18000000;
udelay(2);
/* Setup I2S. */
MAKE_I2S_REG(0x0A0) |= 0x400;
MAKE_I2S_REG(0x088) &= 0xFFFFFFFE;
MAKE_I2S_REG(0x1A0) |= 0x400;
MAKE_I2S_REG(0x188) &= 0xFFFFFFFE;
MAKE_I2S_REG(0x2A0) |= 0x400;
MAKE_I2S_REG(0x288) &= 0xFFFFFFFE;
MAKE_I2S_REG(0x3A0) |= 0x400;
MAKE_I2S_REG(0x388) &= 0xFFFFFFFE;
MAKE_I2S_REG(0x4A0) |= 0x400;
MAKE_I2S_REG(0x488) &= 0xFFFFFFFE;
MAKE_DI_REG(DC_COM_DSC_TOP_CTL) |= 4;
MAKE_VIC_REG(0x8C) = 0xFFFFFFFF;
udelay(2);
/* Set devices in reset. */
car->rst_dev_y_set = 0x40;
car->rst_dev_l_set = 0x18000000;
car->rst_dev_x_set = 0x40000;
/* Clock out enables. */
car->clk_out_enb_h = 0xC0;
car->clk_out_enb_l = 0x80000130;
car->clk_out_enb_u = 0x1F00200;
car->clk_out_enb_v = 0x80400808;
car->clk_out_enb_w = 0x402000FC;
car->clk_out_enb_x = 0x23000780;
car->clk_out_enb_y = 0x300;
/* LVL2 clock gate overrides. */
car->lvl2_clk_gate_ovra = 0;
car->lvl2_clk_gate_ovrb = 0;
car->lvl2_clk_gate_ovrc = 0;
car->lvl2_clk_gate_ovrd = 0;
car->lvl2_clk_gate_ovre = 0;
/* Configure clock sources. */
car->plld_base &= 0x1F7FFFFF;
car->clk_source_sor1 &= 0xFFFF3FFF;
car->clk_source_vi = ((car->clk_source_vi & 0x1FFFFFFF) | 0x80000000);
car->clk_source_host1x = ((car->clk_source_host1x & 0x1FFFFFFF) | 0x80000000);
car->clk_source_nvenc = ((car->clk_source_nvenc & 0x1FFFFFFF) | 0x80000000);
}
static void config_se_brom(void) {
volatile tegra_fuse_chip_common_t *fuse_chip = fuse_chip_common_get_regs();
volatile tegra_se_t *se = se_get_regs();
volatile tegra_pmc_t *pmc = pmc_get_regs();
/* Bootrom part we skipped. */
uint32_t sbk[4] = {fuse_chip->FUSE_PRIVATE_KEY[0], fuse_chip->FUSE_PRIVATE_KEY[1], fuse_chip->FUSE_PRIVATE_KEY[2], fuse_chip->FUSE_PRIVATE_KEY[3]};
set_aes_keyslot(0xE, sbk, 0x10);
/* Lock SBK from being read. */
se->SE_CRYPTO_KEYTABLE_ACCESS[0xE] = 0x7E;
/* This memset needs to happen here, else TZRAM will behave weirdly later on. */
memset((void *)0x7C010000, 0, 0x10000);
pmc->crypto_op = 0;
se->SE_INT_STATUS = 0x1F;
/* Lock SSK (although it's not set and unused anyways). */
se->SE_CRYPTO_KEYTABLE_ACCESS[0xF] = 0x7E;
/* Clear the boot reason to avoid problems later */
pmc->scratch200 = 0;
pmc->rst_status = 0;
}
void nx_hwinit(bool enable_log) {
volatile tegra_pmc_t *pmc = pmc_get_regs();
volatile tegra_car_t *car = car_get_regs();
bool is_mariko = is_soc_mariko();
if (!is_mariko) {
/* Bootrom stuff we skipped by going through RCM. */
config_se_brom();
AHB_AHB_SPARE_REG_0 &= 0xFFFFFF9F;
pmc->scratch49 = (((pmc->scratch49 >> 1) << 1) & 0xFFFFFFFD);
/* Apply the memory built-in self test workaround. */
mbist_workaround();
}
/* Enable SE clock. */
clkrst_reboot(CARDEVICE_SE);
if (is_mariko) {
/* Lock the SE clock. */
car->clk_source_se |= 0x100;
}
/* Initialize the fuse driver. */
fuse_init();
if (!is_mariko) {
/* Initialize the memory controller. */
mc_enable();
}
/* Configure oscillators. */
config_oscillators();
/* Disable pinmux tristate input clamping. */
APB_MISC_PP_PINMUX_GLOBAL_0 = 0;
/* Configure GPIOs. */
config_gpios();
/* UART debugging. */
if (enable_log) {
clkrst_reboot(CARDEVICE_UARTA);
uart_init(UART_A, 115200);
}
/* Enable CL-DVFS clock. */
clkrst_reboot(CARDEVICE_CL_DVFS);
/* Enable I2C1 clock. */
clkrst_reboot(CARDEVICE_I2C1);
/* Enable I2C5 clock. */
clkrst_reboot(CARDEVICE_I2C5);
/* Enable TZRAM clock. */
clkrst_reboot(CARDEVICE_TZRAM);
/* Initialize I2C5. */
i2c_init(I2C_5);
/* Configure the PMIC. */
if (is_mariko) {
uint8_t val = 0x40;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CNFGBBC, &val, 1);
val = 0x78;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, &val, 1);
} else {
uint8_t val = 0x40;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CNFGBBC, &val, 1);
val = 0x60;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, &val, 1);
val = 0x38;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_CFG0, &val, 1);
val = 0x3A;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_CFG1, &val, 1);
val = 0x38;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_CFG2, &val, 1);
val = 0xF;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_LDO4, &val, 1);
val = 0xC7;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_LDO8, &val, 1);
val = 0x4F;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_SD0, &val, 1);
val = 0x29;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_SD1, &val, 1);
val = 0x1B;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_SD3, &val, 1);
/* NOTE: [3.0.0+] This was added. */
val = 0x22;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_GPIO3, &val, 1);
/* TODO: In 3.x+, if the unit is SDEV, the MBLPD bit is set. */
/*
i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CNFGGLBL1, &val, 1);
val |= 0x40;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CNFGGLBL1, &val, 1);
*/
}
/* Configure SD0 voltage. */
uint8_t val = 0x24;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_SD0, &val, 1);
/* Enable LDO8 in HardwareType_Hoag only. */
if (is_mariko && (fuse_get_hardware_type() == 2)) {
val = 0xE8;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_LDO8_CFG, &val, 1);
}
/* Initialize I2C1. */
i2c_init(I2C_1);
/* Set super clock burst policy. */
car->sclk_brst_pol = ((car->sclk_brst_pol & 0xFFFF8888) | 0x3333);
if (is_mariko) {
/* Mariko only PMC configuration for TZRAM. */
pmc->tzram_pwr_cntrl &= 0xFFFFFFFE;
pmc->tzram_non_sec_disable = 0x3;
pmc->tzram_sec_disable = 0x3;
}
/* Save SDRAM parameters to scratch. */
sdram_save_params(sdram_get_params(fuse_get_dram_id()));
/* Initialize SDRAM. */
sdram_init();
}

View File

@ -1,29 +0,0 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer
* 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/>.
*/
#ifndef FUSEE_HWINIT_H_
#define FUSEE_HWINIT_H_
#include <stdbool.h>
#define I2S_BASE 0x702D1000
#define MAKE_I2S_REG(n) MAKE_REG32(I2S_BASE + n)
void nx_hwinit(bool enable_log);
#endif

View File

@ -1,252 +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 "i2c.h"
#include "utils.h"
#include "timers.h"
#include "pinmux.h"
/* Prototypes for internal commands. */
volatile tegra_i2c_t *i2c_get_registers_from_id(I2CDevice id);
void i2c_load_config(volatile tegra_i2c_t *regs);
bool i2c_query(I2CDevice id, uint8_t device, uint8_t r, void *dst, size_t dst_size);
bool i2c_send(I2CDevice id, uint8_t device, uint8_t r, void *src, size_t src_size);
bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src_size);
bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_size);
/* Configure I2C pinmux. */
void i2c_config(I2CDevice id) {
volatile tegra_pinmux_t *pinmux = pinmux_get_regs();
switch (id) {
case I2C_1:
pinmux->gen1_i2c_scl = PINMUX_INPUT;
pinmux->gen1_i2c_sda = PINMUX_INPUT;
break;
case I2C_2:
pinmux->gen2_i2c_scl = PINMUX_INPUT;
pinmux->gen2_i2c_sda = PINMUX_INPUT;
break;
case I2C_3:
pinmux->gen3_i2c_scl = PINMUX_INPUT;
pinmux->gen3_i2c_sda = PINMUX_INPUT;
break;
case I2C_4:
pinmux->cam_i2c_scl = PINMUX_INPUT;
pinmux->cam_i2c_sda = PINMUX_INPUT;
break;
case I2C_5:
pinmux->pwr_i2c_scl = PINMUX_INPUT;
pinmux->pwr_i2c_sda = PINMUX_INPUT;
break;
case I2C_6:
/* Unused. */
break;
default: break;
}
}
/* Initialize I2C based on registers. */
void i2c_init(I2CDevice id) {
volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id);
/* Setup divisor, and clear the bus. */
regs->I2C_I2C_CLK_DIVISOR_REGISTER_0 = 0x50001;
regs->I2C_I2C_BUS_CLEAR_CONFIG_0 = 0x90003;
/* Load hardware configuration. */
i2c_load_config(regs);
/* Wait a while until BUS_CLEAR_DONE is set. */
for (unsigned int i = 0; i < 10; i++) {
udelay(20000);
if (regs->I2C_INTERRUPT_STATUS_REGISTER_0 & 0x800) {
break;
}
}
/* Read the BUS_CLEAR_STATUS. Result doesn't matter. */
regs->I2C_I2C_BUS_CLEAR_STATUS_0;
/* Read and set the Interrupt Status. */
uint32_t int_status = regs->I2C_INTERRUPT_STATUS_REGISTER_0;
regs->I2C_INTERRUPT_STATUS_REGISTER_0 = int_status;
}
/* Sets a bit in a PMIC register over I2C during CPU shutdown. */
void i2c_send_pmic_cpu_shutdown_cmd(void) {
uint32_t val = 0;
/* PMIC == Device 4:3C. */
i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1);
val |= 4;
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1);
}
/* Queries the value of TI charger bit over I2C. */
bool i2c_query_ti_charger_bit_7(void) {
uint32_t val = 0;
/* TI Charger = Device 0:6B. */
i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
return (val & 0x80) != 0;
}
/* Clears TI charger bit over I2C. */
void i2c_clear_ti_charger_bit_7(void) {
uint32_t val = 0;
/* TI Charger = Device 0:6B. */
i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
val &= 0x7F;
i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
}
/* Sets TI charger bit over I2C. */
void i2c_set_ti_charger_bit_7(void) {
uint32_t val = 0;
/* TI Charger = Device 0:6B. */
i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
val |= 0x80;
i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
}
/* Get registers pointer based on I2C ID. */
volatile tegra_i2c_t *i2c_get_registers_from_id(I2CDevice id) {
switch (id) {
case I2C_1:
return I2C1_REGS;
case I2C_2:
return I2C2_REGS;
case I2C_3:
return I2C3_REGS;
case I2C_4:
return I2C4_REGS;
case I2C_5:
return I2C5_REGS;
case I2C_6:
return I2C6_REGS;
default:
generic_panic();
}
return NULL;
}
/* Load hardware config for I2C4. */
void i2c_load_config(volatile tegra_i2c_t *regs) {
/* Set MSTR_CONFIG_LOAD, TIMEOUT_CONFIG_LOAD, undocumented bit. */
regs->I2C_I2C_CONFIG_LOAD_0 = 0x25;
/* Wait a bit for master config to be loaded. */
for (unsigned int i = 0; i < 20; i++) {
udelay(1);
if (!(regs->I2C_I2C_CONFIG_LOAD_0 & 1)) {
break;
}
}
}
/* Reads a register from a device over I2C, writes result to output. */
bool i2c_query(I2CDevice id, uint8_t device, uint8_t r, void *dst, size_t dst_size) {
volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id);
uint32_t val = r;
/* Write single byte register ID to device. */
if (!i2c_write(regs, device, &val, 1)) {
return false;
}
/* Limit output size to 32-bits. */
if (dst_size > 4) {
return false;
}
return i2c_read(regs, device, dst, dst_size);
}
/* Writes a value to a register over I2C. */
bool i2c_send(I2CDevice id, uint8_t device, uint8_t r, void *src, size_t src_size) {
uint32_t val = r;
if (src_size == 0) {
return true;
} else if (src_size <= 3) {
memcpy(((uint8_t *)&val) + 1, src, src_size);
return i2c_write(i2c_get_registers_from_id(id), device, &val, src_size + 1);
} else {
return false;
}
}
/* Writes bytes to device over I2C. */
bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src_size) {
if (src_size > 4) {
return false;
} else if (src_size == 0) {
return true;
}
/* Set device for 7-bit write mode. */
regs->I2C_I2C_CMD_ADDR0_0 = device << 1;
/* Load in data to write. */
regs->I2C_I2C_CMD_DATA1_0 = read32le(src, 0);
/* Set config with LENGTH = src_size, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */
regs->I2C_I2C_CNFG_0 = ((src_size << 1) - 2) | 0x2800;
i2c_load_config(regs);
/* Config |= SEND; */
regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200);
while (regs->I2C_I2C_STATUS_0 & 0x100) {
/* Wait until not busy. */
}
/* Return CMD1_STAT == SL1_XFER_SUCCESSFUL. */
return (regs->I2C_I2C_STATUS_0 & 0xF) == 0;
}
/* Reads bytes from device over I2C. */
bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_size) {
if (dst_size > 4) {
return false;
} else if (dst_size == 0) {
return true;
}
/* Set device for 7-bit read mode. */
regs->I2C_I2C_CMD_ADDR0_0 = (device << 1) | 1;
/* Set config with LENGTH = dst_size, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */
regs->I2C_I2C_CNFG_0 = ((dst_size << 1) - 2) | 0x2840;
i2c_load_config(regs);
/* Config |= SEND; */
regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200);
while (regs->I2C_I2C_STATUS_0 & 0x100) {
/* Wait until not busy. */
}
/* Ensure success. */
if ((regs->I2C_I2C_STATUS_0 & 0xF) != 0) {
return false;
}
uint32_t val = regs->I2C_I2C_CMD_DATA1_0;
memcpy(dst, &val, dst_size);
return true;
}

View File

@ -1,107 +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/>.
*/
#ifndef FUSEE_I2C_H
#define FUSEE_I2C_H
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#define I2C1234_BASE 0x7000C000
#define I2C56_BASE 0x7000D000
#define MAX77621_CPU_I2C_ADDR 0x1B
#define MAX77621_GPU_I2C_ADDR 0x1C
#define MAX77812_PHASE31_CPU_I2C_ADDR 0x31
#define MAX77812_PHASE211_CPU_I2C_ADDR 0x33
#define MAX17050_I2C_ADDR 0x36
#define MAX77620_PWR_I2C_ADDR 0x3C
#define MAX77620_RTC_I2C_ADDR 0x68
#define BQ24193_I2C_ADDR 0x6B
typedef enum {
I2C_1 = 0,
I2C_2 = 1,
I2C_3 = 2,
I2C_4 = 3,
I2C_5 = 4,
I2C_6 = 5,
} I2CDevice;
typedef struct {
uint32_t I2C_I2C_CNFG_0;
uint32_t I2C_I2C_CMD_ADDR0_0;
uint32_t I2C_I2C_CMD_ADDR1_0;
uint32_t I2C_I2C_CMD_DATA1_0;
uint32_t I2C_I2C_CMD_DATA2_0;
uint32_t _0x14;
uint32_t _0x18;
uint32_t I2C_I2C_STATUS_0;
uint32_t I2C_I2C_SL_CNFG_0;
uint32_t I2C_I2C_SL_RCVD_0;
uint32_t I2C_I2C_SL_STATUS_0;
uint32_t I2C_I2C_SL_ADDR1_0;
uint32_t I2C_I2C_SL_ADDR2_0;
uint32_t I2C_I2C_TLOW_SEXT_0;
uint32_t _0x38;
uint32_t I2C_I2C_SL_DELAY_COUNT_0;
uint32_t I2C_I2C_SL_INT_MASK_0;
uint32_t I2C_I2C_SL_INT_SOURCE_0;
uint32_t I2C_I2C_SL_INT_SET_0;
uint32_t _0x4C;
uint32_t I2C_I2C_TX_PACKET_FIFO_0;
uint32_t I2C_I2C_RX_FIFO_0;
uint32_t I2C_PACKET_TRANSFER_STATUS_0;
uint32_t I2C_FIFO_CONTROL_0;
uint32_t I2C_FIFO_STATUS_0;
uint32_t I2C_INTERRUPT_MASK_REGISTER_0;
uint32_t I2C_INTERRUPT_STATUS_REGISTER_0;
uint32_t I2C_I2C_CLK_DIVISOR_REGISTER_0;
uint32_t I2C_I2C_INTERRUPT_SOURCE_REGISTER_0;
uint32_t I2C_I2C_INTERRUPT_SET_REGISTER_0;
uint32_t I2C_I2C_SLV_TX_PACKET_FIFO_0;
uint32_t I2C_I2C_SLV_RX_FIFO_0;
uint32_t I2C_I2C_SLV_PACKET_STATUS_0;
uint32_t I2C_I2C_BUS_CLEAR_CONFIG_0;
uint32_t I2C_I2C_BUS_CLEAR_STATUS_0;
uint32_t I2C_I2C_CONFIG_LOAD_0;
uint32_t _0x90;
uint32_t I2C_I2C_INTERFACE_TIMING_0_0;
uint32_t I2C_I2C_INTERFACE_TIMING_1_0;
uint32_t I2C_I2C_HS_INTERFACE_TIMING_0_0;
uint32_t I2C_I2C_HS_INTERFACE_TIMING_1_0;
} tegra_i2c_t;
#define I2C1_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x000))
#define I2C2_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x400))
#define I2C3_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x500))
#define I2C4_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x700))
#define I2C5_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x000))
#define I2C6_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x100))
void i2c_config(I2CDevice id);
void i2c_init(I2CDevice id);
bool i2c_query(I2CDevice id, uint8_t device, uint8_t r, void *dst, size_t dst_size);
bool i2c_send(I2CDevice id, uint8_t device, uint8_t r, void *src, size_t src_size);
void i2c_send_pmic_cpu_shutdown_cmd(void);
bool i2c_query_ti_charger_bit_7(void);
void i2c_clear_ti_charger_bit_7(void);
void i2c_set_ti_charger_bit_7(void);
#endif

Some files were not shown because too many files have changed in this diff Show More