From b3a739592ea35d437df7ffcebde5fd139a395a19 Mon Sep 17 00:00:00 2001 From: shchmue Date: Sun, 8 Dec 2019 19:17:46 -0700 Subject: [PATCH] Merge hekate 5.1.0 changes --- common/memory_map.h | 87 +++++ source/config/config.c | 612 ++++++++++++++++++++++++++++++ source/config/config.h | 7 + source/config/ini.c | 8 +- source/config/ini.h | 2 +- source/gfx/di.c | 5 +- source/gfx/di.h | 5 +- source/gfx/di.inl | 8 +- source/hos/pkg2.c | 1 + source/keys/keys.c | 1 - source/libs/fatfs/diskio.c | 6 +- source/main.c | 4 +- source/mem/minerva.c | 21 +- source/mem/minerva.h | 6 +- source/mem/sdram.c | 243 ++++++++++-- source/mem/sdram_lp0_param_t210.h | 2 +- source/power/max17050.c | 9 +- source/power/max17050.h | 4 +- source/power/max77620.h | 18 +- source/power/max7762x.c | 25 +- source/sec/se.c | 38 +- source/sec/se_t210.h | 42 +- source/sec/tsec.c | 7 +- source/soc/bpmp.c | 27 +- source/soc/bpmp.h | 11 +- source/soc/clock.c | 29 +- source/soc/clock.h | 3 +- source/soc/cluster.c | 7 +- source/soc/fuse.c | 316 +++++++++++++++ source/soc/fuse.h | 6 + source/soc/hw_init.c | 5 +- source/soc/kfuse.c | 35 +- source/soc/kfuse.h | 2 +- source/soc/smmu.c | 2 +- source/soc/t210.h | 10 +- source/storage/nx_emmc.c | 6 +- source/storage/sd.h | 6 +- source/storage/sdmmc.c | 52 +-- source/storage/sdmmc.h | 2 +- source/storage/sdmmc_driver.c | 20 +- source/utils/btn.c | 21 +- source/utils/btn.h | 3 +- source/utils/dirlist.c | 10 +- source/utils/types.h | 1 + source/utils/util.c | 9 +- source/utils/util.h | 5 +- 46 files changed, 1525 insertions(+), 224 deletions(-) create mode 100644 common/memory_map.h diff --git a/common/memory_map.h b/common/memory_map.h new file mode 100644 index 0000000..271d9f7 --- /dev/null +++ b/common/memory_map.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2019 CTCaer + * + * 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 . + */ + +#ifndef _MEMORY_MAP_H_ +#define _MEMORY_MAP_H_ + +//#define IPL_STACK_TOP 0x4003FF00 +/* --- BIT/BCT: 0x40000000 - 0x40003000 --- */ +/* --- IPL: 0x40003000 - 0x40028000 --- */ +#define IPL_LOAD_ADDR 0x40003000 +#define IPL_SZ_MAX 0x20000 // 128KB. +//#define IRAM_LIB_ADDR 0x4002B000 +#define SDRAM_PARAMS_ADDR 0x40030000 // SDRAM extraction buffer during sdram init. +#define CBFS_DRAM_EN_ADDR 0x4003e000 // u32. + +/* --- DRAM START --- */ +#define DRAM_START 0x80000000 +/* Do not write anything in this area */ +#define NYX_LOAD_ADDR 0x81000000 +#define NYX_SZ_MAX 0x1000000 +/* Stack theoretical max: 220MB */ +#define IPL_STACK_TOP 0x90010000 +#define IPL_HEAP_START 0x90020000 +#define IPL_HEAP_SZ 0x24FE0000 // 592MB. +/* --- Gap: 0xB5000000 - 0xB5FFFFFF --- */ + +// SDMMC DMA buffers +#define SDXC_BUF_ALIGNED 0xB6000000 +#define MIXD_BUF_ALIGNED 0xB7000000 +#define EMMC_BUF_ALIGNED MIXD_BUF_ALIGNED +#define SDMMC_DMA_BUF_SZ 0x1000000 // 16MB (4MB currently used). +#define SDMMC_UPPER_BUFFER 0xB8000000 +#define SDMMC_UP_BUF_SZ 0x8000000 // 128MB. + +// Virtual disk / Chainloader buffers. +#define RAM_DISK_ADDR 0xC1000000 +#define RAM_DISK_SZ 0x20000000 +//#define DRAM_LIB_ADDR 0xE0000000 +/* --- Chnldr: 252MB 0xC03C0000 - 0xCFFFFFFF --- */ //! Only used when chainloading. +/* --- Gap: 464MB 0xD0000000 - 0xECFFFFFF --- */ + +// Nyx buffers. +#define NYX_STORAGE_ADDR 0xED000000 +#define NYX_RES_ADDR 0xEE000000 + +// Framebuffer addresses. +#define IPL_FB_ADDRESS 0xF0000000 +#define IPL_FB_SZ 0x384000 // 720 x 1280 x 4. +#define LOG_FB_ADDRESS 0xF0400000 +#define LOG_FB_SZ 0x334000 // 1280 x 656 x 4. +#define NYX_FB_ADDRESS 0xF0800000 +#define NYX_FB_SZ 0x384000 // 1280 x 720 x 4. + +// Nyx LvGL buffers. +#define NYX_LV_VDB_ADR 0xF0C00000 +#define NYX_FB_SZ 0x384000 // 1280 x 720 x 4. +#define NYX_LV_MEM_ADR 0xF1000000 +#define NYX_LV_MEM_SZ 0x8000000 + +// NX BIS driver sector cache. +#define NX_BIS_CACHE_ADDR 0xF9000000 +#define NX_BIS_CACHE_SZ 0x8800 +/* --- Gap: 111MB 0xF9008800 - 0xFFFFFFFF --- */ + +// #define EXT_PAYLOAD_ADDR 0xC03C0000 +// #define RCM_PAYLOAD_ADDR (EXT_PAYLOAD_ADDR + ALIGN(PATCHED_RELOC_SZ, 0x10)) +// #define COREBOOT_ADDR (0xD0000000 - 0x100000) + +// NYX +// #define EXT_PAYLOAD_ADDR 0xC0000000 +// #define RCM_PAYLOAD_ADDR (EXT_PAYLOAD_ADDR + ALIGN(PATCHED_RELOC_SZ, 0x10)) +// #define COREBOOT_ADDR (0xD0000000 - 0x100000) + +#endif diff --git a/source/config/config.c b/source/config/config.c index 2fa964b..38e5bcf 100644 --- a/source/config/config.c +++ b/source/config/config.c @@ -20,6 +20,7 @@ #include "config.h" #include "ini.h" #include "../gfx/gfx.h" +#include "../gfx/tui.h" #include "../libs/fatfs/ff.h" #include "../soc/t210.h" #include "../storage/sdmmc.h" @@ -52,3 +53,614 @@ void set_default_configuration() sd_power_cycle_time_start = 0xFFFFFFF; } +int create_config_entry() +{ + if (!sd_mount()) + return 1; + + char lbuf[32]; + FIL fp; + bool mainIniFound = false; + + LIST_INIT(ini_sections); + + if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false)) + mainIniFound = true; + else + { + u8 res = f_open(&fp, "bootloader/hekate_ipl.ini", FA_READ); + if (res == FR_NO_FILE || res == FR_NO_PATH) + { + f_mkdir("bootloader"); + f_mkdir("bootloader/ini"); + f_mkdir("bootloader/payloads"); + f_mkdir("bootloader/sys"); + } + else + { + if (!res) + f_close(&fp); + return 1; + } + } + + if (f_open(&fp, "bootloader/hekate_ipl.ini", FA_WRITE | FA_CREATE_ALWAYS) != FR_OK) + return 1; + // Add config entry. + f_puts("[config]\nautoboot=", &fp); + itoa(h_cfg.autoboot, lbuf, 10); + f_puts(lbuf, &fp); + f_puts("\nautoboot_list=", &fp); + itoa(h_cfg.autoboot_list, lbuf, 10); + f_puts(lbuf, &fp); + f_puts("\nbootwait=", &fp); + itoa(h_cfg.bootwait, lbuf, 10); + f_puts(lbuf, &fp); + f_puts("\nverification=", &fp); + itoa(h_cfg.verification, lbuf, 10); + f_puts(lbuf, &fp); + f_puts("\nbacklight=", &fp); + itoa(h_cfg.backlight, lbuf, 10); + f_puts(lbuf, &fp); + f_puts("\nautohosoff=", &fp); + itoa(h_cfg.autohosoff, lbuf, 10); + f_puts(lbuf, &fp); + f_puts("\nautonogc=", &fp); + itoa(h_cfg.autonogc, lbuf, 10); + f_puts(lbuf, &fp); + if (h_cfg.brand) + { + f_puts("\nbrand=", &fp); + f_puts(h_cfg.brand, &fp); + } + if (h_cfg.tagline) + { + f_puts("\ntagline=", &fp); + f_puts(h_cfg.tagline, &fp); + } + f_puts("\n", &fp); + + if (mainIniFound) + { + // Re-construct existing entries. + LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link) + { + if (!strcmp(ini_sec->name, "config")) + continue; + + switch (ini_sec->type) + { + case INI_CHOICE: // Re-construct Boot entry [ ]. + f_puts("[", &fp); + f_puts(ini_sec->name, &fp); + f_puts("]\n", &fp); + // Re-construct boot entry's config. + LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link) + { + f_puts(kv->key, &fp); + f_puts("=", &fp); + f_puts(kv->val, &fp); + f_puts("\n", &fp); + } + break; + case INI_CAPTION: // Re-construct caption entry { }. + f_puts("{", &fp); + f_puts(ini_sec->name, &fp); + f_puts("}\n", &fp); + break; + case INI_NEWLINE: // Re-construct cosmetic newline \n. + f_puts("\n", &fp); + break; + case INI_COMMENT: // Re-construct comment entry #. + f_puts("#", &fp); + f_puts(ini_sec->name, &fp); + f_puts("\n", &fp); + break; + } + } + } + + f_close(&fp); + sd_unmount(); + + return 0; +} + +#pragma GCC push_options +#pragma GCC optimize ("Os") + +static void _save_config() +{ + gfx_clear_grey(0x1B); + gfx_con_setpos(0, 0); + + if (!create_config_entry()) + gfx_puts("\nConfiguration was saved!\n"); + else + EPRINTF("\nConfiguration saving failed!"); + gfx_puts("\nPress any key..."); +} + +static void _config_autoboot_list(void *ent) +{ + gfx_clear_grey(0x1B); + gfx_con_setpos(0, 0); + + u32 *temp_autoboot = NULL; + + LIST_INIT(ini_sections); + + u8 max_entries = 30; + + ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 3)); + u32 *boot_values = (u32 *)malloc(sizeof(u32) * max_entries); + char *boot_text = (char *)malloc(512 * max_entries); + + for (u32 j = 0; j < max_entries; j++) + boot_values[j] = j; + + if (sd_mount()) + { + if (ini_parse(&ini_sections, "bootloader/ini", true)) + { + // Build configuration menu. + ments[0].type = MENT_BACK; + ments[0].caption = "Back"; + + ments[1].type = MENT_CHGLINE; + + u32 i = 2; + LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link) + { + // Skip other ini entries for autoboot. + if (ini_sec->type == INI_CHOICE) + { + if (!strcmp(ini_sec->name, "config")) + continue; + + if (strlen(ini_sec->name) > 510) + ments[i].caption = ini_sec->name; + else + { + if (h_cfg.autoboot != (i - 1) || !h_cfg.autoboot_list) + boot_text[(i - 1) * 512] = ' '; + + else + boot_text[(i - 1) * 512] = '*'; + strcpy(boot_text + (i - 1) * 512 + 1, ini_sec->name); + ments[i].caption = &boot_text[(i - 1) * 512]; + } + ments[i].type = ini_sec->type; + ments[i].data = &boot_values[i - 1]; + i++; + + if ((i - 1) > max_entries) + break; + } + } + + memset(&ments[i], 0, sizeof(ment_t)); + menu_t menu = {ments, "Select an entry to auto boot", 0, 0}; + temp_autoboot = (u32 *)tui_do_menu(&menu); + if (temp_autoboot != NULL) + { + h_cfg.autoboot = *(u32 *)temp_autoboot; + h_cfg.autoboot_list = 1; + _save_config(); + + ment_t *tmp = (ment_t *)ent; + tmp->data = NULL; + } + else + goto out2; + } + else + { + EPRINTF("Could not open 'bootloader/hekate_ipl.ini'.\nMake sure it exists!."); + goto out; + } + } + +out:; + btn_wait(); +out2:; + free(ments); + free(boot_values); + free(boot_text); + + sd_unmount(); +} + +void config_autoboot() +{ + gfx_clear_grey(0x1B); + gfx_con_setpos(0, 0); + + u32 *temp_autoboot = NULL; + + LIST_INIT(ini_sections); + + u8 max_entries = 30; + + ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 5)); + u32 *boot_values = (u32 *)malloc(sizeof(u32) * max_entries); + char *boot_text = (char *)malloc(512 * max_entries); + + for (u32 j = 0; j < max_entries; j++) + boot_values[j] = j; + + if (sd_mount()) + { + if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false)) + { + // Build configuration menu. + ments[0].type = MENT_BACK; + ments[0].caption = "Back"; + + ments[1].type = MENT_CHGLINE; + + ments[2].type = MENT_DATA; + if (!h_cfg.autoboot) + ments[2].caption = "*Disable"; + else + ments[2].caption = " Disable"; + ments[2].data = &boot_values[0]; + + ments[3].type = MENT_HDLR_RE; + if (h_cfg.autoboot_list) + ments[3].caption = "*More configs..."; + else + ments[3].caption = " More configs..."; + ments[3].handler = _config_autoboot_list; + ments[3].data = (void *)0xCAFE; + + ments[4].type = MENT_CHGLINE; + + u32 i = 5; + LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link) + { + // Skip other ini entries for autoboot. + if (ini_sec->type == INI_CHOICE) + { + if (!strcmp(ini_sec->name, "config")) + continue; + + if (strlen(ini_sec->name) > 510) + ments[i].caption = ini_sec->name; + else + { + if (h_cfg.autoboot != (i - 4) || h_cfg.autoboot_list) + boot_text[(i - 4) * 512] = ' '; + + else + boot_text[(i - 4) * 512] = '*'; + strcpy(boot_text + (i - 4) * 512 + 1, ini_sec->name); + ments[i].caption = &boot_text[(i - 4) * 512]; + } + ments[i].type = ini_sec->type; + ments[i].data = &boot_values[i - 4]; + i++; + + if ((i - 4) > max_entries) + break; + } + } + if (i < 6 && !h_cfg.autoboot_list) + { + ments[i].type = MENT_CAPTION; + ments[i].caption = "No main configurations found..."; + ments[i].color = 0xFFFFDD00; + i++; + } + + memset(&ments[i], 0, sizeof(ment_t)); + menu_t menu = {ments, "Disable or select entry to auto boot", 0, 0}; + temp_autoboot = (u32 *)tui_do_menu(&menu); + if (temp_autoboot != NULL) + { + h_cfg.autoboot = *(u32 *)temp_autoboot; + h_cfg.autoboot_list = 0; + _save_config(); + } + else + goto out2; + } + else + { + EPRINTF("Could not open 'bootloader/hekate_ipl.ini'.\nMake sure it exists!."); + goto out; + } + } + +out:; + btn_wait(); +out2:; + free(ments); + free(boot_values); + free(boot_text); + + sd_unmount(); + + if (temp_autoboot == NULL) + return; +} + +void config_bootdelay() +{ + gfx_clear_grey(0x1B); + gfx_con_setpos(0, 0); + + u32 delay_entries = 6; + + ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (delay_entries + 3)); + u32 *delay_values = (u32 *)malloc(sizeof(u32) * delay_entries); + char *delay_text = (char *)malloc(32 * delay_entries); + + for (u32 j = 0; j < delay_entries; j++) + delay_values[j] = j; + + ments[0].type = MENT_BACK; + ments[0].caption = "Back"; + + ments[1].type = MENT_CHGLINE; + + ments[2].type = MENT_DATA; + if (h_cfg.bootwait) + ments[2].caption = " 0 seconds (Bootlogo disabled)"; + else + ments[2].caption = "*0 seconds (Bootlogo disabled)"; + ments[2].data = &delay_values[0]; + + u32 i = 0; + for (i = 1; i < delay_entries; i++) + { + if (h_cfg.bootwait != i) + delay_text[i * 32] = ' '; + else + delay_text[i * 32] = '*'; + delay_text[i * 32 + 1] = i + '0'; + strcpy(delay_text + i * 32 + 2, " seconds"); + + ments[i + 2].type = MENT_DATA; + ments[i + 2].caption = delay_text + i * 32; + ments[i + 2].data = &delay_values[i]; + } + + memset(&ments[i + 2], 0, sizeof(ment_t)); + menu_t menu = {ments, "Time delay for entering bootloader menu", 0, 0}; + + u32 *temp_bootwait = (u32 *)tui_do_menu(&menu); + if (temp_bootwait != NULL) + { + h_cfg.bootwait = *(u32 *)temp_bootwait; + _save_config(); + } + + free(ments); + free(delay_values); + free(delay_text); + + if (temp_bootwait == NULL) + return; + btn_wait(); +} + +void config_verification() +{ + gfx_clear_grey(0x1B); + gfx_con_setpos(0, 0); + + ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * 6); + u32 *vr_values = (u32 *)malloc(sizeof(u32) * 3); + char *vr_text = (char *)malloc(64 * 3); + + for (u32 j = 0; j < 3; j++) + { + vr_values[j] = j; + ments[j + 2].type = MENT_DATA; + ments[j + 2].data = &vr_values[j]; + } + + ments[0].type = MENT_BACK; + ments[0].caption = "Back"; + + ments[1].type = MENT_CHGLINE; + + strcpy(vr_text, " Disable (Fastest - Unsafe)"); + strcpy(vr_text + 64, " Sparse (Fast - Safe)"); + strcpy(vr_text + 128, " Full (Slow - Safe)"); + + for (u32 i = 0; i < 3; i++) + { + if (h_cfg.verification != i) + vr_text[64 * i] = ' '; + else + vr_text[64 * i] = '*'; + ments[2 + i].caption = vr_text + (i * 64); + } + + memset(&ments[5], 0, sizeof(ment_t)); + menu_t menu = {ments, "Backup & Restore verification", 0, 0}; + + u32 *temp_verification = (u32 *)tui_do_menu(&menu); + if (temp_verification != NULL) + { + h_cfg.verification = *(u32 *)temp_verification; + _save_config(); + } + + free(ments); + free(vr_values); + free(vr_text); + + if (temp_verification == NULL) + return; + btn_wait(); +} + +void config_backlight() +{ + gfx_clear_grey(0x1B); + gfx_con_setpos(0, 0); + + u32 bri_entries = 11; + + ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (bri_entries + 3)); + u32 *bri_values = (u32 *)malloc(sizeof(u32) * bri_entries); + char *bri_text = (char *)malloc(8 * bri_entries); + + for (u32 j = 1; j < bri_entries; j++) + bri_values[j] = j * 10; + + ments[0].type = MENT_BACK; + ments[0].caption = "Back"; + + ments[1].type = MENT_CHGLINE; + + u32 i = 0; + for (i = 1; i < bri_entries; i++) + { + if ((h_cfg.backlight / 20) != i) + bri_text[i * 32] = ' '; + else + bri_text[i * 32] = '*'; + + if (i < 10) + { + bri_text[i * 32 + 1] = i + '0'; + strcpy(bri_text + i * 32 + 2, "0%"); + } + else + strcpy(bri_text + i * 32 + 1, "100%"); + + ments[i + 1].type = MENT_DATA; + ments[i + 1].caption = bri_text + i * 32; + ments[i + 1].data = &bri_values[i]; + } + + memset(&ments[i + 1], 0, sizeof(ment_t)); + menu_t menu = {ments, "Backlight brightness", 0, 0}; + + u32 *temp_backlight = (u32 *)tui_do_menu(&menu); + if (temp_backlight != NULL) + { + h_cfg.backlight = (*(u32 *)temp_backlight) * 2; + _save_config(); + } + + free(ments); + free(bri_values); + free(bri_text); + + if (temp_backlight == NULL) + return; + btn_wait(); +} + +void config_auto_hos_poweroff() +{ + gfx_clear_grey(0x1B); + gfx_con_setpos(0, 0); + + ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * 6); + u32 *hp_values = (u32 *)malloc(sizeof(u32) * 3); + + for (u32 j = 0; j < 3; j++) + { + hp_values[j] = j; + ments[j + 2].type = MENT_DATA; + ments[j + 2].data = &hp_values[j]; + } + + ments[0].type = MENT_BACK; + ments[0].caption = "Back"; + + ments[1].type = MENT_CHGLINE; + + if (h_cfg.autohosoff == 1) + { + ments[2].caption = " Disable"; + ments[3].caption = "*Enable"; + ments[4].caption = " Enable (No logo)"; + } + else if (h_cfg.autohosoff >= 2) + { + ments[2].caption = " Disable"; + ments[3].caption = " Enable"; + ments[4].caption = "*Enable (No logo)"; + } + else + { + ments[2].caption = "*Disable"; + ments[3].caption = " Enable"; + ments[4].caption = " Enable (No logo)"; + } + + memset(&ments[5], 0, sizeof(ment_t)); + menu_t menu = {ments, "Power off if woke up from HOS", 0, 0}; + + u32 *temp_autohosoff = (u32 *)tui_do_menu(&menu); + if (temp_autohosoff != NULL) + { + h_cfg.autohosoff = *(u32 *)temp_autohosoff; + _save_config(); + } + + free(ments); + free(hp_values); + + if (temp_autohosoff == NULL) + return; + btn_wait(); +} + +void config_nogc() +{ + gfx_clear_grey(0x1B); + gfx_con_setpos(0, 0); + + ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * 5); + u32 *cb_values = (u32 *)malloc(sizeof(u32) * 2); + + for (u32 j = 0; j < 2; j++) + { + cb_values[j] = j; + ments[j + 2].type = MENT_DATA; + ments[j + 2].data = &cb_values[j]; + } + + ments[0].type = MENT_BACK; + ments[0].caption = "Back"; + + ments[1].type = MENT_CHGLINE; + + if (h_cfg.autonogc) + { + ments[2].caption = " Disable"; + ments[3].caption = "*Auto"; + } + else + { + ments[2].caption = "*Disable"; + ments[3].caption = " Auto"; + } + + memset(&ments[4], 0, sizeof(ment_t)); + menu_t menu = {ments, "No Gamecard", 0, 0}; + + u32 *temp_nogc = (u32 *)tui_do_menu(&menu); + if (temp_nogc != NULL) + { + h_cfg.autonogc = *(u32 *)temp_nogc; + _save_config(); + } + + free(ments); + free(cb_values); + + if (temp_nogc == NULL) + return; + btn_wait(); +} + +#pragma GCC pop_options diff --git a/source/config/config.h b/source/config/config.h index 1f6c36d..8cd34e1 100644 --- a/source/config/config.h +++ b/source/config/config.h @@ -46,5 +46,12 @@ typedef enum } hsysmodule_t; void set_default_configuration(); +int create_config_entry(); +void config_autoboot(); +void config_bootdelay(); +void config_verification(); +void config_backlight(); +void config_auto_hos_poweroff(); +void config_nogc(); #endif /* _CONFIG_H_ */ diff --git a/source/config/ini.c b/source/config/ini.c index f033994..e807aec 100644 --- a/source/config/ini.c +++ b/source/config/ini.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (C) 2018-2019 CTCaer + * Copyright (c) 2018-2019 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -78,7 +78,7 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir) char *filename = (char *)malloc(256); - memcpy(filename, ini_path, pathlen + 1); + strcpy(filename, ini_path); // Get all ini filenames. if (is_dir) @@ -89,7 +89,7 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir) free(filename); return 0; } - memcpy(filename + pathlen, "/", 2); + strcpy(filename + pathlen, "/"); pathlen++; } @@ -100,7 +100,7 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir) { if (filelist[k * 256]) { - memcpy(filename + pathlen, &filelist[k * 256], strlen(&filelist[k * 256]) + 1); + strcpy(filename + pathlen, &filelist[k * 256]); k++; } else diff --git a/source/config/ini.h b/source/config/ini.h index 318adf0..dffbe86 100644 --- a/source/config/ini.h +++ b/source/config/ini.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (C) 2018 CTCaer + * Copyright (c) 2018 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/source/gfx/di.c b/source/gfx/di.c index 1dcef3f..200d412 100644 --- a/source/gfx/di.c +++ b/source/gfx/di.c @@ -262,11 +262,12 @@ void display_color_screen(u32 color) u32 *display_init_framebuffer() { // Sanitize framebuffer area. - memset((u32 *)FB_ADDRESS, 0, 0x3C0000); + memset((u32 *)IPL_FB_ADDRESS, 0, 0x3C0000); + // This configures the framebuffer @ IPL_FB_ADDRESS with a resolution of 1280x720 (line stride 720). exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer, 32); usleep(35000); - return (u32 *)FB_ADDRESS; + return (u32 *)IPL_FB_ADDRESS; } diff --git a/source/gfx/di.h b/source/gfx/di.h index 69d231a..ee796a7 100644 --- a/source/gfx/di.h +++ b/source/gfx/di.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (C) 2018 CTCaer + * Copyright (c) 2018 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -18,10 +18,9 @@ #ifndef _DI_H_ #define _DI_H_ +#include "../../common/memory_map.h" #include "../utils/types.h" -#define FB_ADDRESS 0xC0000000 - /*! Display registers. */ #define _DIREG(reg) ((reg) * 4) diff --git a/source/gfx/di.inl b/source/gfx/di.inl index 58bf442..dd82899 100644 --- a/source/gfx/di.inl +++ b/source/gfx/di.inl @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert -* Copyright (C) 2018 CTCaer +* Copyright (c) 2018 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -128,7 +128,7 @@ static const cfg_op_t _display_config_2[94] = { }; //DSI Init config. -static const cfg_op_t _display_config_3[61] = { +static const cfg_op_t _display_config_3[61] = { {DSI_WR_DATA, 0}, {DSI_INT_ENABLE, 0}, {DSI_INT_STATUS, 0}, @@ -415,7 +415,7 @@ static const cfg_op_t _display_config_11[113] = { {DC_DISP_SYNC_WIDTH, 0x10048}, {DC_DISP_BACK_PORCH, 0x90048}, {DC_DISP_ACTIVE, 0x50002D0}, - {DC_DISP_FRONT_PORCH, 0xA0088}, // Sources say that this should be above the DC_DISP_ACTIVE cmd. + {DC_DISP_FRONT_PORCH, 0xA0088}, // Sources say that this should be above the DC_DISP_ACTIVE cmd. /* End of Display timings */ {DC_DISP_SHIFT_CLOCK_OPTIONS, SC1_H_QUALIFIER_NONE | SC0_H_QUALIFIER_NONE}, {DC_COM_PIN_OUTPUT_ENABLE(1), 0}, @@ -548,7 +548,7 @@ static const cfg_op_t cfg_display_framebuffer[32] = { {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, //768*2x768*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. {DC_WIN_BUFFER_CONTROL, 0}, {DC_WINBUF_SURFACE_KIND, 0}, //Regular surface. - {DC_WINBUF_START_ADDR, FB_ADDRESS}, //Framebuffer address. + {DC_WINBUF_START_ADDR, IPL_FB_ADDRESS}, // Framebuffer address. {DC_WINBUF_ADDR_H_OFFSET, 0}, {DC_WINBUF_ADDR_V_OFFSET, 0}, {DC_WIN_WIN_OPTIONS, 0}, diff --git a/source/hos/pkg2.c b/source/hos/pkg2.c index 301fd4e..e745cbc 100644 --- a/source/hos/pkg2.c +++ b/source/hos/pkg2.c @@ -139,6 +139,7 @@ int pkg2_decompress_kip(pkg2_kip1_info_t* ki, u32 sectsToDecomp) memcpy(newKip, &hdr, sizeof(hdr)); newKipSize = dstDataPtr-(unsigned char*)(newKip); + free(ki->kip1); ki->kip1 = newKip; ki->size = newKipSize; diff --git a/source/keys/keys.c b/source/keys/keys.c index f697fa3..c5a27d3 100644 --- a/source/keys/keys.c +++ b/source/keys/keys.c @@ -484,7 +484,6 @@ get_tsec: ; } pkg2_done: if (ki) { - free(ki->kip1); free(ki); } free(pkg2); diff --git a/source/libs/fatfs/diskio.c b/source/libs/fatfs/diskio.c index 75a1c1e..0dea450 100644 --- a/source/libs/fatfs/diskio.c +++ b/source/libs/fatfs/diskio.c @@ -24,15 +24,15 @@ /*-----------------------------------------------------------------------*/ #include + +#include "../../../common/memory_map.h" + #include "diskio.h" /* FatFs lower layer API */ #include "../../mem/heap.h" #include "../../sec/se.h" #include "../../storage/nx_emmc.h" #include "../../storage/sdmmc.h" -#define SDMMC_UPPER_BUFFER 0xB8000000 -#define DRAM_START 0x80000000 - extern sdmmc_storage_t sd_storage; extern sdmmc_storage_t storage; extern emmc_part_t *system_part; diff --git a/source/main.c b/source/main.c index 5cd0a75..4d3ee27 100644 --- a/source/main.c +++ b/source/main.c @@ -49,6 +49,8 @@ static bool sd_mounted; hekate_config h_cfg; boot_cfg_t __attribute__((section ("._boot_cfg"))) b_cfg; +volatile nyx_storage_t *nyx_str = (nyx_storage_t *)NYX_STORAGE_ADDR; + bool sd_mount() { if (sd_mounted) @@ -420,7 +422,7 @@ void ipl_main() gfx_con_init(); display_backlight_pwm_init(); - bpmp_clk_rate_set(BPMP_CLK_SUPER_BOOST); + bpmp_clk_rate_set(BPMP_CLK_DEFAULT_BOOST); h_cfg.emummc_force_disable = emummc_load_cfg(); diff --git a/source/mem/minerva.c b/source/mem/minerva.c index 2ac8516..6683053 100644 --- a/source/mem/minerva.c +++ b/source/mem/minerva.c @@ -26,7 +26,7 @@ #include "../soc/fuse.h" #include "../soc/t210.h" -volatile nyx_storage_t *nyx_str = (nyx_storage_t *)0xED000000; +extern volatile nyx_storage_t *nyx_str; void minerva_init() { @@ -34,8 +34,10 @@ void minerva_init() mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg; - // Set table to ram. - mtc_cfg->mtc_table = NULL; + // Set table to nyx storage. + mtc_cfg->mtc_table = (emc_table_t *)&nyx_str->mtc_table; + + mtc_cfg->init_done = MTC_NEW_MAGIC; mtc_cfg->sdram_id = (fuse_read_odm(4) >> 3) & 0x1F; u32 ep_addr = ianos_loader(false, "bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)mtc_cfg); minerva_cfg = (void *)ep_addr; @@ -58,6 +60,15 @@ void minerva_init() minerva_cfg(mtc_cfg, NULL); mtc_cfg->rate_to = 1600000; minerva_cfg(mtc_cfg, NULL); + + // FSP WAR. + mtc_cfg->train_mode = OP_SWITCH; + mtc_cfg->rate_to = 800000; + minerva_cfg(mtc_cfg, NULL); + + // Switch to max. + mtc_cfg->rate_to = 1600000; + minerva_cfg(mtc_cfg, NULL); } void minerva_change_freq(minerva_freq_t freq) @@ -66,7 +77,7 @@ void minerva_change_freq(minerva_freq_t freq) return; mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg; - if (minerva_cfg && (mtc_cfg->rate_from != freq)) + if (mtc_cfg->rate_from != freq) { mtc_cfg->rate_to = freq; mtc_cfg->train_mode = OP_SWITCH; @@ -80,7 +91,7 @@ void minerva_periodic_training() return; mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg; - if (minerva_cfg && mtc_cfg->rate_from == FREQ_1600) + if (mtc_cfg->rate_from == FREQ_1600) { mtc_cfg->train_mode = OP_PERIODIC_TRAIN; minerva_cfg(mtc_cfg, NULL); diff --git a/source/mem/minerva.h b/source/mem/minerva.h index dd71658..f1edbaa 100644 --- a/source/mem/minerva.h +++ b/source/mem/minerva.h @@ -20,7 +20,10 @@ #include "mtc_table.h" #include "../utils/types.h" -#define EMC_PERIODIC_TRAIN_MS 100 +#define MTC_INIT_MAGIC 0x3043544D +#define MTC_NEW_MAGIC 0x5243544D + +#define EMC_PERIODIC_TRAIN_MS 250 typedef struct { @@ -35,6 +38,7 @@ typedef struct bool emc_2X_clk_src_is_pllmb; bool fsp_for_src_freq; bool train_ram_patterns; + bool init_done; } mtc_config_t; enum train_mode_t diff --git a/source/mem/sdram.c b/source/mem/sdram.c index db9637a..a9a26d3 100644 --- a/source/mem/sdram.c +++ b/source/mem/sdram.c @@ -16,17 +16,18 @@ * along with this program. If not, see . */ -#include "../soc/i2c.h" -#include "../soc/t210.h" #include "mc.h" #include "emc.h" #include "sdram_param_t210.h" -#include "../soc/pmc.h" -#include "../utils/util.h" -#include "../soc/fuse.h" +#include "../../common/memory_map.h" #include "../power/max77620.h" #include "../power/max7762x.h" #include "../soc/clock.h" +#include "../soc/fuse.h" +#include "../soc/i2c.h" +#include "../soc/pmc.h" +#include "../soc/t210.h" +#include "../utils/util.h" #define CONFIG_SDRAM_COMPRESS_CFG @@ -50,19 +51,31 @@ static u32 _get_sdram_id() static void _sdram_config(const sdram_params_t *params) { - PMC(APBDEV_PMC_IO_DPD3_REQ) = (((4 * params->emc_pmc_scratch1 >> 2) + 0x80000000) ^ 0xFFFF) & 0xC000FFFF; + // Program DPD3/DPD4 regs (coldboot path). + // Enable sel_dpd on unused pins. + u32 dpd_req = (params->emc_pmc_scratch1 & 0x3FFFFFFF) | 0x80000000; + PMC(APBDEV_PMC_IO_DPD3_REQ) = (dpd_req ^ 0xFFFF) & 0xC000FFFF; usleep(params->pmc_io_dpd3_req_wait); - u32 req = (4 * params->emc_pmc_scratch2 >> 2) + 0x80000000; - PMC(APBDEV_PMC_IO_DPD4_REQ) = (req >> 16 << 16) ^ 0x3FFF0000; + // Disable e_dpd_vttgen. + dpd_req = (params->emc_pmc_scratch2 & 0x3FFFFFFF) | 0x80000000; + PMC(APBDEV_PMC_IO_DPD4_REQ) = (dpd_req & 0xFFFF0000) ^ 0x3FFF0000; usleep(params->pmc_io_dpd4_req_wait); - PMC(APBDEV_PMC_IO_DPD4_REQ) = (req ^ 0xFFFF) & 0xC000FFFF; + + // Disable e_dpd_bg. + PMC(APBDEV_PMC_IO_DPD4_REQ) = (dpd_req ^ 0xFFFF) & 0xC000FFFF; usleep(params->pmc_io_dpd4_req_wait); + PMC(APBDEV_PMC_WEAK_BIAS) = 0; usleep(1); + // Start clocks. CLOCK(CLK_RST_CONTROLLER_PLLM_MISC1) = params->pllm_setup_control; CLOCK(CLK_RST_CONTROLLER_PLLM_MISC2) = 0; + + // u32 tmp = (params->pllm_feedback_divider << 8) | params->pllm_input_divider | ((params->pllm_post_divider & 0xFFFF) << 20); + // CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) = tmp; + // CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) = tmp | 0x40000000; CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) = (params->pllm_feedback_divider << 8) | params->pllm_input_divider | 0x40000000 | ((params->pllm_post_divider & 0xFFFF) << 20); u32 wait_end = get_tmr_us() + 300; @@ -72,24 +85,35 @@ static void _sdram_config(const sdram_params_t *params) goto break_nosleep; } usleep(10); -break_nosleep: +break_nosleep: CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = ((params->mc_emem_arb_misc0 >> 11) & 0x10000) | (params->emc_clock_source & 0xFFFEFFFF); if (params->emc_clock_source_dll) CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC_DLL) = params->emc_clock_source_dll; if (params->clear_clock2_mc1) CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = 0x40000000; - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = 0x2000001; - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = 0x4000; - CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = 0x2000001; + + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = 0x2000001; // Enable EMC and MEM clocks. + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = 0x4000; // Enable EMC_DLL clock. + CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = 0x2000001; // Clear EMC and MEM resets. + + // Set pad macros. EMC(EMC_PMACRO_VTTGEN_CTRL_0) = params->emc_pmacro_vttgen_ctrl0; EMC(EMC_PMACRO_VTTGEN_CTRL_1) = params->emc_pmacro_vttgen_ctrl1; EMC(EMC_PMACRO_VTTGEN_CTRL_2) = params->emc_pmacro_vttgen_ctrl2; - EMC(EMC_TIMING_CONTROL) = 1; - usleep(1); + + EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place. + usleep(10); // Ensure the regulators settle. + + // Select EMC write mux. EMC(EMC_DBG) = (params->emc_dbg_write_mux << 1) | params->emc_dbg; + + // Patch 2 using BCT spare variables. if (params->emc_bct_spare2) *(vu32 *)params->emc_bct_spare2 = params->emc_bct_spare3; + + // Program CMD mapping. Required before brick mapping, else + // we can't guarantee CK will be differential at all times. EMC(EMC_FBIO_CFG7) = params->emc_fbio_cfg7; EMC(EMC_CMD_MAPPING_CMD0_0) = params->emc_cmd_mapping_cmd0_0; EMC(EMC_CMD_MAPPING_CMD0_1) = params->emc_cmd_mapping_cmd0_1; @@ -104,25 +128,40 @@ break_nosleep: EMC(EMC_CMD_MAPPING_CMD3_1) = params->emc_cmd_mapping_cmd3_1; EMC(EMC_CMD_MAPPING_CMD3_2) = params->emc_cmd_mapping_cmd3_2; EMC(EMC_CMD_MAPPING_BYTE) = params->emc_cmd_mapping_byte; + + // Program brick mapping. EMC(EMC_PMACRO_BRICK_MAPPING_0) = params->emc_pmacro_brick_mapping0; EMC(EMC_PMACRO_BRICK_MAPPING_1) = params->emc_pmacro_brick_mapping1; EMC(EMC_PMACRO_BRICK_MAPPING_2) = params->emc_pmacro_brick_mapping2; + EMC(EMC_PMACRO_BRICK_CTRL_RFU1) = (params->emc_pmacro_brick_ctrl_rfu1 & 0x1120112) | 0x1EED1EED; + + // This is required to do any reads from the pad macros. EMC(EMC_CONFIG_SAMPLE_DELAY) = params->emc_config_sample_delay; + EMC(EMC_FBIO_CFG8) = params->emc_fbio_cfg8; + + // Set swizzle for Rank 0. EMC(EMC_SWIZZLE_RANK0_BYTE0) = params->emc_swizzle_rank0_byte0; EMC(EMC_SWIZZLE_RANK0_BYTE1) = params->emc_swizzle_rank0_byte1; EMC(EMC_SWIZZLE_RANK0_BYTE2) = params->emc_swizzle_rank0_byte2; EMC(EMC_SWIZZLE_RANK0_BYTE3) = params->emc_swizzle_rank0_byte3; + // Set swizzle for Rank 1. EMC(EMC_SWIZZLE_RANK1_BYTE0) = params->emc_swizzle_rank1_byte0; EMC(EMC_SWIZZLE_RANK1_BYTE1) = params->emc_swizzle_rank1_byte1; EMC(EMC_SWIZZLE_RANK1_BYTE2) = params->emc_swizzle_rank1_byte2; EMC(EMC_SWIZZLE_RANK1_BYTE3) = params->emc_swizzle_rank1_byte3; + + // Patch 4 using BCT spare variables. if (params->emc_bct_spare6) *(vu32 *)params->emc_bct_spare6 = params->emc_bct_spare7; + + // Set pad controls. EMC(EMC_XM2COMPPADCTRL) = params->emc_xm2_comp_pad_ctrl; EMC(EMC_XM2COMPPADCTRL2) = params->emc_xm2_comp_pad_ctrl2; EMC(EMC_XM2COMPPADCTRL3) = params->emc_xm2_comp_pad_ctrl3; + + // Program Autocal controls with shadowed register fields. EMC(EMC_AUTO_CAL_CONFIG2) = params->emc_auto_cal_config2; EMC(EMC_AUTO_CAL_CONFIG3) = params->emc_auto_cal_config3; EMC(EMC_AUTO_CAL_CONFIG4) = params->emc_auto_cal_config4; @@ -130,6 +169,7 @@ break_nosleep: EMC(EMC_AUTO_CAL_CONFIG6) = params->emc_auto_cal_config6; EMC(EMC_AUTO_CAL_CONFIG7) = params->emc_auto_cal_config7; EMC(EMC_AUTO_CAL_CONFIG8) = params->emc_auto_cal_config8; + EMC(EMC_PMACRO_RX_TERM) = params->emc_pmacro_rx_term; EMC(EMC_PMACRO_DQ_TX_DRV) = params->emc_pmacro_dq_tx_drive; EMC(EMC_PMACRO_CA_TX_DRV) = params->emc_pmacro_ca_tx_drive; @@ -137,9 +177,11 @@ break_nosleep: EMC(EMC_PMACRO_AUTOCAL_CFG_COMMON) = params->emc_pmacro_auto_cal_common; EMC(EMC_AUTO_CAL_CHANNEL) = params->emc_auto_cal_channel; EMC(EMC_PMACRO_ZCTRL) = params->emc_pmacro_zcrtl; + EMC(EMC_DLL_CFG_0) = params->emc_dll_cfg0; EMC(EMC_DLL_CFG_1) = params->emc_dll_cfg1; EMC(EMC_CFG_DIG_DLL_1) = params->emc_cfg_dig_dll_1; + EMC(EMC_DATA_BRLSHFT_0) = params->emc_data_brlshft0; EMC(EMC_DATA_BRLSHFT_1) = params->emc_data_brlshft1; EMC(EMC_DQS_BRLSHFT_0) = params->emc_dqs_brlshft0; @@ -152,8 +194,10 @@ break_nosleep: EMC(EMC_QUSE_BRLSHFT_1) = params->emc_quse_brlshft1; EMC(EMC_QUSE_BRLSHFT_2) = params->emc_quse_brlshft2; EMC(EMC_QUSE_BRLSHFT_3) = params->emc_quse_brlshft3; + EMC(EMC_PMACRO_BRICK_CTRL_RFU1) = (params->emc_pmacro_brick_ctrl_rfu1 & 0x1BF01BF) | 0x1E401E40; EMC(EMC_PMACRO_PAD_CFG_CTRL) = params->emc_pmacro_pad_cfg_ctrl; + EMC(EMC_PMACRO_CMD_BRICK_CTRL_FDPD) = params->emc_pmacro_cmd_brick_ctrl_fdpd; EMC(EMC_PMACRO_BRICK_CTRL_RFU2) = params->emc_pmacro_brick_ctrl_rfu2 & 0xFF7FFF7F; EMC(EMC_PMACRO_DATA_BRICK_CTRL_FDPD) = params->emc_pmacro_data_brick_ctrl_fdpd; @@ -164,6 +208,7 @@ break_nosleep: EMC(EMC_PMACRO_DATA_RX_TERM_MODE) = params->emc_pmacro_data_rx_term_mode; EMC(EMC_PMACRO_CMD_RX_TERM_MODE) = params->emc_pmacro_cmd_rx_term_mode; EMC(EMC_PMACRO_CMD_PAD_TX_CTRL) = params->emc_pmacro_cmd_pad_tx_ctrl; + EMC(EMC_CFG_3) = params->emc_cfg3; EMC(EMC_PMACRO_TX_PWRD_0) = params->emc_pmacro_tx_pwrd0; EMC(EMC_PMACRO_TX_PWRD_1) = params->emc_pmacro_tx_pwrd1; @@ -189,6 +234,7 @@ break_nosleep: EMC(EMC_PMACRO_IB_VREF_DQS_0) = params->emc_pmacro_ib_vref_dqs_0; EMC(EMC_PMACRO_IB_VREF_DQS_1) = params->emc_pmacro_ib_vref_dqs_1; EMC(EMC_PMACRO_IB_RXRT) = params->emc_pmacro_ib_rxrt; + EMC(EMC_PMACRO_QUSE_DDLL_RANK0_0) = params->emc_pmacro_quse_ddll_rank0_0; EMC(EMC_PMACRO_QUSE_DDLL_RANK0_1) = params->emc_pmacro_quse_ddll_rank0_1; EMC(EMC_PMACRO_QUSE_DDLL_RANK0_2) = params->emc_pmacro_quse_ddll_rank0_2; @@ -202,6 +248,7 @@ break_nosleep: EMC(EMC_PMACRO_QUSE_DDLL_RANK1_4) = params->emc_pmacro_quse_ddll_rank1_4; EMC(EMC_PMACRO_QUSE_DDLL_RANK1_5) = params->emc_pmacro_quse_ddll_rank1_5; EMC(EMC_PMACRO_BRICK_CTRL_RFU1) = params->emc_pmacro_brick_ctrl_rfu1; + EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0) = params->emc_pmacro_ob_ddll_long_dq_rank0_0; EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1) = params->emc_pmacro_ob_ddll_long_dq_rank0_1; EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2) = params->emc_pmacro_ob_ddll_long_dq_rank0_2; @@ -214,6 +261,7 @@ break_nosleep: EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3) = params->emc_pmacro_ob_ddll_long_dq_rank1_3; EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_4) = params->emc_pmacro_ob_ddll_long_dq_rank1_4; EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_5) = params->emc_pmacro_ob_ddll_long_dq_rank1_5; + EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_0) = params->emc_pmacro_ob_ddll_long_dqs_rank0_0; EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_1) = params->emc_pmacro_ob_ddll_long_dqs_rank0_1; EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_2) = params->emc_pmacro_ob_ddll_long_dqs_rank0_2; @@ -234,6 +282,7 @@ break_nosleep: EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_1) = params->emc_pmacro_ib_ddll_long_dqs_rank1_1; EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_2) = params->emc_pmacro_ib_ddll_long_dqs_rank1_2; EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_3) = params->emc_pmacro_ib_ddll_long_dqs_rank1_3; + EMC(EMC_PMACRO_DDLL_LONG_CMD_0) = params->emc_pmacro_ddll_long_cmd_0; EMC(EMC_PMACRO_DDLL_LONG_CMD_1) = params->emc_pmacro_ddll_long_cmd_1; EMC(EMC_PMACRO_DDLL_LONG_CMD_2) = params->emc_pmacro_ddll_long_cmd_2; @@ -242,10 +291,17 @@ break_nosleep: EMC(EMC_PMACRO_DDLL_SHORT_CMD_0) = params->emc_pmacro_ddll_short_cmd_0; EMC(EMC_PMACRO_DDLL_SHORT_CMD_1) = params->emc_pmacro_ddll_short_cmd_1; EMC(EMC_PMACRO_DDLL_SHORT_CMD_2) = params->emc_pmacro_ddll_short_cmd_2; + + // Common pad macro (cpm). EMC(EMC_PMACRO_COMMON_PAD_TX_CTRL) = (params->emc_pmacro_common_pad_tx_ctrl & 1) | 0xE; + + // Patch 3 using BCT spare variables. if (params->emc_bct_spare4) *(vu32 *)params->emc_bct_spare4 = params->emc_bct_spare5; - EMC(EMC_TIMING_CONTROL) = 1; + + EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place. + + // Initialize MC VPR settings. MC(MC_VIDEO_PROTECT_BOM) = params->mc_video_protect_bom; MC(MC_VIDEO_PROTECT_BOM_ADR_HI) = params->mc_video_protect_bom_adr_hi; MC(MC_VIDEO_PROTECT_SIZE_MB) = params->mc_video_protect_size_mb; @@ -253,20 +309,32 @@ break_nosleep: MC(MC_VIDEO_PROTECT_VPR_OVERRIDE1) = params->mc_video_protect_vpr_override1; MC(MC_VIDEO_PROTECT_GPU_OVERRIDE_0) = params->mc_video_protect_gpu_override0; MC(MC_VIDEO_PROTECT_GPU_OVERRIDE_1) = params->mc_video_protect_gpu_override1; + + // Program SDRAM geometry parameters. MC(MC_EMEM_ADR_CFG) = params->mc_emem_adr_cfg; MC(MC_EMEM_ADR_CFG_DEV0) = params->mc_emem_adr_cfg_dev0; MC(MC_EMEM_ADR_CFG_DEV1) = params->mc_emem_adr_cfg_dev1; MC(MC_EMEM_ADR_CFG_CHANNEL_MASK) = params->mc_emem_adr_cfg_channel_mask; + + // Program bank swizzling. MC(MC_EMEM_ADR_CFG_BANK_MASK_0) = params->mc_emem_adr_cfg_bank_mask0; MC(MC_EMEM_ADR_CFG_BANK_MASK_1) = params->mc_emem_adr_cfg_bank_mask1; MC(MC_EMEM_ADR_CFG_BANK_MASK_2) = params->mc_emem_adr_cfg_bank_mask2; + + // Program external memory aperture (base and size). MC(MC_EMEM_CFG) = params->mc_emem_cfg; + + // Program SEC carveout (base and size). MC(MC_SEC_CARVEOUT_BOM) = params->mc_sec_carveout_bom; MC(MC_SEC_CARVEOUT_ADR_HI) = params->mc_sec_carveout_adr_hi; MC(MC_SEC_CARVEOUT_SIZE_MB) = params->mc_sec_carveout_size_mb; + + // Program MTS carveout (base and size). MC(MC_MTS_CARVEOUT_BOM) = params->mc_mts_carveout_bom; MC(MC_MTS_CARVEOUT_ADR_HI) = params->mc_mts_carveout_adr_hi; MC(MC_MTS_CARVEOUT_SIZE_MB) = params->mc_mts_carveout_size_mb; + + // Program the memory arbiter. MC(MC_EMEM_ARB_CFG) = params->mc_emem_arb_cfg; MC(MC_EMEM_ARB_OUTSTANDING_REQ) = params->mc_emem_arb_outstanding_req; MC(MC_EMEM_ARB_REFPB_HP_CTRL) = params->emc_emem_arb_refpb_hp_ctrl; @@ -295,21 +363,38 @@ break_nosleep: MC(MC_EMEM_ARB_OVERRIDE_1) = params->mc_emem_arb_override1; MC(MC_EMEM_ARB_RSV) = params->mc_emem_arb_rsv; MC(MC_DA_CONFIG0) = params->mc_da_cfg0; - MC(MC_TIMING_CONTROL) = 1; + + MC(MC_TIMING_CONTROL) = 1; // Trigger MC timing update. + + // Program second-level clock enable overrides. MC(MC_CLKEN_OVERRIDE) = params->mc_clken_override; + + // Program statistics gathering. MC(MC_STAT_CONTROL) = params->mc_stat_control; + + // Program SDRAM geometry parameters. EMC(EMC_ADR_CFG) = params->emc_adr_cfg; + + // Program second-level clock enable overrides. EMC(EMC_CLKEN_OVERRIDE) = params->emc_clken_override; + + // Program EMC pad auto calibration. EMC(EMC_PMACRO_AUTOCAL_CFG_0) = params->emc_pmacro_auto_cal_cfg0; EMC(EMC_PMACRO_AUTOCAL_CFG_1) = params->emc_pmacro_auto_cal_cfg1; EMC(EMC_PMACRO_AUTOCAL_CFG_2) = params->emc_pmacro_auto_cal_cfg2; + EMC(EMC_AUTO_CAL_VREF_SEL_0) = params->emc_auto_cal_vref_sel0; EMC(EMC_AUTO_CAL_VREF_SEL_1) = params->emc_auto_cal_vref_sel1; + EMC(EMC_AUTO_CAL_INTERVAL) = params->emc_auto_cal_interval; EMC(EMC_AUTO_CAL_CONFIG) = params->emc_auto_cal_config; usleep(params->emc_auto_cal_wait); + + // Patch 5 using BCT spare variables. if (params->emc_bct_spare8) *(vu32 *)params->emc_bct_spare8 = params->emc_bct_spare9; + + // Program EMC timing configuration. EMC(EMC_CFG_2) = params->emc_cfg2; EMC(EMC_CFG_PIPE) = params->emc_cfg_pipe; EMC(EMC_CFG_PIPE_1) = params->emc_cfg_pipe1; @@ -354,9 +439,11 @@ break_nosleep: EMC(EMC_EINPUT_DURATION) = params->emc_einput_duration; EMC(EMC_PUTERM_EXTRA) = params->emc_puterm_extra; EMC(EMC_PUTERM_WIDTH) = params->emc_puterm_width; + EMC(EMC_PMACRO_COMMON_PAD_TX_CTRL) = params->emc_pmacro_common_pad_tx_ctrl; EMC(EMC_DBG) = params->emc_dbg; EMC(EMC_QRST) = params->emc_qrst; + EMC(EMC_ISSUE_QRST) = 1; EMC(EMC_ISSUE_QRST) = 0; EMC(EMC_QSAFE) = params->emc_qsafe; EMC(EMC_RDV) = params->emc_rdv; @@ -389,6 +476,8 @@ break_nosleep: EMC(EMC_ODT_WRITE) = params->emc_odt_write; EMC(EMC_CFG_DIG_DLL) = params->emc_cfg_dig_dll; EMC(EMC_CFG_DIG_DLL_PERIOD) = params->emc_cfg_dig_dll_period; + + // Don't write CFG_ADR_EN (bit 1) here - lock bit written later. EMC(EMC_FBIO_SPARE) = params->emc_fbio_spare & 0xFFFFFFFD; EMC(EMC_CFG_RSV) = params->emc_cfg_rsv; EMC(EMC_PMC_SCRATCH1) = params->emc_pmc_scratch1; @@ -396,70 +485,104 @@ break_nosleep: EMC(EMC_PMC_SCRATCH3) = params->emc_pmc_scratch3; EMC(EMC_ACPD_CONTROL) = params->emc_acpd_control; EMC(EMC_TXDSRVTTGEN) = params->emc_txdsrvttgen; + + // Set pipe bypass enable bits before sending any DRAM commands. EMC(EMC_CFG) = (params->emc_cfg & 0xE) | 0x3C00000; + + // Patch BootROM. if (params->boot_rom_patch_control & (1 << 31)) { *(vu32 *)(APB_MISC_BASE + params->boot_rom_patch_control * 4) = params->boot_rom_patch_data; - MC(MC_TIMING_CONTROL) = 1; + MC(MC_TIMING_CONTROL) = 1; // Trigger MC timing update. } - PMC(APBDEV_PMC_IO_DPD3_REQ) = ((4 * params->emc_pmc_scratch1 >> 2) + 0x40000000) & 0xCFFF0000; + + // Release SEL_DPD_CMD. + PMC(APBDEV_PMC_IO_DPD3_REQ) = ((params->emc_pmc_scratch1 & 0x3FFFFFFF) | 0x40000000) & 0xCFFF0000; usleep(params->pmc_io_dpd3_req_wait); + + // Set autocal interval if not configured. if (!params->emc_auto_cal_interval) EMC(EMC_AUTO_CAL_CONFIG) = params->emc_auto_cal_config | 0x200; + EMC(EMC_PMACRO_BRICK_CTRL_RFU2) = params->emc_pmacro_brick_ctrl_rfu2; + + // ZQ CAL setup (not actually issuing ZQ CAL now). if (params->emc_zcal_warm_cold_boot_enables & 1) { if (params->memory_type == 2) - EMC(EMC_ZCAL_WAIT_CNT) = 8 * params->emc_zcal_wait_cnt; + EMC(EMC_ZCAL_WAIT_CNT) = params->emc_zcal_wait_cnt << 3; if (params->memory_type == 3) { EMC(EMC_ZCAL_WAIT_CNT) = params->emc_zcal_wait_cnt; EMC(EMC_ZCAL_MRW_CMD) = params->emc_zcal_mrw_cmd; } } - EMC(EMC_TIMING_CONTROL) = 1; + + EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place. usleep(params->emc_timing_control_wait); + + // Deassert HOLD_CKE_LOW. PMC(APBDEV_PMC_DDR_CNTRL) &= 0xFFF8007F; usleep(params->pmc_ddr_ctrl_wait); - if (params->memory_type == 2) + + // Set clock enable signal. + u32 pin_gpio_cfg = (params->emc_pin_gpio_enable << 16) | (params->emc_pin_gpio << 12); + if (params->memory_type == 2 || params->memory_type == 3) { - EMC(EMC_PIN) = (params->emc_pin_gpio_enable << 16) | (params->emc_pin_gpio << 12); + EMC(EMC_PIN) = pin_gpio_cfg; + (void)EMC(EMC_PIN); usleep(params->emc_pin_extra_wait + 200); - EMC(EMC_PIN) = ((params->emc_pin_gpio_enable << 16) | (params->emc_pin_gpio << 12)) + 256; - usleep(params->emc_pin_extra_wait + 500); + EMC(EMC_PIN) = pin_gpio_cfg | 0x100; + (void)EMC(EMC_PIN); } + if (params->memory_type == 3) - { - EMC(EMC_PIN) = (params->emc_pin_gpio_enable << 16) | (params->emc_pin_gpio << 12); - usleep(params->emc_pin_extra_wait + 200); - EMC(EMC_PIN) = ((params->emc_pin_gpio_enable << 16) | (params->emc_pin_gpio << 12)) + 256; usleep(params->emc_pin_extra_wait + 2000); - } - EMC(EMC_PIN) = ((params->emc_pin_gpio_enable << 16) | (params->emc_pin_gpio << 12)) + 0x101; + else if (params->memory_type == 2) + usleep(params->emc_pin_extra_wait + 500); + + // Enable clock enable signal. + EMC(EMC_PIN) = pin_gpio_cfg | 0x101; + (void)EMC(EMC_PIN); usleep(params->emc_pin_program_wait); + + // Send NOP (trigger just needs to be non-zero). if (params->memory_type != 3) EMC(EMC_NOP) = (params->emc_dev_select << 30) + 1; + + // On coldboot w/LPDDR2/3, wait 200 uSec after asserting CKE high. if (params->memory_type == 1) usleep(params->emc_pin_extra_wait + 200); + + // Init zq calibration, if (params->memory_type == 3) { + // Patch 6 using BCT spare variables. if (params->emc_bct_spare10) *(vu32 *)params->emc_bct_spare10 = params->emc_bct_spare11; + + // Write mode registers. EMC(EMC_MRW2) = params->emc_mrw2; EMC(EMC_MRW) = params->emc_mrw1; EMC(EMC_MRW3) = params->emc_mrw3; EMC(EMC_MRW4) = params->emc_mrw4; EMC(EMC_MRW6) = params->emc_mrw6; EMC(EMC_MRW14) = params->emc_mrw14; + EMC(EMC_MRW8) = params->emc_mrw8; EMC(EMC_MRW12) = params->emc_mrw12; EMC(EMC_MRW9) = params->emc_mrw9; EMC(EMC_MRW13) = params->emc_mrw13; + if (params->emc_zcal_warm_cold_boot_enables & 1) { + // Issue ZQCAL start, device 0. EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev0; usleep(params->emc_zcal_init_wait); + + // Issue ZQCAL latch. EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev0 ^ 3; + // Same for device 1. if (!(params->emc_dev_select & 2)) { EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev1; @@ -468,42 +591,64 @@ break_nosleep: } } } + + // Set package and DPD pad control. PMC(APBDEV_PMC_DDR_CFG) = params->pmc_ddr_cfg; + + // Start periodic ZQ calibration (LPDDRx only). if (params->memory_type - 1 <= 2) { EMC(EMC_ZCAL_INTERVAL) = params->emc_zcal_interval; EMC(EMC_ZCAL_WAIT_CNT) = params->emc_zcal_wait_cnt; EMC(EMC_ZCAL_MRW_CMD) = params->emc_zcal_mrw_cmd; } + + // Patch 7 using BCT spare variables. if (params->emc_bct_spare12) *(vu32 *)params->emc_bct_spare12 = params->emc_bct_spare13; - EMC(EMC_TIMING_CONTROL) = 1; + + EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place. + if (params->emc_extra_refresh_num) - EMC(EMC_REF) = ((1 << params->emc_extra_refresh_num << 8) - 0xFD) | (params->emc_pin_gpio << 30); + EMC(EMC_REF) = (((1 << params->emc_extra_refresh_num) - 1) << 8) | (params->emc_dev_select << 30) | 3; + + // Enable refresh. EMC(EMC_REFCTRL) = params->emc_dev_select | 0x80000000; + EMC(EMC_DYN_SELF_REF_CONTROL) = params->emc_dyn_self_ref_control; EMC(EMC_CFG_UPDATE) = params->emc_cfg_update; EMC(EMC_CFG) = params->emc_cfg; EMC(EMC_FDPD_CTRL_DQ) = params->emc_fdpd_ctrl_dq; EMC(EMC_FDPD_CTRL_CMD) = params->emc_fdpd_ctrl_cmd; EMC(EMC_SEL_DPD_CTRL) = params->emc_sel_dpd_ctrl; + + // Write addr swizzle lock bit. EMC(EMC_FBIO_SPARE) = params->emc_fbio_spare | 2; - EMC(EMC_TIMING_CONTROL) = 1; + + EMC(EMC_TIMING_CONTROL) = 1; // Re-trigger timing to latch power saving functions. + + // Enable EMC pipe clock gating. EMC(EMC_CFG_PIPE_CLK) = params->emc_cfg_pipe_clk; + + // Depending on freqency, enable CMD/CLK fdpd. EMC(EMC_FDPD_CTRL_CMD_NO_RAMP) = params->emc_fdpd_ctrl_cmd_no_ramp; - SYSREG(AHB_ARBITRATION_XBAR_CTRL) = (SYSREG(AHB_ARBITRATION_XBAR_CTRL) & 0xFFFEFFFF) | ((params->ahb_arbitration_xbar_ctrl_meminit_done & 0xFFFF) << 16); + + // Enable arbiter. + SYSREG(AHB_ARBITRATION_XBAR_CTRL) = (SYSREG(AHB_ARBITRATION_XBAR_CTRL) & 0xFFFEFFFF) | (params->ahb_arbitration_xbar_ctrl_meminit_done << 16); + + // Lock carveouts per BCT cfg. MC(MC_VIDEO_PROTECT_REG_CTRL) = params->mc_video_protect_write_access; MC(MC_SEC_CARVEOUT_REG_CTRL) = params->mc_sec_carveout_protect_write_access; MC(MC_MTS_CARVEOUT_REG_CTRL) = params->mc_mts_carveout_reg_ctrl; - MC(MC_EMEM_CFG_ACCESS_CTRL) = 1; //Disable write access to a bunch of EMC registers. + + //Disable write access to a bunch of EMC registers. + MC(MC_EMEM_CFG_ACCESS_CTRL) = 1; } sdram_params_t *sdram_get_params() { - //TODO: sdram_id should be in [0, 7]. - #ifdef CONFIG_SDRAM_COMPRESS_CFG - u8 *buf = (u8 *)0x40030000; + u8 *buf = (u8 *)SDRAM_PARAMS_ADDR; LZ_Uncompress(_dram_cfg_lz, buf, sizeof(_dram_cfg_lz)); return (sdram_params_t *)&buf[sizeof(sdram_params_t) * _get_sdram_id()]; #else @@ -535,7 +680,17 @@ sdram_params_t *sdram_get_params_patched() // Disable Warmboot signature check. sdram_params->boot_rom_patch_control = (1 << 31) | (((IPATCH_BASE + 4) - APB_MISC_BASE) / 4); sdram_params->boot_rom_patch_data = IPATCH_CONFIG(0x10459E, 0x2000); +/* + // Disable SBK lock. + sdram_params->emc_bct_spare8 = (IPATCH_BASE + 7 * 4); + sdram_params->emc_bct_spare9 = IPATCH_CONFIG(0x10210E, 0x2000); + // Disable bootrom read lock. + sdram_params->emc_bct_spare10 = (IPATCH_BASE + 10 * 4); + sdram_params->emc_bct_spare11 = IPATCH_CONFIG(0x100FDC, 0xF000); + sdram_params->emc_bct_spare12 = (IPATCH_BASE + 11 * 4); + sdram_params->emc_bct_spare13 = IPATCH_CONFIG(0x100FDE, 0xE320); +*/ return sdram_params; } @@ -544,16 +699,24 @@ void sdram_init() //TODO: sdram_id should be in [0,4]. const sdram_params_t *params = (const sdram_params_t *)sdram_get_params(); + // Set DRAM voltage. i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, 0x05); - max77620_regulator_set_voltage(REGULATOR_SD1, 1100000); // Set DRAM voltage. + max77620_regulator_set_voltage(REGULATOR_SD1, 1100000); + // VDDP Select. PMC(APBDEV_PMC_VDDP_SEL) = params->pmc_vddp_sel; usleep(params->pmc_vddp_sel_wait); + + // Set DDR pad voltage. PMC(APBDEV_PMC_DDR_PWR) = PMC(APBDEV_PMC_DDR_PWR); + + // Turn on MEM IO Power. PMC(APBDEV_PMC_NO_IOPOWER) = params->pmc_no_io_power; PMC(APBDEV_PMC_REG_SHORT) = params->pmc_reg_short; + PMC(APBDEV_PMC_DDR_CNTRL) = params->pmc_ddr_ctrl; + // Patch 1 using BCT spare variables if (params->emc_bct_spare0) *(vu32 *)params->emc_bct_spare0 = params->emc_bct_spare1; diff --git a/source/mem/sdram_lp0_param_t210.h b/source/mem/sdram_lp0_param_t210.h index 7f44f1d..9028990 100644 --- a/source/mem/sdram_lp0_param_t210.h +++ b/source/mem/sdram_lp0_param_t210.h @@ -1,7 +1,7 @@ /* * Copyright (c) 2013-2015, NVIDIA CORPORATION. All rights reserved. * Copyright 2014 Google Inc. - * Copyright (C) 2018 CTCaer + * Copyright (c) 2018 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/source/power/max17050.c b/source/power/max17050.c index 227f76b..635a437 100644 --- a/source/power/max17050.c +++ b/source/power/max17050.c @@ -1,9 +1,9 @@ /* * Fuel gauge driver for Nintendo Switch's Maxim 17050 * - * Copyright (C) 2011 Samsung Electronics + * Copyright (c) 2011 Samsung Electronics * MyungJoo Ham - * Copyright (C) 2018 CTCaer + * Copyright (c) 2018 CTCaer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -43,6 +43,9 @@ #define MAX17050_VMAX_TOLERANCE 50 /* 50 mV */ +#pragma GCC push_options +#pragma GCC optimize ("Os") + int max17050_get_property(enum MAX17050_reg reg, int *value) { u16 data; @@ -264,3 +267,5 @@ int max17050_fix_configuration() return 0; } + +#pragma GCC pop_options \ No newline at end of file diff --git a/source/power/max17050.h b/source/power/max17050.h index 2196b80..e4c8acf 100644 --- a/source/power/max17050.h +++ b/source/power/max17050.h @@ -2,9 +2,9 @@ * Fuel gauge driver for Nintendo Switch's Maxim 17050 * Note that Maxim 8966 and 8997 are mfd and this is its subdevice. * - * Copyright (C) 2011 Samsung Electronics + * Copyright (c) 2011 Samsung Electronics * MyungJoo Ham - * Copyright (C) 2018 CTCaer + * Copyright (c) 2018 CTCaer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/source/power/max77620.h b/source/power/max77620.h index 479661d..26ea855 100644 --- a/source/power/max77620.h +++ b/source/power/max77620.h @@ -1,7 +1,7 @@ /* * Defining registers address and its bit definitions of MAX77620 and MAX20024 * - * Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2016 NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2019 CTCaer * * This program is free software; you can redistribute it and/or modify it @@ -19,9 +19,19 @@ #define MAX77620_CNFGGLBL1_LBDAC_EN (1 << 7) #define MAX77620_CNFGGLBL1_MPPLD (1 << 6) #define MAX77620_CNFGGLBL1_LBHYST ((1 << 5) | (1 << 4)) -#define MAX77620_CNFGGLBL1_LBHYST_N (1 << 4) -#define MAX77620_CNFGGLBL1_LBDAC 0x0E -#define MAX77620_CNFGGLBL1_LBDAC_N (1 << 1) +#define MAX77620_CNFGGLBL1_LBHYST_100 (0 << 4) +#define MAX77620_CNFGGLBL1_LBHYST_200 (1 << 4) +#define MAX77620_CNFGGLBL1_LBHYST_300 (2 << 4) +#define MAX77620_CNFGGLBL1_LBHYST_400 (3 << 4) +#define MAX77620_CNFGGLBL1_LBDAC_MASK 0x0E +#define MAX77620_CNFGGLBL1_LBDAC_2700 (0 << 1) +#define MAX77620_CNFGGLBL1_LBDAC_2800 (1 << 1) +#define MAX77620_CNFGGLBL1_LBDAC_2900 (2 << 1) +#define MAX77620_CNFGGLBL1_LBDAC_3000 (3 << 1) +#define MAX77620_CNFGGLBL1_LBDAC_3100 (4 << 1) +#define MAX77620_CNFGGLBL1_LBDAC_3200 (5 << 1) +#define MAX77620_CNFGGLBL1_LBDAC_3300 (6 << 1) +#define MAX77620_CNFGGLBL1_LBDAC_3400 (7 << 1) #define MAX77620_CNFGGLBL1_LBRSTEN (1 << 0) #define MAX77620_REG_CNFGGLBL2 0x01 diff --git a/source/power/max7762x.c b/source/power/max7762x.c index 2c8cff4..0e7a6b5 100644 --- a/source/power/max7762x.c +++ b/source/power/max7762x.c @@ -64,6 +64,16 @@ static const max77620_regulator_t _pmic_regulators[] = { { REGULATOR_LDO, "ldo8", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO8, 3, 7, 0 } }; +static void _max77620_try_set_reg(u8 reg, u8 val) +{ + u8 tmp; + do + { + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, reg, val); + tmp = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg); + } while (val != tmp); +} + int max77620_regulator_get_status(u32 id) { if (id > REGULATOR_MAX) @@ -83,7 +93,7 @@ int max77620_regulator_config_fps(u32 id) const max77620_regulator_t *reg = &_pmic_regulators[id]; - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, reg->fps_addr, + _max77620_try_set_reg(reg->fps_addr, (reg->fps_src << MAX77620_FPS_SRC_SHIFT) | (reg->pu_period << MAX77620_FPS_PU_PERIOD_SHIFT) | (reg->pd_period)); return 1; @@ -102,7 +112,7 @@ int max77620_regulator_set_voltage(u32 id, u32 mv) u32 mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step; u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->volt_addr); val = (val & ~reg->volt_mask) | (mult & reg->volt_mask); - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, reg->volt_addr, val); + _max77620_try_set_reg(reg->volt_addr, val); usleep(1000); return 1; @@ -121,7 +131,7 @@ int max77620_regulator_enable(u32 id, int enable) val = (val & ~reg->enable_mask) | ((MAX77620_POWER_MODE_NORMAL << reg->enable_shift) & reg->enable_mask); else val &= ~reg->enable_mask; - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, addr, val); + _max77620_try_set_reg(addr, val); usleep(1000); return 1; @@ -139,7 +149,7 @@ int max77620_regulator_set_volt_and_flags(u32 id, u32 mv, u8 flags) u32 mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step; u8 val = ((flags << reg->enable_shift) & ~reg->volt_mask) | (mult & reg->volt_mask); - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, reg->volt_addr, val); + _max77620_try_set_reg(reg->volt_addr, val); usleep(1000); return 1; @@ -155,11 +165,12 @@ void max77620_config_default() if (_pmic_regulators[i].fps_src != MAX77620_FPS_SRC_NONE) max77620_regulator_enable(i, 1); } - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, 4); + _max77620_try_set_reg(MAX77620_REG_SD_CFG2, 4); } void max77620_low_battery_monitor_config() { - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CNFGGLBL1, - MAX77620_CNFGGLBL1_LBDAC_EN | MAX77620_CNFGGLBL1_LBHYST_N | MAX77620_CNFGGLBL1_LBDAC_N); + _max77620_try_set_reg(MAX77620_REG_CNFGGLBL1, + MAX77620_CNFGGLBL1_LBDAC_EN | MAX77620_CNFGGLBL1_MPPLD | + MAX77620_CNFGGLBL1_LBHYST_200 | MAX77620_CNFGGLBL1_LBDAC_2800); } diff --git a/source/sec/se.c b/source/sec/se.c index 3074b9e..7416d38 100644 --- a/source/sec/se.c +++ b/source/sec/se.c @@ -86,8 +86,8 @@ static int _se_wait() while (!(SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_OP_DONE(INT_SET))) ; if (SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_ERROR(INT_SET) || - SE(SE_STATUS_0) & 3 || - SE(SE_ERR_STATUS_0) != 0) + SE(SE_STATUS_0) & SE_STATUS_0_STATE_WAIT_IN || + SE(SE_ERR_STATUS_0) != SE_ERR_STATUS_0_SE_NS_ACCESS_CLEAR) return 0; return 1; } @@ -111,12 +111,12 @@ static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src SE(SE_ERR_STATUS_0) = SE(SE_ERR_STATUS_0); SE(SE_INT_STATUS_REG_OFFSET) = SE(SE_INT_STATUS_REG_OFFSET); - bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY); + bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); SE(SE_OPERATION_REG_OFFSET) = SE_OPERATION(op); int res = _se_wait(); - bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY); + bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); return res; } @@ -148,9 +148,11 @@ static void _se_aes_ctr_set(void *ctr) void se_rsa_acc_ctrl(u32 rs, u32 flags) { - if (flags & 0x7F) - SE(SE_RSA_KEYTABLE_ACCESS_REG_OFFSET + 4 * rs) = (((flags >> 4) & 4) | (flags & 3)) ^ 7; - if (flags & 0x80) + if (flags & SE_RSA_KEY_TBL_DIS_KEY_ALL_FLAG) + SE(SE_RSA_KEYTABLE_ACCESS_REG_OFFSET + 4 * rs) = + ((flags >> SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) | + ((flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG) ^ SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG); + if (flags & SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG) SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) &= ~(1 << rs); } @@ -216,9 +218,9 @@ int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_siz void se_key_acc_ctrl(u32 ks, u32 flags) { - if (flags & 0x7F) + if (flags & SE_KEY_TBL_DIS_KEY_ACCESS_FLAG) SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 4 * ks) = ~flags; - if (flags & 0x80) + if (flags & SE_KEY_TBL_DIS_KEY_LOCK_FLAG) SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) &= ~(1 << ks); } @@ -424,15 +426,15 @@ int se_calc_sha256(void *dst, const void *src, u32 src_size) int res; // Setup config for SHA256, size = BITS(src_size). SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG); - SE(SE_SHA_CONFIG_REG_OFFSET) = SHA_INIT_ENABLE; - SE(SE_SHA_MSG_LENGTH_REG_OFFSET) = (u32)(src_size << 3); - SE(SE_SHA_MSG_LENGTH_REG_OFFSET + 4 * 1) = 0; - SE(SE_SHA_MSG_LENGTH_REG_OFFSET + 4 * 2) = 0; - SE(SE_SHA_MSG_LENGTH_REG_OFFSET + 4 * 3) = 0; - SE(SE_SHA_MSG_LEFT_REG_OFFSET) = (u32)(src_size << 3); - SE(SE_SHA_MSG_LEFT_REG_OFFSET + 4 * 1) = 0; - SE(SE_SHA_MSG_LEFT_REG_OFFSET + 4 * 2) = 0; - SE(SE_SHA_MSG_LEFT_REG_OFFSET + 4 * 3) = 0; + SE(SE_SHA_CONFIG_REG_OFFSET) = SHA_INIT_HASH; + SE(SE_SHA_MSG_LENGTH_0_REG_OFFSET) = (u32)(src_size << 3); + SE(SE_SHA_MSG_LENGTH_1_REG_OFFSET) = 0; + SE(SE_SHA_MSG_LENGTH_2_REG_OFFSET) = 0; + SE(SE_SHA_MSG_LENGTH_3_REG_OFFSET) = 0; + SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = (u32)(src_size << 3); + SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = 0; + SE(SE_SHA_MSG_LEFT_2_REG_OFFSET) = 0; + SE(SE_SHA_MSG_LEFT_3_REG_OFFSET) = 0; // Trigger the operation. res = _se_execute(OP_START, NULL, 0, src, src_size); diff --git a/source/sec/se_t210.h b/source/sec/se_t210.h index 7d93099..3b610bc 100644 --- a/source/sec/se_t210.h +++ b/source/sec/se_t210.h @@ -36,6 +36,8 @@ #define SE_SECURITY_0 0x000 #define SE_KEY_SCHED_READ_SHIFT 3 +#define SE_TZRAM_SECURITY_0 0x004 + #define SE_CONFIG_REG_OFFSET 0x014 #define SE_CONFIG_ENC_ALG_SHIFT 12 #define SE_CONFIG_DEC_ALG_SHIFT 8 @@ -209,8 +211,12 @@ #define SE_INT_OP_DONE(x) (x << SE_INT_OP_DONE_SHIFT) #define SE_INT_ERROR_SHIFT 16 #define SE_INT_ERROR(x) (x << SE_INT_ERROR_SHIFT) + #define SE_STATUS_0 0x800 +#define SE_STATUS_0_STATE_WAIT_IN 3 + #define SE_ERR_STATUS_0 0x804 +#define SE_ERR_STATUS_0_SE_NS_ACCESS_CLEAR 0 #define SE_CRYPTO_KEYTABLE_DST_REG_OFFSET 0X330 #define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT 0 @@ -231,11 +237,17 @@ #define SE_SPARE_0_REG_OFFSET 0x80c #define SE_SHA_CONFIG_REG_OFFSET 0x200 -#define SHA_INIT_DISABLE 0 -#define SHA_INIT_ENABLE 1 +#define SHA_CONTINUE 0 +#define SHA_INIT_HASH 1 -#define SE_SHA_MSG_LENGTH_REG_OFFSET 0x204 -#define SE_SHA_MSG_LEFT_REG_OFFSET 0x214 +#define SE_SHA_MSG_LENGTH_0_REG_OFFSET 0x204 +#define SE_SHA_MSG_LENGTH_1_REG_OFFSET 0x208 +#define SE_SHA_MSG_LENGTH_2_REG_OFFSET 0x20C +#define SE_SHA_MSG_LENGTH_3_REG_OFFSET 0x210 +#define SE_SHA_MSG_LEFT_0_REG_OFFSET 0x214 +#define SE_SHA_MSG_LEFT_1_REG_OFFSET 0x218 +#define SE_SHA_MSG_LEFT_2_REG_OFFSET 0x21C +#define SE_SHA_MSG_LEFT_3_REG_OFFSET 0x220 #define SE_HASH_RESULT_REG_COUNT 16 #define SE_HASH_RESULT_REG_OFFSET 0x030 @@ -254,13 +266,24 @@ TEGRA_SE_RNG_DT_SIZE) #define TEGRA_SE_AES_CMAC_DIGEST_SIZE 16 -#define TEGRA_SE_RSA512_DIGEST_SIZE 64 +#define TEGRA_SE_RSA512_DIGEST_SIZE 64 #define TEGRA_SE_RSA1024_DIGEST_SIZE 128 #define TEGRA_SE_RSA1536_DIGEST_SIZE 192 #define TEGRA_SE_RSA2048_DIGEST_SIZE 256 #define SE_KEY_TABLE_ACCESS_LOCK_OFFSET 0x280 +#define SE_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80 + #define SE_KEY_TABLE_ACCESS_REG_OFFSET 0x284 +#define SE_KEY_TBL_DIS_KEYREAD_FLAG (1 << 0) +#define SE_KEY_TBL_DIS_KEYUPDATE_FLAG (1 << 1) +#define SE_KEY_TBL_DIS_OIVREAD_FLAG (1 << 2) +#define SE_KEY_TBL_DIS_OIVUPDATE_FLAG (1 << 3) +#define SE_KEY_TBL_DIS_UIVREAD_FLAG (1 << 4) +#define SE_KEY_TBL_DIS_UIVUPDATE_FLAG (1 << 5) +#define SE_KEY_TBL_DIS_KEYUSE_FLAG (1 << 6) +#define SE_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F + #define SE_KEY_READ_DISABLE_SHIFT 0 #define SE_KEY_UPDATE_DISABLE_SHIFT 1 @@ -312,7 +335,16 @@ #define TEGRA_SE_RSA_KEYSLOT_COUNT 2 #define SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET 0x40C +#define SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80 + #define SE_RSA_KEYTABLE_ACCESS_REG_OFFSET 0x410 +#define SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG (1 << 0) +#define SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG (1 << 1) +#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG) +#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG (1 << 2) +#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT (1 << 2) +#define SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG 7 +#define SE_RSA_KEY_TBL_DIS_KEY_ALL_FLAG 0x7F #define SE_RSA_KEYTABLE_ADDR 0x420 #define SE_RSA_KEYTABLE_DATA 0x424 diff --git a/source/sec/tsec.c b/source/sec/tsec.c index e07ca83..17cd623 100644 --- a/source/sec/tsec.c +++ b/source/sec/tsec.c @@ -23,6 +23,7 @@ #include "../sec/se_t210.h" #include "../soc/bpmp.h" #include "../soc/clock.h" +#include "../soc/kfuse.h" #include "../soc/smmu.h" #include "../soc/t210.h" #include "../mem/heap.h" @@ -77,6 +78,8 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt) clock_enable_sor1(); clock_enable_kfuse(); + kfuse_wait_ready(); + //Configure Falcon. TSEC(TSEC_DMACTL) = 0; TSEC(TSEC_IRQMSET) = @@ -208,7 +211,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt) res = -6; smmu_deinit_for_tsec(); - goto out; + goto out_free; } // Give some extra time to make sure PKG1.1 is decrypted. @@ -278,7 +281,7 @@ out:; clock_disable_sor_safe(); clock_disable_tsec(); bpmp_mmu_enable(); - bpmp_clk_rate_set(BPMP_CLK_SUPER_BOOST); + bpmp_clk_rate_set(BPMP_CLK_DEFAULT_BOOST); return res; } diff --git a/source/soc/bpmp.c b/source/soc/bpmp.c index 3d6091d..94ce6d5 100644 --- a/source/soc/bpmp.c +++ b/source/soc/bpmp.c @@ -19,6 +19,7 @@ #include "bpmp.h" #include "clock.h" #include "t210.h" +#include "../../common/memory_map.h" #include "../utils/util.h" #define BPMP_CACHE_CONFIG 0x0 @@ -74,13 +75,13 @@ bpmp_mmu_entry_t mmu_entries[] = { - { 0x80000000, 0xFFFFFFFF, MMU_EN_READ | MMU_EN_WRITE | MMU_EN_EXEC | MMU_EN_CACHED, true }, - { IPL_LOAD_ADDR, 0x40040000, MMU_EN_READ | MMU_EN_WRITE | MMU_EN_EXEC | MMU_EN_CACHED, true } + { DRAM_START, 0xFFFFFFFF, MMU_EN_READ | MMU_EN_WRITE | MMU_EN_EXEC | MMU_EN_CACHED, true }, + { IRAM_BASE, 0x4003FFFF, MMU_EN_READ | MMU_EN_WRITE | MMU_EN_EXEC | MMU_EN_CACHED, true } }; -void bpmp_mmu_maintenance(u32 op) +void bpmp_mmu_maintenance(u32 op, bool force) { - if (!(BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) & CFG_ENABLE)) + if (!force && !(BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) & CFG_ENABLE)) return; BPMP_CACHE_CTRL(BPMP_CACHE_INT_CLEAR) = INT_CLR_MAINT_DONE; @@ -132,13 +133,13 @@ void bpmp_mmu_enable() BPMP_CACHE_CTRL(BPMP_CACHE_MMU_CMD) = MMU_CMD_COPY_SHADOW; // Invalidate cache. - bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY); + bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY, true); // Enable cache. BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) = CFG_ENABLE | CFG_FORCE_WRITE_THROUGH | CFG_TAG_CHK_ABRT_ON_ERR; // HW bug. Invalidate cache again. - bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY); + bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY, false); } void bpmp_mmu_disable() @@ -147,21 +148,19 @@ void bpmp_mmu_disable() return; // Clean and invalidate cache. - bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY); + bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); // Disable cache. BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) = 0; - - // HW bug. Invalidate cache again. - bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY); } const u8 pllc4_divn[] = { 0, // BPMP_CLK_NORMAL: 408MHz 0% - 136MHz APB. - 85, // BPMP_CLK_LOW_BOOST: 544MHz 33% - 136MHz APB. - 90, // BPMP_CLK_MID_BOOST: 576MHz 41% - 144MHz APB. - 94 // BPMP_CLK_SUPER_BOOST: 602MHz 48% - 150MHz APB. - //95 // BPMP_CLK_SUPER_BOOST: 608MHz 49% - 152MHz APB. + 85, // BPMP_CLK_HIGH_BOOST: 544MHz 33% - 136MHz APB. + 90, // BPMP_CLK_SUPER_BOOST: 576MHz 41% - 144MHz APB. + 92 // BPMP_CLK_HYPER_BOOST: 589MHz 44% - 147MHz APB. + // Do not use for public releases! + //95 // BPMP_CLK_DEV_BOOST: 608MHz 49% - 152MHz APB. }; bpmp_freq_t bpmp_clock_set = BPMP_CLK_NORMAL; diff --git a/source/soc/bpmp.h b/source/soc/bpmp.h index b45ab7a..4c1155e 100644 --- a/source/soc/bpmp.h +++ b/source/soc/bpmp.h @@ -36,13 +36,16 @@ typedef struct _bpmp_mmu_entry_t typedef enum { BPMP_CLK_NORMAL, // 408MHz 0% - 136MHz APB. - BPMP_CLK_LOW_BOOST, // 544MHz 33% - 136MHz APB. - BPMP_CLK_MID_BOOST, // 576MHz 41% - 144MHz APB. - BPMP_CLK_SUPER_BOOST, // 608MHz 49% - 152MHz APB. + BPMP_CLK_HIGH_BOOST, // 544MHz 33% - 136MHz APB. + BPMP_CLK_SUPER_BOOST, // 576MHz 41% - 144MHz APB. + BPMP_CLK_HYPER_BOOST, // 589MHz 44% - 147MHz APB. + //BPMP_CLK_DEV_BOOST, // 608MHz 49% - 152MHz APB. BPMP_CLK_MAX } bpmp_freq_t; -void bpmp_mmu_maintenance(u32 op); +#define BPMP_CLK_DEFAULT_BOOST BPMP_CLK_HYPER_BOOST + +void bpmp_mmu_maintenance(u32 op, bool force); void bpmp_mmu_set_entry(int idx, bpmp_mmu_entry_t *entry, bool apply); void bpmp_mmu_enable(); void bpmp_mmu_disable(); diff --git a/source/soc/clock.c b/source/soc/clock.c index 0726748..dda6d4b 100644 --- a/source/soc/clock.c +++ b/source/soc/clock.c @@ -15,7 +15,6 @@ */ #include "../soc/clock.h" -#include "../soc/kfuse.h" #include "../soc/t210.h" #include "../utils/util.h" #include "../storage/sdmmc.h" @@ -30,13 +29,14 @@ static const clock_t _clock_uart[] = { /* UART E */ { CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE, 20, 0, 2 } }; +//I2C default parameters - TLOW: 4, THIGH: 2, DEBOUNCE: 0 FM_DIV: 26. static const clock_t _clock_i2c[] = { -/* I2C1 */ { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_I2C1, 12, 6, 0 }, // 0, 19 }, // 100KHz -/* I2C2 */ { 0 }, -/* I2C3 */ { 0 }, -/* I2C4 */ { 0 }, -/* I2C5 */ { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C5, 15, 6, 0 }, // 0, 4 }, // 400KHz -/* I2C6 */ { 0 } +/* I2C1 */ { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_I2C1, 12, 0, 19 }, //20.4MHz -> 100KHz +/* I2C2 */ { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C2, 22, 0, 4 }, //81.6MHz -> 400KHz +/* I2C3 */ { CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_I2C3, 3, 0, 4 }, //81.6MHz -> 400KHz +/* I2C4 */ { CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_I2C4, 7, 0, 19 }, //20.4MHz -> 100KHz +/* I2C5 */ { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C5, 15, 0, 4 }, //81.6MHz -> 400KHz +/* I2C6 */ { CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_I2C6, 6, 0, 19 } //20.4MHz -> 100KHz }; static clock_t _clock_se = { @@ -74,7 +74,7 @@ static clock_t _clock_coresight = { }; static clock_t _clock_pwm = { - CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, 17, 6, 4 // Freference: 6.2MHz. + CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, 17, 6, 4 // Fref: 6.2MHz. }; void clock_enable(const clock_t *clk) @@ -88,6 +88,8 @@ void clock_enable(const clock_t *clk) CLOCK(clk->source) = clk->clk_div | (clk->clk_src << 29); // Enable. CLOCK(clk->enable) = (CLOCK(clk->enable) & ~(1 << clk->index)) | (1 << clk->index); + usleep(2); + // Take clock off reset. CLOCK(clk->reset) &= ~(1 << clk->index); } @@ -189,7 +191,6 @@ void clock_enable_kfuse() usleep(10); CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) &= 0xFFFFFEFF; usleep(20); - kfuse_wait_ready(); } void clock_disable_kfuse() @@ -368,7 +369,7 @@ static void _clock_sdmmc_clear_enable(u32 id) static u32 _clock_sdmmc_table[8] = { 0 }; #define PLLP_OUT0 0x0 -static int _clock_sdmmc_config_clock_source_inner(u32 *pout, u32 id, u32 val) +static int _clock_sdmmc_config_clock_host(u32 *pout, u32 id, u32 val) { u32 divisor = 0; u32 source = PLLP_OUT0; @@ -416,6 +417,7 @@ static int _clock_sdmmc_config_clock_source_inner(u32 *pout, u32 id, u32 val) _clock_sdmmc_table[2 * id] = val; _clock_sdmmc_table[2 * id + 1] = *pout; + // Set SDMMC clock. switch (id) { case SDMMC_1: @@ -446,15 +448,16 @@ void clock_sdmmc_config_clock_source(u32 *pout, u32 id, u32 val) int is_enabled = _clock_sdmmc_is_enabled(id); if (is_enabled) _clock_sdmmc_clear_enable(id); - _clock_sdmmc_config_clock_source_inner(pout, id, val); + _clock_sdmmc_config_clock_host(pout, id, val); if (is_enabled) _clock_sdmmc_set_enable(id); _clock_sdmmc_is_reset(id); } } -void clock_sdmmc_get_params(u32 *pout, u16 *pdivisor, u32 type) +void clock_sdmmc_get_card_clock_div(u32 *pout, u16 *pdivisor, u32 type) { + // Get Card clock divisor. switch (type) { case 0: @@ -515,7 +518,7 @@ void clock_sdmmc_enable(u32 id, u32 val) if (_clock_sdmmc_is_enabled(id)) _clock_sdmmc_clear_enable(id); _clock_sdmmc_set_reset(id); - _clock_sdmmc_config_clock_source_inner(&div, id, val); + _clock_sdmmc_config_clock_host(&div, id, val); _clock_sdmmc_set_enable(id); _clock_sdmmc_is_reset(id); usleep((100000 + div - 1) / div); diff --git a/source/soc/clock.h b/source/soc/clock.h index db7a974..ce6a81d 100644 --- a/source/soc/clock.h +++ b/source/soc/clock.h @@ -104,6 +104,7 @@ #define CLK_RST_CONTROLLER_CLK_SOURCE_SYS 0x400 #define CLK_RST_CONTROLLER_CLK_SOURCE_SOR1 0x410 #define CLK_RST_CONTROLLER_CLK_SOURCE_SE 0x42C +#define CLK_RST_CONTROLLER_RST_DEV_V_CLR 0x434 #define CLK_RST_CONTROLLER_CLK_ENB_V_SET 0x440 #define CLK_RST_CONTROLLER_CLK_ENB_V_CLR 0x444 #define CLK_RST_CONTROLLER_CLK_ENB_W_SET 0x448 @@ -181,7 +182,7 @@ void clock_disable_coresight(); void clock_enable_pwm(); void clock_disable_pwm(); void clock_sdmmc_config_clock_source(u32 *pout, u32 id, u32 val); -void clock_sdmmc_get_params(u32 *pout, u16 *pdivisor, u32 type); +void clock_sdmmc_get_card_clock_div(u32 *pout, u16 *pdivisor, u32 type); int clock_sdmmc_is_not_reset_and_enabled(u32 id); void clock_sdmmc_enable(u32 id, u32 val); void clock_sdmmc_disable(u32 id); diff --git a/source/soc/cluster.c b/source/soc/cluster.c index 0791d36..79538ed 100644 --- a/source/soc/cluster.c +++ b/source/soc/cluster.c @@ -80,9 +80,9 @@ void cluster_boot_cpu0(u32 entry) _cluster_enable_power(); - if (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & 0x40000000)) + if (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & 0x40000000)) // PLLX_ENABLE. { - CLOCK(CLK_RST_CONTROLLER_PLLX_MISC_3) &= 0xFFFFFFF7; + CLOCK(CLK_RST_CONTROLLER_PLLX_MISC_3) &= 0xFFFFFFF7; // Disable IDDQ. usleep(2); CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x80404E02; CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x404E02; @@ -127,6 +127,9 @@ void cluster_boot_cpu0(u32 entry) SB(SB_CSR) = SB_CSR_NS_RST_VEC_WR_DIS; (void)SB(SB_CSR); + // Tighten up the security aperture. + // MC(MC_TZ_SECURITY_CTRL) = 1; + // Clear MSELECT reset. CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_V) &= 0xFFFFFFF7; // Clear NONCPU reset. diff --git a/source/soc/fuse.c b/source/soc/fuse.c index c53389e..04d3612 100644 --- a/source/soc/fuse.c +++ b/source/soc/fuse.c @@ -22,6 +22,34 @@ #include "../soc/fuse.h" #include "../soc/t210.h" +#define ARRAYSIZE(x) (sizeof(x) / sizeof(*x)) + +static const u32 evp_thunk_template[] = { + 0xe92d0007, // STMFD SP!, {R0-R2} + 0xe1a0200e, // MOV R2, LR + 0xe2422002, // SUB R2, R2, #2 + 0xe5922000, // LDR R2, [R2] + 0xe20220ff, // AND R2, R2, #0xFF + 0xe1a02082, // MOV R2, R2,LSL#1 + 0xe59f001c, // LDR R0, =evp_thunk_template + 0xe59f101c, // LDR R1, =thunk_end + 0xe0411000, // SUB R1, R1, R0 + 0xe59f0018, // LDR R0, =iram_evp_thunks + 0xe0800001, // ADD R0, R0, R1 + 0xe0822000, // ADD R2, R2, R0 + 0xe3822001, // ORR R2, R2, #1 + 0xe8bd0003, // LDMFD SP!, {R0,R1} + 0xe12fff12, // BX R2 + 0x001007b0, // off_1007EC DCD evp_thunk_template + 0x001007f8, // off_1007F0 DCD thunk_end + 0x40004c30, // off_1007F4 DCD iram_evp_thunks + // thunk_end is here +}; +static const u32 evp_thunk_template_len = sizeof(evp_thunk_template); + +// treated as 12bit values +static const u32 hash_vals[] = {1, 2, 4, 8, 0, 3, 5, 6, 7, 9, 10, 11}; + void fuse_disable_program() { FUSE(FUSE_DISABLEREGPROGRAM) = 1; @@ -31,3 +59,291 @@ u32 fuse_read_odm(u32 idx) { return FUSE(FUSE_RESERVED_ODMX(idx)); } + +void fuse_wait_idle() +{ + u32 ctrl; + do + { + ctrl = FUSE(FUSE_CTRL); + } while (((ctrl >> 16) & 0x1f) != 4); +} + +u32 fuse_read(u32 addr) +{ + FUSE(FUSE_ADDR) = addr; + FUSE(FUSE_CTRL) = (FUSE(FUSE_ADDR) & ~FUSE_CMD_MASK) | FUSE_READ; + fuse_wait_idle(); + return FUSE(FUSE_RDATA); +} + +void fuse_read_array(u32 *words) +{ + for (u32 i = 0; i < 192; i++) + words[i] = fuse_read(i); +} + +static u32 _parity32_even(u32 *words, u32 count) +{ + u32 acc = words[0]; + for (u32 i = 1; i < count; i++) + { + acc ^= words[i]; + } + u32 lo = ((acc & 0xffff) ^ (acc >> 16)) & 0xff; + u32 hi = ((acc & 0xffff) ^ (acc >> 16)) >> 8; + u32 x = hi ^ lo; + lo = ((x & 0xf) ^ (x >> 4)) & 3; + hi = ((x & 0xf) ^ (x >> 4)) >> 2; + x = hi ^ lo; + + return (x & 1) ^ (x >> 1); +} + +static int _patch_hash_one(u32 *word) +{ + u32 bits20_31 = *word & 0xfff00000; + u32 parity_bit = _parity32_even(&bits20_31, 1); + u32 hash = 0; + for (u32 i = 0; i < 12; i++) + { + if (*word & (1 << (20 + i))) + { + hash ^= hash_vals[i]; + } + } + if (hash == 0) + { + if (parity_bit == 0) + { + return 0; + } + *word ^= 1 << 24; + return 1; + } + if (parity_bit == 0) + { + return 3; + } + for (u32 i = 0; i < ARRAYSIZE(hash_vals); i++) + { + if (hash_vals[i] == hash) + { + *word ^= 1 << (20 + i); + return 1; + } + } + return 2; +} + +static int _patch_hash_multi(u32 *words, u32 count) +{ + u32 parity_bit = _parity32_even(words, count); + u32 bits0_14 = words[0] & 0x7fff; + u32 bit15 = words[0] & 0x8000; + u32 bits16_19 = words[0] & 0xf0000; + + u32 hash = 0; + words[0] = bits16_19; + for (u32 i = 0; i < count; i++) + { + u32 w = words[i]; + if (w) + { + for (u32 bitpos = 0; bitpos < 32; bitpos++) + { + if ((w >> bitpos) & 1) + { + hash ^= 0x4000 + i * 32 + bitpos; + } + } + } + } + hash ^= bits0_14; + // stupid but this is what original code does. + // equivalent to original words[0] &= 0xfff00000 + words[0] = bits16_19 ^ bit15 ^ bits0_14; + + if (hash == 0) + { + if (parity_bit == 0) + { + return 0; + } + words[0] ^= 0x8000; + return 1; + } + if (parity_bit == 0) + { + return 3; + } + u32 bitcount = hash - 0x4000; + if (bitcount < 16 || bitcount >= count * 32) + { + u32 num_set = 0; + for (u32 bitpos = 0; bitpos < 15; bitpos++) + { + if ((hash >> bitpos) & 1) + { + num_set++; + } + } + if (num_set != 1) + { + return 2; + } + words[0] ^= hash; + return 1; + } + words[bitcount / 32] ^= 1 << (hash & 0x1f); + return 1; +} + +int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value)) +{ + u32 words[80]; + u32 word_count; + u32 word_addr; + u32 word0 = 0; + u32 total_read = 0; + + word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE); + word_count &= 0x7F; + word_addr = 191; + + while (word_count) + { + total_read += word_count; + if (total_read >= ARRAYSIZE(words)) + { + break; + } + + for (u32 i = 0; i < word_count; i++) + words[i] = fuse_read(word_addr--); + + word0 = words[0]; + if (_patch_hash_multi(words, word_count) >= 2) + { + return 1; + } + u32 ipatch_count = (words[0] >> 16) & 0xF; + if (ipatch_count) + { + for (u32 i = 0; i < ipatch_count; i++) + { + u32 word = words[i + 1]; + u32 addr = (word >> 16) * 2; + u32 data = word & 0xFFFF; + + ipatch(addr, data); + } + } + words[0] = word0; + if ((word0 >> 25) == 0) + break; + if (_patch_hash_one(&word0) >= 2) + { + return 3; + } + word_count = word0 >> 25; + } + + return 0; +} + +int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len) +{ + u32 words[80]; + u32 word_count; + u32 word_addr; + u32 word0 = 0; + u32 total_read = 0; + int evp_thunk_written = 0; + void *evp_thunk_dst_addr = 0; + + memset(iram_evp_thunks, 0, *iram_evp_thunks_len); + + word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE); + word_count &= 0x7F; + word_addr = 191; + + while (word_count) + { + total_read += word_count; + if (total_read >= ARRAYSIZE(words)) + { + break; + } + + for (u32 i = 0; i < word_count; i++) + words[i] = fuse_read(word_addr--); + + word0 = words[0]; + if (_patch_hash_multi(words, word_count) >= 2) + { + return 1; + } + u32 ipatch_count = (words[0] >> 16) & 0xF; + u32 insn_count = word_count - ipatch_count - 1; + if (insn_count) + { + if (!evp_thunk_written) + { + evp_thunk_dst_addr = (void *)iram_evp_thunks; + + memcpy(evp_thunk_dst_addr, (void *)evp_thunk_template, evp_thunk_template_len); + evp_thunk_dst_addr += evp_thunk_template_len; + evp_thunk_written = 1; + *iram_evp_thunks_len = evp_thunk_template_len; + + //write32(TEGRA_EXCEPTION_VECTORS_BASE + 0x208, iram_evp_thunks); + } + + u32 thunk_patch_len = insn_count * sizeof(u32); + memcpy(evp_thunk_dst_addr, &words[ipatch_count + 1], thunk_patch_len); + evp_thunk_dst_addr += thunk_patch_len; + *iram_evp_thunks_len += thunk_patch_len; + } + words[0] = word0; + if ((word0 >> 25) == 0) + break; + if (_patch_hash_one(&word0) >= 2) + { + return 3; + } + word_count = word0 >> 25; + } + + return 0; +} + +bool fuse_check_patched_rcm() +{ + // Check if XUSB in use. + if (FUSE(FUSE_RESERVED_SW) & (1<<7)) + return true; + + // Check if RCM is ipatched. + u32 word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE) & 0x7F; + u32 word_addr = 191; + + while (word_count) + { + u32 word0 = fuse_read(word_addr); + u32 ipatch_count = (word0 >> 16) & 0xF; + + for (u32 i = 0; i < ipatch_count; i++) + { + u32 word = fuse_read(word_addr - (i + 1)); + u32 addr = (word >> 16) * 2; + if (addr == 0x769A) + return true; + } + + word_addr -= word_count; + word_count = word0 >> 25; + } + + return false; +} diff --git a/source/soc/fuse.h b/source/soc/fuse.h index 0748936..9240b04 100644 --- a/source/soc/fuse.h +++ b/source/soc/fuse.h @@ -54,6 +54,7 @@ #define FUSE_PRIVATE_KEY3 0x1B0 #define FUSE_PRIVATE_KEY4 0x1B4 #define FUSE_RESERVED_SW 0x1C0 +#define FUSE_SKU_DIRECT_CONFIG 0x1F4 #define FUSE_OPT_VENDOR_CODE 0x200 #define FUSE_OPT_FAB_CODE 0x204 #define FUSE_OPT_LOT_CODE_0 0x208 @@ -74,5 +75,10 @@ void fuse_disable_program(); u32 fuse_read_odm(u32 idx); +void fuse_wait_idle(); +int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value)); +int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len); +void fuse_read_array(u32 *words); +bool fuse_check_patched_rcm(); #endif diff --git a/source/soc/hw_init.c b/source/soc/hw_init.c index e343fd0..9f0e900 100644 --- a/source/soc/hw_init.c +++ b/source/soc/hw_init.c @@ -219,7 +219,7 @@ void _config_regulators() { i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CNFGBBC, MAX77620_CNFGBBC_RESISTOR_1K); i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, - (1 << 6) | (1 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off. + (1 << 6) | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off. i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG0, (7 << MAX77620_FPS_TIME_PERIOD_SHIFT)); @@ -257,7 +257,7 @@ void _config_regulators() MAX77621_T_JUNCTION_120 | MAX77621_FT_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS | MAX77621_CKKADV_TRIP_150mV_PER_US | MAX77621_INDUCTOR_NOMINAL); - // Disable low battery shutdown monitor. + // Enable low battery shutdown monitor for < 2800mV. max77620_low_battery_monitor_config(); } @@ -274,6 +274,7 @@ void config_hw() // Enable fuse clock. clock_enable_fuse(true); + // Disable fuse programming. fuse_disable_program(); diff --git a/source/soc/kfuse.c b/source/soc/kfuse.c index 52f188f..f2fde5a 100644 --- a/source/soc/kfuse.c +++ b/source/soc/kfuse.c @@ -17,7 +17,21 @@ #include "../soc/kfuse.h" #include "../soc/clock.h" #include "../soc/t210.h" -#include "../utils/util.h" + +#pragma GCC push_options +#pragma GCC optimize ("Os") + +int kfuse_wait_ready() +{ + // Wait for KFUSE to finish init and verification of data. + while (!(KFUSE(KFUSE_STATE) & KFUSE_STATE_DONE)) + ; + + if (!(KFUSE(KFUSE_STATE) & KFUSE_STATE_CRCPASS)) + return 0; + + return 1; +} int kfuse_read(u32 *buf) { @@ -25,10 +39,7 @@ int kfuse_read(u32 *buf) clock_enable_kfuse(); - while (!(KFUSE(KFUSE_STATE) & KFUSE_STATE_DONE)) - ; - - if (!(KFUSE(KFUSE_STATE) & KFUSE_STATE_CRCPASS)) + if (!kfuse_wait_ready()) goto out; KFUSE(KFUSE_KEYADDR) = KFUSE_KEYADDR_AUTOINC; @@ -42,16 +53,4 @@ out:; return res; } -int kfuse_wait_ready() -{ - // Wait for KFUSE to finish init and verification of data. - while (!(KFUSE(KFUSE_STATE) & KFUSE_STATE_DONE)) - { - usleep(500); - } - - if (!(KFUSE(KFUSE_STATE) & KFUSE_STATE_CRCPASS)) - return 0; - - return 1; -} +#pragma GCC pop_options diff --git a/source/soc/kfuse.h b/source/soc/kfuse.h index 3824eb8..a535803 100644 --- a/source/soc/kfuse.h +++ b/source/soc/kfuse.h @@ -36,7 +36,7 @@ #define KFUSE_NUM_WORDS 144 -int kfuse_read(u32 *buf); int kfuse_wait_ready(); +int kfuse_read(u32 *buf); #endif diff --git a/source/soc/smmu.c b/source/soc/smmu.c index 5aceaa4..fb096d4 100644 --- a/source/soc/smmu.c +++ b/source/soc/smmu.c @@ -106,7 +106,7 @@ bool smmu_is_used() void smmu_exit() { - *(uint32_t *)(smmu_payload + 0x14) = _NOP(); + *(u32 *)(smmu_payload + 0x14) = _NOP(); } u32 *smmu_init_domain4(u32 dev_base, u32 asid) diff --git a/source/soc/t210.h b/source/soc/t210.h index ea83dbc..85e42f4 100644 --- a/source/soc/t210.h +++ b/source/soc/t210.h @@ -108,6 +108,14 @@ /*! EVP registers. */ #define EVP_CPU_RESET_VECTOR 0x100 +#define EVP_COP_RESET_VECTOR 0x200 +#define EVP_COP_UNDEF_VECTOR 0x204 +#define EVP_COP_SWI_VECTOR 0x208 +#define EVP_COP_PREFETCH_ABORT_VECTOR 0x20C +#define EVP_COP_DATA_ABORT_VECTOR 0x210 +#define EVP_COP_RSVD_VECTOR 0x214 +#define EVP_COP_IRQ_VECTOR 0x218 +#define EVP_COP_FIQ_VECTOR 0x21C /*! Misc registers. */ #define APB_MISC_PP_STRAPPING_OPT_A 0x08 @@ -208,7 +216,7 @@ #define HALT_COP_JTAG (1 << 28) #define HALT_COP_WAIT_EVENT (1 << 30) #define HALT_COP_WAIT_IRQ (1 << 31) -#define HALT_COP_MAX_CNT 0xFF +#define HALT_COP_MAX_CNT 0xFF #define FLOW_CTLR_HALT_CPU0_EVENTS 0x0 #define FLOW_CTLR_HALT_CPU1_EVENTS 0x14 #define FLOW_CTLR_HALT_CPU2_EVENTS 0x1C diff --git a/source/storage/nx_emmc.c b/source/storage/nx_emmc.c index 8f03848..c35177e 100644 --- a/source/storage/nx_emmc.c +++ b/source/storage/nx_emmc.c @@ -36,9 +36,9 @@ void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage) part->lba_end = ent->lba_end; part->attrs = ent->attrs; - //HACK - for (u32 j = 0; j < 36; j++) - part->name[j] = ent->name[j]; + // ASCII conversion. Copy only the LSByte of the UTF-16LE name. + for (u32 i = 0; i < 36; i++) + part->name[i] = ent->name[i]; part->name[36] = 0; list_append(gpt, &part->link); diff --git a/source/storage/sd.h b/source/storage/sd.h index c3bf82b..fafd322 100644 --- a/source/storage/sd.h +++ b/source/storage/sd.h @@ -1,8 +1,8 @@ /* * include/linux/mmc/sd.h * - * Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved. - * Copyright (C) 2018 CTCaer + * Copyright (c) 2005-2007 Pierre Ossman, All Rights Reserved. + * Copyright (c) 2018 CTCaer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,7 +40,9 @@ #define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */ #define SD_OCR_XPC (1 << 28) /* SDXC power control */ #define SD_OCR_CCS (1 << 30) /* Card Capacity Status */ +#define SD_OCR_VDD_27_34 (0x7F << 15) /* VDD voltage 2.7 ~ 3.4 */ #define SD_OCR_VDD_32_33 (1 << 20) /* VDD voltage 3.2 ~ 3.3 */ +#define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */ /* * SD_SWITCH argument format: diff --git a/source/storage/sdmmc.c b/source/storage/sdmmc.c index 814556d..d75e609 100644 --- a/source/storage/sdmmc.c +++ b/source/storage/sdmmc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (C) 2018-2019 CTCaer + * Copyright (c) 2018-2019 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -19,6 +19,7 @@ #include "sdmmc.h" #include "mmc.h" #include "sd.h" +#include "../../common/memory_map.h" #include "../gfx/gfx.h" #include "../mem/heap.h" #include "../utils/util.h" @@ -220,10 +221,10 @@ static int _mmc_storage_get_op_cond_inner(sdmmc_storage_t *storage, u32 *pout, u switch (power) { case SDMMC_POWER_1_8: - arg = 0x40000080; //Sector access, voltage. + arg = SD_OCR_CCS | SD_OCR_VDD_18; break; case SDMMC_POWER_3_3: - arg = 0x403F8000; //Sector access, voltage. + arg = SD_OCR_CCS | SD_OCR_VDD_27_34; break; default: return 0; @@ -248,7 +249,7 @@ static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power) if (cond & MMC_CARD_BUSY) { - if (cond & 0x40000000) + if (cond & SD_OCR_CCS) storage->has_sector_access = 1; return 1; @@ -569,7 +570,7 @@ DPRINTF("[MMC] BKOPS disabled\n"); if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type)) return 0; -DPRINTF("[MMC] succesfully switched to highspeed mode\n"); +DPRINTF("[MMC] succesfully switched to HS mode\n"); sdmmc_sd_clock_ctrl(storage->sdmmc, 1); @@ -819,17 +820,17 @@ void _sd_storage_set_current_limit(sdmmc_storage_t *storage, u8 *buf) switch (pwr) { case SD_SET_CURRENT_LIMIT_800: -DPRINTF("[SD] Power limit raised to 800mA\n"); +DPRINTF("[SD] power limit raised to 800mA\n"); break; case SD_SET_CURRENT_LIMIT_600: -DPRINTF("[SD] Power limit raised to 600mA\n"); +DPRINTF("[SD] power limit raised to 600mA\n"); break; case SD_SET_CURRENT_LIMIT_400: -DPRINTF("[SD] Power limit raised to 800mA\n"); +DPRINTF("[SD] power limit raised to 800mA\n"); break; default: case SD_SET_CURRENT_LIMIT_200: -DPRINTF("[SD] Power limit defaulted to 200mA\n"); +DPRINTF("[SD] power limit defaulted to 200mA\n"); break; } } @@ -857,7 +858,7 @@ DPRINTF("[SD] SD supports selected (U)HS mode\n"); return 1; } -int _sd_storage_enable_highspeed_low_volt(sdmmc_storage_t *storage, u32 type, u8 *buf) +int _sd_storage_enable_uhs_low_volt(sdmmc_storage_t *storage, u32 type, u8 *buf) { // Try to raise the current limit to let the card perform better. _sd_storage_set_current_limit(storage, buf); @@ -878,7 +879,7 @@ int _sd_storage_enable_highspeed_low_volt(sdmmc_storage_t *storage, u32 type, u8 { type = 11; hs_type = UHS_SDR104_BUS_SPEED; -DPRINTF("[SD] Bus speed set to SDR104\n"); +DPRINTF("[SD] bus speed set to SDR104\n"); storage->csd.busspeed = 104; break; } @@ -887,7 +888,7 @@ DPRINTF("[SD] Bus speed set to SDR104\n"); { type = 10; hs_type = UHS_SDR50_BUS_SPEED; -DPRINTF("[SD] Bus speed set to SDR50\n"); +DPRINTF("[SD] bus speed set to SDR50\n"); storage->csd.busspeed = 50; break; } @@ -896,7 +897,7 @@ DPRINTF("[SD] Bus speed set to SDR50\n"); return 0; type = 8; hs_type = UHS_SDR12_BUS_SPEED; -DPRINTF("[SD] Bus speed set to SDR12\n"); +DPRINTF("[SD] bus speed set to SDR12\n"); storage->csd.busspeed = 12; break; default: @@ -916,7 +917,7 @@ DPRINTF("[SD] config tuning\n"); return _sdmmc_storage_check_status(storage); } -int _sd_storage_enable_highspeed_high_volt(sdmmc_storage_t *storage, u8 *buf) +int _sd_storage_enable_hs_high_volt(sdmmc_storage_t *storage, u8 *buf) { if (!_sd_storage_switch_get(storage, buf)) return 0; @@ -1064,8 +1065,9 @@ void sdmmc_storage_init_wait_sd() int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32 bus_width, u32 type) { int is_version_1 = 0; + u8 *buf = (u8 *)SDMMC_UPPER_BUFFER; - // Some cards (Sandisk U1), do not like a fast power cycle. Wait min 100ms. + // Some cards (SanDisk U1), do not like a fast power cycle. Wait min 100ms. sdmmc_storage_init_wait_sd(); memset(storage, 0, sizeof(sdmmc_storage_t)); @@ -1138,12 +1140,8 @@ DPRINTF("[SD] set blocklen to 512\n"); return 0; DPRINTF("[SD] cleared card detect\n"); - u8 *buf = (u8 *)malloc(512); if (!_sd_storage_get_scr(storage, buf)) - { - free(buf); return 0; - } //gfx_hexdump(0, storage->raw_scr, 8); DPRINTF("[SD] got scr\n"); @@ -1152,10 +1150,8 @@ DPRINTF("[SD] got scr\n"); if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & 4) && (storage->scr.sda_vsn & 0xF)) { if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_BUS_WIDTH, SD_BUS_WIDTH_4, 0, R1_STATE_TRAN)) - { - free(buf); return 0; - } + sdmmc_set_bus_width(storage->sdmmc, SDMMC_BUS_WIDTH_4); DPRINTF("[SD] switched to wide bus width\n"); } @@ -1166,20 +1162,15 @@ DPRINTF("[SD] SD does not support wide bus width\n"); if (storage->is_low_voltage) { - if (!_sd_storage_enable_highspeed_low_volt(storage, type, buf)) - { - free(buf); + if (!_sd_storage_enable_uhs_low_volt(storage, type, buf)) return 0; - } DPRINTF("[SD] enabled UHS\n"); } else if (type != 6 && (storage->scr.sda_vsn & 0xF) != 0) { - if (!_sd_storage_enable_highspeed_high_volt(storage, buf)) - { - free(buf); + if (!_sd_storage_enable_hs_high_volt(storage, buf)) return 0; - } + DPRINTF("[SD] enabled HS\n"); storage->csd.busspeed = 25; } @@ -1192,7 +1183,6 @@ DPRINTF("[SD] enabled HS\n"); DPRINTF("[SD] got sd status\n"); } - free(buf); return 1; } diff --git a/source/storage/sdmmc.h b/source/storage/sdmmc.h index fdc2bbb..c8b8f96 100644 --- a/source/storage/sdmmc.h +++ b/source/storage/sdmmc.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (C) 2018 CTCaer + * Copyright (c) 2018 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/source/storage/sdmmc_driver.c b/source/storage/sdmmc_driver.c index 0c0c2ff..57d20f9 100644 --- a/source/storage/sdmmc_driver.c +++ b/source/storage/sdmmc_driver.c @@ -252,7 +252,7 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type) u32 tmp; u16 divisor; - clock_sdmmc_get_params(&tmp, &divisor, type); + clock_sdmmc_get_card_clock_div(&tmp, &divisor, type); clock_sdmmc_config_clock_source(&tmp, sdmmc->id, tmp); sdmmc->divisor = (tmp + divisor - 1) / divisor; @@ -722,7 +722,7 @@ static int _sdmmc_check_mask_interrupt(sdmmc_t *sdmmc, u16 *pout, u16 mask) sdmmc->regs->norintsts = norintsts & mask; return SDMMC_MASKINT_MASKED; } - + return SDMMC_MASKINT_NOERROR; } @@ -767,7 +767,7 @@ static int _sdmmc_stop_transmission_inner(sdmmc_t *sdmmc, u32 *rsp) if (!res) return 0; - + _sdmmc_cache_rsp(sdmmc, rsp, 4, SDMMC_RSP_TYPE_1); return _sdmmc_wait_prnsts_type1(sdmmc); @@ -830,7 +830,7 @@ static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req) trnmode |= TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_READ; if (req->is_auto_cmd12) trnmode = (trnmode & 0xFFF3) | TEGRA_MMC_TRNMOD_AUTO_CMD12; - bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY); + bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); sdmmc->regs->trnmod = trnmode; return 1; @@ -855,7 +855,7 @@ static int _sdmmc_update_dma(sdmmc_t *sdmmc) break; if (intr & TEGRA_MMC_NORINTSTS_XFER_COMPLETE) { - bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY); + bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); return 1; // Transfer complete. } if (intr & TEGRA_MMC_NORINTSTS_DMA_INTERRUPT) @@ -901,7 +901,7 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_ _sdmmc_parse_cmdbuf(sdmmc, cmd, is_data_present); int res = _sdmmc_wait_request(sdmmc); - DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", res, + DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", res, sdmmc->regs->rspreg0, sdmmc->regs->rspreg1, sdmmc->regs->rspreg2, sdmmc->regs->rspreg3); if (res) { @@ -943,7 +943,7 @@ static int _sdmmc_config_sdmmc1() gpio_output_enable(GPIO_PORT_Z, GPIO_PIN_1, GPIO_OUTPUT_DISABLE); usleep(100); - // Check if SD card is inserted. + // Check if SD card is inserted. if(!!gpio_read(GPIO_PORT_Z, GPIO_PIN_1)) return 0; @@ -1015,7 +1015,7 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int n u32 clock; u16 divisor; - clock_sdmmc_get_params(&clock, &divisor, type); + clock_sdmmc_get_card_clock_div(&clock, &divisor, type); clock_sdmmc_enable(id, clock); sdmmc->clock_stopped = 0; @@ -1055,7 +1055,7 @@ void sdmmc_end(sdmmc_t *sdmmc) if (!sdmmc->clock_stopped) { _sdmmc_sd_clock_disable(sdmmc); - // Disable SDMMC power. + // Disable SDMMC power. _sdmmc_set_voltage(sdmmc, SDMMC_POWER_OFF); // Disable SD card power. @@ -1134,7 +1134,7 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc) _sdmmc_set_voltage(sdmmc, SDMMC_POWER_1_8); _sdmmc_get_clkcon(sdmmc); msleep(5); - + if (sdmmc->regs->hostctl2 & SDHCI_CTRL_VDD_180) { sdmmc->regs->clkcon |= TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE; diff --git a/source/utils/btn.c b/source/utils/btn.c index f0a8ffc..678b19f 100644 --- a/source/utils/btn.c +++ b/source/utils/btn.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (C) 2018 CTCaer + * Copyright (c) 2018 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -61,16 +61,25 @@ u8 btn_wait() u8 btn_wait_timeout(u32 time_ms, u8 mask) { + u8 single_button = mask & BTN_SINGLE; + mask &= ~BTN_SINGLE; + u32 timeout = get_tmr_ms() + time_ms; - u8 res = btn_read() & mask; + u8 res = btn_read(); while (get_tmr_ms() < timeout) { - if (res == mask) - break; + if ((res & mask) == mask) + { + if (single_button && (res & ~mask)) // Undesired button detected. + res = btn_read(); + else + return (res & mask); + } else - res = btn_read() & mask; + res = btn_read(); }; - return res; + // Timed out. + return 0; } diff --git a/source/utils/btn.h b/source/utils/btn.h index ede13ac..d6cad0c 100644 --- a/source/utils/btn.h +++ b/source/utils/btn.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (C) 2018 CTCaer + * Copyright (c) 2018 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -23,6 +23,7 @@ #define BTN_POWER (1 << 0) #define BTN_VOL_DOWN (1 << 1) #define BTN_VOL_UP (1 << 2) +#define BTN_SINGLE (1 << 7) u8 btn_read(); u8 btn_wait(); diff --git a/source/utils/dirlist.c b/source/utils/dirlist.c index b4d0169..2bb8eaf 100644 --- a/source/utils/dirlist.c +++ b/source/utils/dirlist.c @@ -42,7 +42,7 @@ char *dirlist(const char *directory, const char *pattern, bool includeHiddenFile break; if (!(fno.fattrib & AM_DIR) && (fno.fname[0] != '.') && (includeHiddenFiles || !(fno.fattrib & AM_HID))) { - memcpy(dir_entries + (k * 256), fno.fname, strlen(fno.fname) + 1); + strcpy(dir_entries + (k * 256), fno.fname); k++; if (k > (max_entries - 1)) break; @@ -56,7 +56,7 @@ char *dirlist(const char *directory, const char *pattern, bool includeHiddenFile { if (!(fno.fattrib & AM_DIR) && (fno.fname[0] != '.') && (includeHiddenFiles || !(fno.fattrib & AM_HID))) { - memcpy(dir_entries + (k * 256), fno.fname, strlen(fno.fname) + 1); + strcpy(dir_entries + (k * 256), fno.fname); k++; if (k > (max_entries - 1)) break; @@ -81,9 +81,9 @@ char *dirlist(const char *directory, const char *pattern, bool includeHiddenFile { if (strcmp(&dir_entries[i * 256], &dir_entries[j * 256]) > 0) { - memcpy(temp, &dir_entries[i * 256], strlen(&dir_entries[i * 256]) + 1); - memcpy(&dir_entries[i * 256], &dir_entries[j * 256], strlen(&dir_entries[j * 256]) + 1); - memcpy(&dir_entries[j * 256], temp, strlen(temp) + 1); + strcpy(temp, &dir_entries[i * 256]); + strcpy(&dir_entries[i * 256], &dir_entries[j * 256]); + strcpy(&dir_entries[j * 256], temp); } } } diff --git a/source/utils/types.h b/source/utils/types.h index ab6f35b..544e059 100644 --- a/source/utils/types.h +++ b/source/utils/types.h @@ -20,6 +20,7 @@ #define NULL ((void *)0) #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) +#define ALIGN_DOWN(x, a) (((x) - ((a) - 1)) & ~((a) - 1)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b)) diff --git a/source/utils/util.c b/source/utils/util.c index a217520..cae1981 100644 --- a/source/utils/util.c +++ b/source/utils/util.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert -* Copyright (C) 2018 CTCaer +* Copyright (c) 2018 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -17,6 +17,7 @@ #include "util.h" #include "../gfx/di.h" +#include "../mem/minerva.h" #include "../power/max77620.h" #include "../rtc/max77620-rtc.h" #include "../soc/bpmp.h" @@ -26,6 +27,8 @@ #define USE_RTC_TIMER +extern volatile nyx_storage_t *nyx_str; + extern void sd_unmount(); u32 get_tmr_s() @@ -100,6 +103,8 @@ void reboot_normal() sd_unmount(); display_end(); + nyx_str->mtc_cfg.init_done = 0; + panic(0x21); // Bypass fuse programming in package1. } @@ -110,6 +115,8 @@ void reboot_rcm() sd_unmount(); display_end(); + nyx_str->mtc_cfg.init_done = 0; + PMC(APBDEV_PMC_SCRATCH0) = 2; // Reboot into rcm. PMC(APBDEV_PMC_CNTRL) |= PMC_CNTRL_MAIN_RST; diff --git a/source/utils/util.h b/source/utils/util.h index 2eb0899..55f5f18 100644 --- a/source/utils/util.h +++ b/source/utils/util.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (C) 2018 CTCaer + * Copyright (c) 2018 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -21,6 +21,9 @@ #include "types.h" #include "../mem/minerva.h" +#define NYX_CFG_DUMP (1 << 7) +#define NYX_CFG_MINERVA (1 << 8) + #define byte_swap_32(num) (((num >> 24) & 0xff) | ((num << 8) & 0xff0000) | \ ((num >> 8 )& 0xff00) | ((num << 24) & 0xff000000))