From 7dd3178d481dfc2b4b01169eccb585a5adc42d50 Mon Sep 17 00:00:00 2001 From: CTCaer Date: Sat, 13 Jun 2020 18:16:29 +0300 Subject: [PATCH] Equalize hekate main and Nyx common functions --- bootloader/config/config.c | 2 +- bootloader/config/ini.c | 2 +- bootloader/frontend/fe_emmc_tools.c | 4 +- bootloader/gfx/di.c | 108 +++++++++- bootloader/gfx/di.h | 11 +- bootloader/gfx/di.inl | 110 +++++++++- bootloader/gfx/gfx.c | 20 +- bootloader/libs/fatfs/diskio.h | 8 + bootloader/libs/fatfs/ff.c | 208 ++++++++++++++++++ bootloader/libs/fatfs/ff.h | 8 + bootloader/libs/fatfs/ffconf.h | 9 +- bootloader/main.c | 20 +- bootloader/mem/minerva.c | 37 ++++ bootloader/mem/sdram.c | 13 +- bootloader/mem/sdram_config.inl | 31 ++- bootloader/mem/sdram_param_t210.h | 1 - bootloader/power/bq24193.c | 5 - bootloader/power/max17050.c | 5 - bootloader/sec/se.c | 139 +++++++++--- bootloader/sec/se.h | 4 +- bootloader/soc/clock.c | 80 ++++++- bootloader/soc/hw_init.c | 27 ++- bootloader/soc/kfuse.c | 7 +- bootloader/soc/uart.c | 2 +- bootloader/storage/emummc.c | 1 - bootloader/storage/nx_emmc.c | 4 + bootloader/storage/nx_emmc.h | 7 +- bootloader/storage/sd.h | 6 +- bootloader/storage/sdmmc_driver.c | 51 ++++- bootloader/utils/btn.c | 16 ++ bootloader/utils/btn.h | 1 + bootloader/utils/dirlist.c | 18 +- bootloader/utils/dirlist.h | 2 +- nyx/nyx_gui/frontend/fe_emmc_tools.c | 2 +- nyx/nyx_gui/frontend/gui.c | 2 +- nyx/nyx_gui/frontend/gui_info.c | 2 +- nyx/nyx_gui/gfx/di.c | 22 +- nyx/nyx_gui/gfx/di.h | 3 +- nyx/nyx_gui/gfx/di.inl | 44 +++- nyx/nyx_gui/libs/fatfs/ff.c | 14 +- nyx/nyx_gui/libs/fatfs/ff.h | 6 +- nyx/nyx_gui/libs/fatfs/ffconf.h | 12 +- nyx/nyx_gui/mem/minerva.c | 18 ++ nyx/nyx_gui/mem/sdram.c | 9 +- nyx/nyx_gui/mem/sdram_config.inl | 31 ++- nyx/nyx_gui/mem/sdram_param_t210.h | 1 - nyx/nyx_gui/sec/se.c | 5 + nyx/nyx_gui/sec/se.h | 1 + nyx/nyx_gui/soc/clock.c | 4 +- nyx/nyx_gui/soc/hw_init.c | 312 ++++++++++++++++++++++++++- nyx/nyx_gui/soc/hw_init.h | 2 + nyx/nyx_gui/soc/kfuse.c | 2 +- nyx/nyx_gui/soc/uart.c | 2 +- nyx/nyx_gui/storage/nx_emmc.h | 2 +- nyx/nyx_gui/storage/sd.h | 6 +- nyx/nyx_gui/storage/sdmmc_driver.c | 34 ++- nyx/nyx_gui/utils/btn.c | 28 +++ nyx/nyx_gui/utils/btn.h | 2 + 58 files changed, 1342 insertions(+), 191 deletions(-) diff --git a/bootloader/config/config.c b/bootloader/config/config.c index adcfee4..aaaa154 100644 --- a/bootloader/config/config.c +++ b/bootloader/config/config.c @@ -47,7 +47,7 @@ void set_default_configuration() h_cfg.errors = 0; h_cfg.eks = NULL; h_cfg.sept_run = EMC(EMC_SCRATCH0) & EMC_SEPT_RUN; - h_cfg.rcm_patched = true; + h_cfg.rcm_patched = fuse_check_patched_rcm(); h_cfg.emummc_force_disable = false; sd_power_cycle_time_start = 0; diff --git a/bootloader/config/ini.c b/bootloader/config/ini.c index 4c200dd..b83160c 100644 --- a/bootloader/config/ini.c +++ b/bootloader/config/ini.c @@ -81,7 +81,7 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir) // Get all ini filenames. if (is_dir) { - filelist = dirlist(filename, "*.ini", false); + filelist = dirlist(filename, "*.ini", false, false); if (!filelist) { free(filename); diff --git a/bootloader/frontend/fe_emmc_tools.c b/bootloader/frontend/fe_emmc_tools.c index e3a7468..5da3745 100644 --- a/bootloader/frontend/fe_emmc_tools.c +++ b/bootloader/frontend/fe_emmc_tools.c @@ -95,8 +95,8 @@ static int _dump_emmc_verify(sdmmc_storage_t *storage, u32 lba_curr, char *outFi return 1; } - se_calc_sha256(hashEm, bufEm, num << 9); - se_calc_sha256(hashSd, bufSd, num << 9); + se_calc_sha256_oneshot(hashEm, bufEm, num << 9); + se_calc_sha256_oneshot(hashSd, bufSd, num << 9); res = memcmp(hashEm, hashSd, 0x10); if (res) diff --git a/bootloader/gfx/di.c b/bootloader/gfx/di.c index 3252475..015df23 100644 --- a/bootloader/gfx/di.c +++ b/bootloader/gfx/di.c @@ -145,13 +145,13 @@ void display_init() // Decode Display ID. _display_id = ((_display_id >> 8) & 0xFF00) | (_display_id & 0xFF); - if ((_display_id & 0xFF) == PANEL_JDI_LPM062M) - _display_id = PANEL_JDI_LPM062M; + if ((_display_id & 0xFF) == PANEL_JDI_XXX062M) + _display_id = PANEL_JDI_XXX062M; // Initialize display panel. switch (_display_id) { - case PANEL_JDI_LPM062M: + case PANEL_JDI_XXX062M: exec_cfg((u32 *)DSI_BASE, _display_init_config_jdi, 43); _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000); break; @@ -264,7 +264,7 @@ void display_end() // De-initialize display panel. switch (_display_id) { - case PANEL_JDI_LPM062M: + case PANEL_JDI_XXX062M: exec_cfg((u32 *)DSI_BASE, _display_deinit_config_jdi, 22); break; case PANEL_AUO_A062TAN01: @@ -337,15 +337,111 @@ void display_color_screen(u32 color) display_backlight(true); } -u32 *display_init_framebuffer() +u32 *display_init_framebuffer_pitch() { // Sanitize framebuffer area. 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); + exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_pitch, 32); usleep(35000); return (u32 *)IPL_FB_ADDRESS; } +u32 *display_init_framebuffer_pitch_inv() +{ + // This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 1280x720 (line stride 720). + exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_pitch_inv, 34); + + usleep(35000); + + return (u32 *)NYX_FB_ADDRESS; +} + +u32 *display_init_framebuffer_block() +{ + // This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 1280x720 (line stride 720). + exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_block, 34); + + usleep(35000); + + return (u32 *)NYX_FB_ADDRESS; +} + +u32 *display_init_framebuffer_log() +{ + // This configures the framebuffer @ LOG_FB_ADDRESS with a resolution of 1280x720 (line stride 720). + exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_log, 20); + + return (u32 *)LOG_FB_ADDRESS; +} + +void display_activate_console() +{ + DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_D_SELECT; // Select window C. + DISPLAY_A(_DIREG(DC_WIN_WIN_OPTIONS)) = WIN_ENABLE; // Enable window DD. + DISPLAY_A(_DIREG(DC_WIN_POSITION)) = 0xFF80; + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE; + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ; + + for (u32 i = 0xFF80; i < 0x10000; i++) + { + DISPLAY_A(_DIREG(DC_WIN_POSITION)) = i & 0xFFFF; + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE; + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ; + usleep(1000); + } + + DISPLAY_A(_DIREG(DC_WIN_POSITION)) = 0; + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE; + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ; +} + +void display_deactivate_console() +{ + DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_D_SELECT; // Select window C. + + for (u32 i = 0xFFFF; i > 0xFF7F; i--) + { + DISPLAY_A(_DIREG(DC_WIN_POSITION)) = i & 0xFFFF; + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE; + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ; + usleep(500); + } + + DISPLAY_A(_DIREG(DC_WIN_POSITION)) = 0; + DISPLAY_A(_DIREG(DC_WIN_WIN_OPTIONS)) = 0; // Disable window DD. + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE; + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ; +} + +void display_init_cursor(void *crs_fb, u32 size) +{ + // Setup cursor. + DISPLAY_A(_DIREG(DC_DISP_CURSOR_START_ADDR)) = CURSOR_CLIPPING(CURSOR_CLIP_WIN_A) | size | ((u32)crs_fb >> 10); + DISPLAY_A(_DIREG(DC_DISP_BLEND_CURSOR_CONTROL)) = + CURSOR_BLEND_R8G8B8A8 | CURSOR_BLEND_DST_FACTOR(CURSOR_BLEND_K1) | CURSOR_BLEND_SRC_FACTOR(CURSOR_BLEND_K1) | 0xFF; + + DISPLAY_A(_DIREG(DC_DISP_DISP_WIN_OPTIONS)) |= CURSOR_ENABLE; + + // Arm and activate changes. + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | CURSOR_UPDATE; + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | CURSOR_ACT_REQ; +} + +void display_set_pos_cursor(u32 x, u32 y) +{ + DISPLAY_A(_DIREG(DC_DISP_CURSOR_POSITION)) = x | (y << 16); + + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | CURSOR_UPDATE; + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | CURSOR_ACT_REQ; +} + +void display_deinit_cursor() +{ + DISPLAY_A(_DIREG(DC_DISP_BLEND_CURSOR_CONTROL)) = 0; + DISPLAY_A(_DIREG(DC_DISP_DISP_WIN_OPTIONS)) &= ~CURSOR_ENABLE; + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | CURSOR_UPDATE; + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | CURSOR_ACT_REQ; +} diff --git a/bootloader/gfx/di.h b/bootloader/gfx/di.h index a160eff..2b4e579 100644 --- a/bootloader/gfx/di.h +++ b/bootloader/gfx/di.h @@ -506,7 +506,9 @@ enum { - PANEL_JDI_LPM062M = 0x10, + PANEL_JDI_XXX062M = 0x10, + PANEL_JDI_LAM062M109A = 0x0910, + PANEL_JDI_LPM062M326A = 0x2610, PANEL_INL_P062CCA_AZ1 = 0x0F20, PANEL_AUO_A062TAN01 = 0x0F30, PANEL_INL_P062CCA_AZ2 = 0x1020, @@ -525,7 +527,12 @@ void display_backlight(bool enable); void display_backlight_brightness(u32 brightness, u32 step_delay); /*! Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */ -u32 *display_init_framebuffer(); +u32 *display_init_framebuffer_pitch(); +u32 *display_init_framebuffer_pitch_inv(); +u32 *display_init_framebuffer_block(); +u32 *display_init_framebuffer_log(); +void display_activate_console(); +void display_deactivate_console(); void display_init_cursor(void *crs_fb, u32 size); void display_set_pos_cursor(u32 x, u32 y); void display_deinit_cursor(); diff --git a/bootloader/gfx/di.inl b/bootloader/gfx/di.inl index 9a275eb..ef3b1b0 100644 --- a/bootloader/gfx/di.inl +++ b/bootloader/gfx/di.inl @@ -559,8 +559,8 @@ static const cfg_op_t cfg_display_one_color[8] = { {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY} // Continuous display. }; -//Display A config. -static const cfg_op_t cfg_display_framebuffer[32] = { +//Display A config linear pitch. +static const cfg_op_t cfg_display_framebuffer_pitch[32] = { {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, {DC_WIN_WIN_OPTIONS, 0}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, @@ -568,14 +568,14 @@ static const cfg_op_t cfg_display_framebuffer[32] = { {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, {DC_WIN_WIN_OPTIONS, 0}, {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, - {DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, //NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8 + {DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, // NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8. {DC_WIN_WIN_OPTIONS, 0}, {DC_WIN_WIN_OPTIONS, 0}, {DC_WIN_POSITION, 0}, //(0,0) {DC_WIN_H_INITIAL_DDA, 0}, {DC_WIN_V_INITIAL_DDA, 0}, - {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(2880)}, - {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x + {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)}, + {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x. {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, // 720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. {DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST}, @@ -594,3 +594,103 @@ static const cfg_op_t cfg_display_framebuffer[32] = { {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE}, {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ} }; + +//Display A config linear pitch inverse + Win D support. +static const cfg_op_t cfg_display_framebuffer_pitch_inv[34] = { + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, + {DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, // NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8. + {DC_WIN_WIN_OPTIONS, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_WIN_POSITION, 0}, //(0,0) + {DC_WIN_H_INITIAL_DDA, 0}, + {DC_WIN_V_INITIAL_DDA, 0}, + {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)}, + {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x. + {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, + {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, // 720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. + {DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST}, + {DC_WINBUF_SURFACE_KIND, PITCH}, + {DC_WINBUF_START_ADDR, NYX_FB_ADDRESS}, // Framebuffer address. + {DC_WINBUF_ADDR_H_OFFSET, 0}, // Linear: 0x383FFC, Block: 0x3813FC. + {DC_WINBUF_ADDR_V_OFFSET, 1279}, // Linear: 1279, Block: 0. + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, + {DC_WIN_WIN_OPTIONS, WIN_ENABLE | V_DIRECTION}, // Enable window AD. + {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, // Continuous display. + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ} +}; + +//Display A config block linear. +static const cfg_op_t cfg_display_framebuffer_block[34] = { + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, + {DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, // NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8. + {DC_WIN_WIN_OPTIONS, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_WIN_POSITION, 0}, //(0,0) + {DC_WIN_H_INITIAL_DDA, 0}, + {DC_WIN_V_INITIAL_DDA, 0}, + {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)}, + {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x. + {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, + {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(1280 * 2) | LINE_STRIDE(1280 * 4)}, //720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. + {DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST}, + {DC_WINBUF_SURFACE_KIND, BLOCK_HEIGHT(4) | BLOCK}, + {DC_WINBUF_START_ADDR, NYX_FB_ADDRESS}, // Framebuffer address. + {DC_WINBUF_ADDR_H_OFFSET, 0x3813FC}, // Linear: 0x383FFC, Block: 0x3813FC. + {DC_WINBUF_ADDR_V_OFFSET, 0}, // Linear: 1279, Block: 0. + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, + {DC_WIN_WIN_OPTIONS, WIN_ENABLE | SCAN_COLUMN | H_DIRECTION}, // Enable window AD. | SCAN_COLUMN | H_DIRECTION. + {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, // Continuous display. + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ} +}; + +//Display D config. +static const cfg_op_t cfg_display_framebuffer_log[20] = { + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, + {DC_WIN_POSITION, 0}, //(0,0) + {DC_WIN_H_INITIAL_DDA, 0}, + {DC_WIN_V_INITIAL_DDA, 0}, + {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(656 * 4)}, + {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x. + {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(656)}, + {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(656 * 2) | LINE_STRIDE(656 * 4)}, //656*2x656*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. + {DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST}, + {DC_WINBUF_SURFACE_KIND, PITCH}, + {DC_WINBUF_START_ADDR, LOG_FB_ADDRESS}, // Framebuffer address. + {DC_WINBUF_ADDR_H_OFFSET, 0}, + {DC_WINBUF_ADDR_V_OFFSET, 0}, + {DC_WINBUF_BLEND_LAYER_CONTROL, WIN_BLEND_ENABLE | WIN_K1(200)}, + {DC_WINBUF_BLEND_MATCH_SELECT, WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1 | WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1}, + {DC_WIN_WIN_OPTIONS, 0}, // Enable window DD. + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_D_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_D_ACT_REQ} +}; diff --git a/bootloader/gfx/gfx.c b/bootloader/gfx/gfx.c index 46551c9..5c30ba7 100644 --- a/bootloader/gfx/gfx.c +++ b/bootloader/gfx/gfx.c @@ -121,28 +121,28 @@ static const u8 _gfx_font[] = { 0x00, 0x00, 0x00, 0x4C, 0x32, 0x00, 0x00, 0x00 // Char 126 (~) }; -void gfx_init_ctxt(u32 *fb, u32 width, u32 height, u32 stride) -{ - gfx_ctxt.fb = fb; - gfx_ctxt.width = width; - gfx_ctxt.height = height; - gfx_ctxt.stride = stride; -} - void gfx_clear_grey(u8 color) { memset(gfx_ctxt.fb, color, gfx_ctxt.width * gfx_ctxt.height * 4); } +void gfx_clear_partial_grey(u8 color, u32 pos_x, u32 height) +{ + memset(gfx_ctxt.fb + pos_x * gfx_ctxt.stride, color, height * 4 * gfx_ctxt.stride); +} + void gfx_clear_color(u32 color) { for (u32 i = 0; i < gfx_ctxt.width * gfx_ctxt.height; i++) gfx_ctxt.fb[i] = color; } -void gfx_clear_partial_grey(u8 color, u32 pos_x, u32 height) +void gfx_init_ctxt(u32 *fb, u32 width, u32 height, u32 stride) { - memset(gfx_ctxt.fb + pos_x * gfx_ctxt.stride, color, height * 4 * gfx_ctxt.stride); + gfx_ctxt.fb = fb; + gfx_ctxt.width = width; + gfx_ctxt.height = height; + gfx_ctxt.stride = stride; } void gfx_con_init() diff --git a/bootloader/libs/fatfs/diskio.h b/bootloader/libs/fatfs/diskio.h index e868352..31b855d 100644 --- a/bootloader/libs/fatfs/diskio.h +++ b/bootloader/libs/fatfs/diskio.h @@ -23,6 +23,13 @@ typedef enum { RES_PARERR /* 4: Invalid Parameter */ } DRESULT; +typedef enum { + DRIVE_SD = 0, + DRIVE_RAM = 1, + DRIVE_EMMC = 2, + DRIVE_BIS = 3 +} DDRIVE; + /*---------------------------------------*/ /* Prototypes for disk control functions */ @@ -33,6 +40,7 @@ DSTATUS disk_status (BYTE pdrv); DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count); DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count); DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); +DRESULT disk_set_info (BYTE pdrv, BYTE cmd, void *buff); /* Disk Status Bits (DSTATUS) */ diff --git a/bootloader/libs/fatfs/ff.c b/bootloader/libs/fatfs/ff.c index 732e31b..c6c4d75 100644 --- a/bootloader/libs/fatfs/ff.c +++ b/bootloader/libs/fatfs/ff.c @@ -3906,6 +3906,92 @@ FRESULT f_read ( +#if FF_FASTFS && FF_USE_FASTSEEK +/*-----------------------------------------------------------------------*/ +/* Fast Read Aligned Sized File Without a Cache */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_read_fast ( + FIL* fp, /* Pointer to the file object */ + const void* buff, /* Pointer to the data to be written */ + UINT btr /* Number of bytes to read */ +) +{ + FRESULT res; + FATFS *fs; + UINT csize_bytes; + DWORD clst; + UINT count = 0; + FSIZE_t work_sector = 0; + FSIZE_t sector_base = 0; + BYTE *wbuff = (BYTE*)buff; + + // TODO support sector reading inside a cluster + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) { + EFSPRINTF("FOV"); + LEAVE_FF(fs, res); /* Check validity */ + } + + if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + FSIZE_t remain = fp->obj.objsize - fp->fptr; + if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ + + csize_bytes = fs->csize * SS(fs); + + if (!fp->fptr) { /* On the top of the file? */ + clst = fp->obj.sclust; /* Follow from the origin */ + } else { + if (fp->cltbl) clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + else { EFSPRINTF("CLTBL"); ABORT(fs, FR_CLTBL_NO_INIT); } + } + if (clst < 2) { EFSPRINTF("CCHK"); ABORT(fs, FR_INT_ERR); } + else if (clst == 0xFFFFFFFF) { EFSPRINTF("DSKC"); ABORT(fs, FR_DISK_ERR); } + + fp->clust = clst; /* Set working cluster */ + + sector_base = clst2sect(fs, fp->clust); + count += fs->csize; + btr -= csize_bytes; + fp->fptr += csize_bytes; + + while (btr) { + clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + + if (clst < 2) { EFSPRINTF("CCHK2"); ABORT(fs, FR_INT_ERR); } + else if (clst == 0xFFFFFFFF) { EFSPRINTF("DSKC"); ABORT(fs, FR_DISK_ERR); } + + fp->clust = clst; + + work_sector = clst2sect(fs, fp->clust); + if ((work_sector - sector_base) == count) count += fs->csize; + else { + if (disk_read(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); + wbuff += count * SS(fs); + + sector_base = work_sector; + count = fs->csize; + } + + fp->fptr += MIN(btr, csize_bytes); + btr -= MIN(btr, csize_bytes); + + // TODO: what about if data is smaller than cluster? + // Must read-write back that cluster. + + if (!btr) { /* Final cluster/sectors read. */ + if (disk_read(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); + } + } + + LEAVE_FF(fs, FR_OK); +} +#endif + + + + #if !FF_FS_READONLY /*-----------------------------------------------------------------------*/ /* Write File */ @@ -4045,6 +4131,97 @@ FRESULT f_write ( +#if FF_FASTFS && FF_USE_FASTSEEK +/*-----------------------------------------------------------------------*/ +/* Fast Write Aligned Sized File Without a Cache */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_write_fast ( + FIL* fp, /* Pointer to the file object */ + const void* buff, /* Pointer to the data to be written */ + UINT btw /* Number of bytes to write */ +) +{ + FRESULT res; + FATFS *fs; + UINT csize_bytes; + DWORD clst; + UINT count = 0; + FSIZE_t work_sector = 0; + FSIZE_t sector_base = 0; + const BYTE *wbuff = (const BYTE*)buff; + + // TODO support sector writing inside a cluster + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) { + EFSPRINTF("FOV"); + LEAVE_FF(fs, res); /* Check validity */ + } + + if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + /* Check fptr wrap-around (file size cannot reach 4 GiB at FAT volume) */ + if ((!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) { + btw = (UINT)(0xFFFFFFFF - (DWORD)fp->fptr); + } + + csize_bytes = fs->csize * SS(fs); + + if (!fp->fptr) { /* On the top of the file? */ + clst = fp->obj.sclust; /* Follow from the origin */ + } else { + if (fp->cltbl) clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + else { EFSPRINTF("CLTBL"); ABORT(fs, FR_CLTBL_NO_INIT); } + } + + if (clst < 2) { EFSPRINTF("CCHK"); ABORT(fs, FR_INT_ERR); } + else if (clst == 0xFFFFFFFF) { EFSPRINTF("DERR"); ABORT(fs, FR_DISK_ERR); } + + fp->clust = clst; /* Set working cluster */ + + sector_base = clst2sect(fs, fp->clust); + count += fs->csize; + btw -= csize_bytes; + fp->fptr += csize_bytes; + + while (btw) { + clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + + if (clst < 2) { EFSPRINTF("CCHK2"); ABORT(fs, FR_INT_ERR); } + else if (clst == 0xFFFFFFFF) { EFSPRINTF("DERR"); ABORT(fs, FR_DISK_ERR); } + + fp->clust = clst; + + work_sector = clst2sect(fs, fp->clust); + if ((work_sector - sector_base) == count) count += fs->csize; + else { + if (disk_write(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); + wbuff += count * SS(fs); + + sector_base = work_sector; + count = fs->csize; + } + + fp->fptr += MIN(btw, csize_bytes); + btw -= MIN(btw, csize_bytes); + + // what about if data is smaller than cluster? + // Probably must read-write back that cluster. + if (!btw) { /* Final cluster/sectors write. */ + if (disk_write(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } + } + + fp->flag |= FA_MODIFIED; /* Set file change flag */ + + LEAVE_FF(fs, FR_OK); +} +#endif + + + + /*-----------------------------------------------------------------------*/ /* Synchronize the File */ /*-----------------------------------------------------------------------*/ @@ -4501,6 +4678,37 @@ FRESULT f_lseek ( +#if FF_FASTFS && FF_USE_FASTSEEK +/*-----------------------------------------------------------------------*/ +/* Seek File Read/Write Pointer */ +/*-----------------------------------------------------------------------*/ + +DWORD *f_expand_cltbl ( + FIL* fp, /* Pointer to the file object */ + UINT tblsz, /* Size of table */ + FSIZE_t ofs /* File pointer from top of file */ +) +{ + if (fp->flag & FA_WRITE) f_lseek(fp, ofs); /* Expand file if write is enabled */ + if (!fp->cltbl) { /* Allocate memory for cluster link table */ + fp->cltbl = (DWORD *)ff_memalloc(tblsz); + fp->cltbl[0] = tblsz; + } + if (f_lseek(fp, CREATE_LINKMAP)) { /* Create cluster link table */ + ff_memfree(fp->cltbl); + fp->cltbl = NULL; + EFSPRINTF("CLTBLSZ"); + return NULL; + } + f_lseek(fp, 0); + + return fp->cltbl; +} +#endif + + + + #if FF_FS_MINIMIZE <= 1 /*-----------------------------------------------------------------------*/ /* Create a Directory Object */ diff --git a/bootloader/libs/fatfs/ff.h b/bootloader/libs/fatfs/ff.h index b036443..af1151f 100644 --- a/bootloader/libs/fatfs/ff.h +++ b/bootloader/libs/fatfs/ff.h @@ -246,7 +246,12 @@ typedef enum { FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */ +#if FF_FASTFS + FR_INVALID_PARAMETER, /* (19) Given parameter is invalid */ + FR_CLTBL_NO_INIT /* (20) The cluster table for fast seek/read/write was not created */ +#else FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ +#endif } FRESULT; @@ -258,6 +263,8 @@ FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a f FRESULT f_close (FIL* fp); /* Close an open file object */ FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */ FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */ +FRESULT f_read_fast (FIL* fp, const void* buff, UINT btr); /* Fast read data from the file */ +FRESULT f_write_fast (FIL* fp, const void* buff, UINT btw); /* Fast write data to the file */ FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */ FRESULT f_truncate (FIL* fp); /* Truncate the file */ FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */ @@ -279,6 +286,7 @@ FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get numbe FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */ FRESULT f_setlabel (const TCHAR* label); /* Set volume label */ FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */ +DWORD *f_expand_cltbl (FIL* fp, UINT tblsz, FSIZE_t ofs); /* Expand file and populate cluster table */ FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt); /* Allocate a contiguous block to the file */ FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */ FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */ diff --git a/bootloader/libs/fatfs/ffconf.h b/bootloader/libs/fatfs/ffconf.h index be64ef3..ee536ef 100644 --- a/bootloader/libs/fatfs/ffconf.h +++ b/bootloader/libs/fatfs/ffconf.h @@ -45,6 +45,13 @@ #define FF_USE_FASTSEEK 0 /* This option switches fast seek function. (0:Disable or 1:Enable) */ +#define FF_FASTFS 0 + +#if FF_FASTFS +#undef FF_USE_FASTSEEK +#define FF_USE_FASTSEEK 1 +#endif + #define FF_USE_EXPAND 0 /* This option switches f_expand function. (0:Disable or 1:Enable) */ @@ -239,7 +246,7 @@ #define FF_FS_NORTC 1 #define FF_NORTC_MON 1 #define FF_NORTC_MDAY 1 -#define FF_NORTC_YEAR 2019 +#define FF_NORTC_YEAR 2020 /* The option FF_FS_NORTC switches timestamp function. If the system does not have / any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable / the timestamp function. Every object modified by FatFs will have a fixed timestamp diff --git a/bootloader/main.c b/bootloader/main.c index 573abd5..37c3e8f 100644 --- a/bootloader/main.c +++ b/bootloader/main.c @@ -318,7 +318,7 @@ void launch_tools() memcpy(dir, "bootloader/payloads", 20); - filelist = dirlist(dir, NULL, false); + filelist = dirlist(dir, NULL, false, false); u32 i = 0; @@ -1022,7 +1022,7 @@ skip_list: // Wait before booting. If VOL- is pressed go into bootloader menu. if (!h_cfg.sept_run && !(b_cfg.boot_cfg & BOOT_CFG_FROM_LAUNCH)) { - btn = btn_wait_timeout(h_cfg.bootwait * 1000, BTN_VOL_DOWN | BTN_SINGLE); + btn = btn_wait_timeout_single(h_cfg.bootwait * 1000, BTN_VOL_DOWN | BTN_SINGLE); if (btn & BTN_VOL_DOWN) goto out; @@ -1082,8 +1082,6 @@ static void _patched_rcm_protection() sdmmc_storage_t storage; sdmmc_t sdmmc; - h_cfg.rcm_patched = fuse_check_patched_rcm(); - if (!h_cfg.rcm_patched) return; @@ -1253,12 +1251,12 @@ static void _check_low_battery() } // Check if charging status changed or Power button was pressed. - if (((charge_status != current_charge_status) || (btn_wait_timeout(0, BTN_POWER) & BTN_POWER))) + if ((charge_status != current_charge_status) || (btn_wait_timeout_single(0, BTN_POWER) & BTN_POWER)) { if (!screen_on) { display_init(); - u32 *fb = display_init_framebuffer(); + u32 *fb = display_init_framebuffer_pitch(); gfx_init_ctxt(fb, 720, 1280, 720); gfx_set_rect_rgb(battery_icon, X_BATTERY_EMPTY, Y_BATTERY_EMPTY_BATT, 16, battery_icon_y_pos); @@ -1350,9 +1348,9 @@ ment_t ment_options[] = { MDEF_BACK(), MDEF_CHGLINE(), MDEF_HANDLER("Auto boot", config_autoboot), - //MDEF_HANDLER("Boot delay", config_bootdelay), - //MDEF_HANDLER("Auto NoGC", config_nogc), - //MDEF_HANDLER("Auto HOS power off", config_auto_hos_poweroff), + MDEF_HANDLER("Boot delay", config_bootdelay), + MDEF_HANDLER("Auto NoGC", config_nogc), + MDEF_HANDLER("Auto HOS power off", config_auto_hos_poweroff), MDEF_HANDLER("Backlight", config_backlight), MDEF_END() }; @@ -1431,7 +1429,7 @@ menu_t menu_tools = { ment_tools, "Tools", 0, 0 }; ment_t ment_top[] = { MDEF_HANDLER("Launch", launch_firmware), - MDEF_MENU("Options", &menu_options), + //MDEF_MENU("Options", &menu_options), MDEF_CAPTION("---------------", 0xFF444444), MDEF_MENU("Tools", &menu_tools), MDEF_MENU("Console info", &menu_cinfo), @@ -1482,7 +1480,7 @@ void ipl_main() display_init(); - u32 *fb = display_init_framebuffer(); + u32 *fb = display_init_framebuffer_pitch(); gfx_init_ctxt(fb, 720, 1280, 720); #ifdef MENU_LOGO_ENABLE diff --git a/bootloader/mem/minerva.c b/bootloader/mem/minerva.c index 2607c4b..c399070 100644 --- a/bootloader/mem/minerva.c +++ b/bootloader/mem/minerva.c @@ -27,6 +27,7 @@ #include "../soc/t210.h" extern volatile nyx_storage_t *nyx_str; + void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *); u32 minerva_init() @@ -35,6 +36,41 @@ u32 minerva_init() minerva_cfg = NULL; mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg; + +#ifdef NYX + // Set table to nyx storage. + mtc_cfg->mtc_table = (emc_table_t *)nyx_str->mtc_table; + + // Check if Minerva is already initialized. + if (mtc_cfg->init_done == MTC_INIT_MAGIC) + { + mtc_cfg->train_mode = OP_PERIODIC_TRAIN; // Retrain if needed. + u32 ep_addr = ianos_loader(false, "bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)mtc_cfg); + minerva_cfg = (void *)ep_addr; + + return 0; + } + else + { + mtc_config_t mtc_tmp; + + mtc_tmp.mtc_table = mtc_cfg->mtc_table; + mtc_tmp.sdram_id = (fuse_read_odm(4) >> 3) & 0x1F; + mtc_tmp.init_done = MTC_NEW_MAGIC; + + u32 ep_addr = ianos_loader(false, "bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)&mtc_tmp); + + // Ensure that Minerva is new. + if (mtc_tmp.init_done == MTC_INIT_MAGIC) + minerva_cfg = (void *)ep_addr; + else + mtc_cfg->init_done = 0; + + // Copy Minerva context to Nyx storage. + if (minerva_cfg) + memcpy(mtc_cfg, (void *)&mtc_tmp, sizeof(mtc_config_t)); + } +#else memset(mtc_cfg, 0, sizeof(mtc_config_t)); // Set table to nyx storage. @@ -50,6 +86,7 @@ u32 minerva_init() minerva_cfg = (void *)ep_addr; else mtc_cfg->init_done = 0; +#endif if (!minerva_cfg) return 1; diff --git a/bootloader/mem/sdram.c b/bootloader/mem/sdram.c index 36f54c1..d1e5db9 100644 --- a/bootloader/mem/sdram.c +++ b/bootloader/mem/sdram.c @@ -202,7 +202,7 @@ break_nosleep: 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. + // Patch 3 using BCT spare variables. if (params->emc_bct_spare6) *(vu32 *)params->emc_bct_spare6 = params->emc_bct_spare7; @@ -345,7 +345,7 @@ break_nosleep: // 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. + // Patch 4 using BCT spare variables. if (params->emc_bct_spare4) *(vu32 *)params->emc_bct_spare4 = params->emc_bct_spare5; @@ -723,11 +723,14 @@ sdram_params_t *sdram_get_params() case DRAM_4GB_SAMSUNG_K4F6E304HB_MGCH: case DRAM_4GB_MICRON_MT53B512M32D2NP_062_WT: break; + case DRAM_4GB_HYNIX_H9HCNNNBPUMLHR_NLN: - case DRAM_4GB_COPPER_UNK_3: case DRAM_6GB_SAMSUNG_K4FHE3D4HM_MFCH: - case DRAM_4GB_COPPER_UNK_5: - case DRAM_4GB_COPPER_UNK_6: +#ifdef CONFIG_SDRAM_COPPER_SUPPORT + case DRAM_4GB_COPPER_SAMSUNG: + case DRAM_4GB_COPPER_HYNIX: + case DRAM_4GB_COPPER_MICRON: +#endif _sdram_patch_model_params(dramid, (u32 *)buf); break; } diff --git a/bootloader/mem/sdram_config.inl b/bootloader/mem/sdram_config.inl index 58eb62d..42e0555 100644 --- a/bootloader/mem/sdram_config.inl +++ b/bootloader/mem/sdram_config.inl @@ -15,15 +15,17 @@ * along with this program. If not, see . */ +#define DRAM_CFG_SIZE 1896 + #define DRAM_ID(x) (1 << (x)) #define DRAM_4GB_SAMSUNG_K4F6E304HB_MGCH 0 #define DRAM_4GB_HYNIX_H9HCNNNBPUMLHR_NLN 1 #define DRAM_4GB_MICRON_MT53B512M32D2NP_062_WT 2 -#define DRAM_4GB_COPPER_UNK_3 3 // Samsung? +#define DRAM_4GB_COPPER_SAMSUNG 3 #define DRAM_6GB_SAMSUNG_K4FHE3D4HM_MFCH 4 -#define DRAM_4GB_COPPER_UNK_5 5 // Samsung? -#define DRAM_4GB_COPPER_UNK_6 6 // Samsung? +#define DRAM_4GB_COPPER_HYNIX 5 +#define DRAM_4GB_COPPER_MICRON 6 typedef struct _sdram_vendor_patch_t { @@ -658,11 +660,22 @@ static const sdram_params_t _dram_cfg_0_samsung_4gb = { }; static const sdram_vendor_patch_t sdram_cfg_vendor_patches[] = { - { 0x0000003A, 59, DRAM_ID(6) }, // emc_rfc. Auto refresh. - { 0x0000001D, 60, DRAM_ID(6) }, // emc_rfc_pb. Bank Auto refresh. + // Hynix timing config. { 0x0000000D, 67, DRAM_ID(1) | DRAM_ID(5) }, // emc_r2w. { 0x00000001, 91, DRAM_ID(1) | DRAM_ID(5) }, // emc_puterm_extra. { 0x80000000, 92, DRAM_ID(1) | DRAM_ID(5) }, // emc_puterm_width. + { 0x00000210, 317, DRAM_ID(1) | DRAM_ID(5) }, // emc_pmacro_data_rx_term_mode. + { 0x00000005, 368, DRAM_ID(1) | DRAM_ID(5) }, // mc_emem_arb_timing_r2w. + + // Samsung 6GB density config. + { 0x000C0302, 347, DRAM_ID(4) }, // mc_emem_adr_cfg_dev0. 768MB sub-partition density. + { 0x000C0302, 348, DRAM_ID(4) }, // mc_emem_adr_cfg_dev1. 768MB sub-partition density. + { 0x00001800, 353, DRAM_ID(4) }, // mc_emem_cfg. 6GB total density. + +#ifdef CONFIG_SDRAM_COPPER_SUPPORT + // Copper prototype Samsung/Hynix/Micron timing configs. + { 0x0000003A, 59, DRAM_ID(6) }, // emc_rfc. Auto refresh. + { 0x0000001D, 60, DRAM_ID(6) }, // emc_rfc_pb. Bank Auto refresh. { 0x00000012, 108, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_rw2pden. { 0x0000003B, 112, DRAM_ID(6) }, // emc_txsr. { 0x0000003B, 113, DRAM_ID(6) }, // emc_txsr_dll. @@ -687,11 +700,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches[] = { { 0x00000015, 237, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_4. { 0x00000012, 295, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_cmd_brlshft2. { 0x00000012, 296, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_cmd_brlshft3. - { 0x00000210, 317, DRAM_ID(1) | DRAM_ID(5) }, // emc_pmacro_data_rx_term_mode. - { 0x000C0302, 347, DRAM_ID(4) }, // mc_emem_adr_cfg_dev0. 768MB sub-partition density. - { 0x000C0302, 348, DRAM_ID(4) }, // mc_emem_adr_cfg_dev1. 768MB sub-partition density. - { 0x00001800, 353, DRAM_ID(4) }, // mc_emem_cfg. 6GB total density. - { 0x00000005, 368, DRAM_ID(1) | DRAM_ID(5) }, // mc_emem_arb_timing_r2w. { 0x00000007, 370, DRAM_ID(6) }, // mc_emem_arb_timing_rfcpb. Bank refresh. - { 0x72A30504, 373, DRAM_ID(6) } // mc_emem_arb_misc0. + { 0x72A30504, 373, DRAM_ID(6) }, // mc_emem_arb_misc0. +#endif }; diff --git a/bootloader/mem/sdram_param_t210.h b/bootloader/mem/sdram_param_t210.h index 4980918..4c6c60a 100644 --- a/bootloader/mem/sdram_param_t210.h +++ b/bootloader/mem/sdram_param_t210.h @@ -113,7 +113,6 @@ typedef struct _sdram_params /* Specifies the value for EMC_AUTO_CAL_CONFIG3 */ u32 emc_auto_cal_config3; - u32 emc_auto_cal_config4; u32 emc_auto_cal_config5; u32 emc_auto_cal_config6; diff --git a/bootloader/power/bq24193.c b/bootloader/power/bq24193.c index e5f24a7..d95b322 100644 --- a/bootloader/power/bq24193.c +++ b/bootloader/power/bq24193.c @@ -20,9 +20,6 @@ #include "../soc/i2c.h" #include "../utils/util.h" -#pragma GCC push_options -#pragma GCC optimize ("Os") - int bq24193_get_property(enum BQ24193_reg_prop prop, int *value) { u8 data; @@ -166,5 +163,3 @@ void bq24193_fake_battery_removal() value |= BQ24193_MISC_BATFET_DI_MASK; i2c_send_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_Misc, value); } - -#pragma GCC pop_options diff --git a/bootloader/power/max17050.c b/bootloader/power/max17050.c index bfd80c4..5fc9e3f 100644 --- a/bootloader/power/max17050.c +++ b/bootloader/power/max17050.c @@ -43,9 +43,6 @@ #define MAX17050_VMAX_TOLERANCE 50 /* 50 mV */ -#pragma GCC push_options -#pragma GCC optimize ("Os") - static u32 battery_voltage = 0; u32 max17050_get_cached_batt_volt() { @@ -274,5 +271,3 @@ int max17050_fix_configuration() return 0; } - -#pragma GCC pop_options \ No newline at end of file diff --git a/bootloader/sec/se.c b/bootloader/sec/se.c index 57c0958..52f8fea 100644 --- a/bootloader/sec/se.c +++ b/bootloader/sec/se.c @@ -71,9 +71,11 @@ static int _se_wait() return 1; } -static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size) +se_ll_t *ll_dst, *ll_src; +static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size, bool is_oneshot) { - se_ll_t *ll_dst = NULL, *ll_src = NULL; + ll_dst = NULL; + ll_src = NULL; if (dst) { @@ -95,14 +97,39 @@ static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); SE(SE_OPERATION_REG_OFFSET) = SE_OPERATION(op); + + int res = 1; + if (is_oneshot) + { + res = _se_wait(); + + bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); + + if (src) + free(ll_src); + if (dst) + free(ll_dst); + } + + return res; +} + +static int _se_execute_finalize() +{ int res = _se_wait(); bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); - if (src) + if (ll_src) + { free(ll_src); - if (dst) + ll_src = NULL; + } + if (ll_dst) + { free(ll_dst); + ll_dst = NULL; + } return res; } @@ -118,7 +145,7 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; memcpy(block, src, src_size); - int res = _se_execute(op, block, 0x10, block, 0x10); + int res = _se_execute(op, block, 0x10, block, 0x10, true); memcpy(dst, block, dst_size); free(block); @@ -176,7 +203,7 @@ int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input) SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst); - return _se_execute(OP_START, NULL, 0, input, 0x10); + return _se_execute(OP_START, NULL, 0, input, 0x10, true); } int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size) @@ -192,7 +219,7 @@ int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT); } SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1; - return _se_execute(OP_START, dst, dst_size, src, src_size); + return _se_execute(OP_START, dst, dst_size, src, src_size, true); } int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size) @@ -210,7 +237,7 @@ int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM); } SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1; - return _se_execute(OP_START, dst, dst_size, src, src_size); + return _se_execute(OP_START, dst, dst_size, src, src_size, true); } int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src) @@ -232,7 +259,7 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_s if (src_size_aligned) { SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1; - if (!_se_execute(OP_START, dst, dst_size, src, src_size_aligned)) + if (!_se_execute(OP_START, dst, dst_size, src, src_size_aligned, true)) return 0; } @@ -293,28 +320,90 @@ int se_aes_xts_crypt(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, void *src, u return 1; } -int se_calc_sha256(void *dst, const void *src, u32 src_size) +int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot) { int res; - // Setup config for SHA256, size = BITS(src_size). + u32 *hash32 = (u32 *)hash; + + if (src_size > 0xFFFFFF || (u32)hash % 4 || !hash) // Max 16MB - 1 chunks and aligned x4 hash buffer. + return 0; + + // Setup config for SHA256. 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_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_CONFIG_REG_OFFSET) = sha_cfg; + SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; + + // Set total size to current buffer size if empty. + if (!total_size) + total_size = src_size; + + // Set total size: BITS(src_size), up to 2 EB. + SE(SE_SHA_MSG_LENGTH_0_REG_OFFSET) = (u32)(total_size << 3); + SE(SE_SHA_MSG_LENGTH_1_REG_OFFSET) = (u32)(total_size >> 29); 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; + + // Set size left to hash. + SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = (u32)(total_size << 3); + SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = (u32)(total_size >> 29); SE(SE_SHA_MSG_LEFT_2_REG_OFFSET) = 0; SE(SE_SHA_MSG_LEFT_3_REG_OFFSET) = 0; + // If we hash in chunks, copy over the intermediate. + if (sha_cfg == SHA_CONTINUE) + { + if (!msg_left) + return 0; + + // Restore message left to process. + SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = msg_left[0]; + SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = msg_left[1]; + + // Restore hash reg. + for (u32 i = 0; i < 8; i++) + SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)) = byte_swap_32(hash32[i]); + } + // Trigger the operation. - res = _se_execute(OP_START, NULL, 0, src, src_size); + res = _se_execute(OP_START, NULL, 0, src, src_size, is_oneshot); + + if (is_oneshot) + { + // Backup message left. + if (msg_left) + { + msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG_OFFSET); + msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG_OFFSET); + } + + // Copy output hash. + for (u32 i = 0; i < 8; i++) + hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2))); + } + + return res; +} + +int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size) +{ + return se_calc_sha256(hash, NULL, src, src_size, 0, SHA_INIT_HASH, true); +} + +int se_calc_sha256_finalize(void *hash, u32 *msg_left) +{ + u32 *hash32 = (u32 *)hash; + int res = _se_execute_finalize(); + + // Backup message left. + if (msg_left) + { + msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG_OFFSET); + msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG_OFFSET); + } // Copy output hash. - u32 *dst32 = (u32 *)dst; for (u32 i = 0; i < 8; i++) - dst32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2))); + hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2))); return res; } @@ -333,7 +422,7 @@ int se_gen_prng128(void *dst) SE(SE_BLOCK_COUNT_REG_OFFSET) = (16 >> 4) - 1; // Trigger the operation. - return _se_execute(OP_START, dst, 16, NULL, 0); + return _se_execute(OP_START, dst, 16, NULL, 0, true); } void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize) @@ -345,7 +434,7 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize) SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(0) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY) | SE_RNG_CONFIG_MODE(RNG_MODE_FORCE_RESEED); SE(SE_CRYPTO_LAST_BLOCK) = 0; - _se_execute(OP_START, NULL, 0, NULL, 0); + _se_execute(OP_START, NULL, 0, NULL, 0, true); // Save AES keys. SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); @@ -356,7 +445,7 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize) (i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_0_3); SE(SE_CRYPTO_LAST_BLOCK) = 0; - _se_execute(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0); + _se_execute(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0, true); memcpy(keys + i * keysize, aligned_buf, 0x10); if (keysize > 0x10) @@ -365,7 +454,7 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize) (i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_4_7); SE(SE_CRYPTO_LAST_BLOCK) = 0; - _se_execute(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0); + _se_execute(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0, true); memcpy(keys + i * keysize + 0x10, aligned_buf, 0x10); } } @@ -373,11 +462,11 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize) // Save SRK to PMC secure scratches. SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(SRK); SE(0x80) = 0; // SE_CRYPTO_LAST_BLOCK - _se_execute(OP_CTX_SAVE, NULL, 0, NULL, 0); + _se_execute(OP_CTX_SAVE, NULL, 0, NULL, 0, true); // End context save. SE(SE_CONFIG_REG_OFFSET) = 0; - _se_execute(OP_CTX_SAVE, NULL, 0, NULL, 0); + _se_execute(OP_CTX_SAVE, NULL, 0, NULL, 0, true); // Get SRK. u32 srk[4]; diff --git a/bootloader/sec/se.h b/bootloader/sec/se.h index 7d12207..2184b4d 100644 --- a/bootloader/sec/se.h +++ b/bootloader/sec/se.h @@ -28,7 +28,9 @@ int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input); int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size); int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src); int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr); -int se_calc_sha256(void *dst, const void *src, u32 src_size); +int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot); +int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size); +int se_calc_sha256_finalize(void *hash, u32 *msg_left); int se_gen_prng128(void *dst); #endif diff --git a/bootloader/soc/clock.c b/bootloader/soc/clock.c index 60a069b..5d49b33 100644 --- a/bootloader/soc/clock.c +++ b/bootloader/soc/clock.c @@ -276,7 +276,7 @@ void clock_enable_pllc(u32 divn) return; // Take PLLC out of reset and set basic misc parameters. - CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) = + CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) = ((CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) & 0xFFF0000F) & ~PLLC_MISC_RESET) | (0x80000 << 4); // PLLC_EXT_FRU. CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_2) |= 0xF0 << 8; // PLLC_FLL_LD_MEM. @@ -312,6 +312,53 @@ void clock_disable_pllc() usleep(10); } +#define PLLC4_ENABLED (1 << 31) +#define PLLC4_IN_USE (~PLLC4_ENABLED) + +u32 pllc4_enabled = 0; + +static void _clock_enable_pllc4(u32 mask) +{ + pllc4_enabled |= mask; + + if (pllc4_enabled & PLLC4_ENABLED) + return; + + // Enable Phase and Frequency lock detection. + //CLOCK(CLK_RST_CONTROLLER_PLLC4_MISC) = PLLC4_MISC_EN_LCKDET; + + // Disable PLL and IDDQ in case they are on. + CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) &= ~PLLCX_BASE_ENABLE; + CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) &= ~PLLC4_BASE_IDDQ; + usleep(10); + + // Set PLLC4 dividers. + CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) = (104 << 8) | 4; // DIVM: 4, DIVP: 1. + + // Enable PLLC4 and wait for Phase and Frequency lock. + CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) |= PLLCX_BASE_ENABLE; + while (!(CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) & PLLCX_BASE_LOCK)) + ; + + msleep(1); // Wait a bit for PLL to stabilize. + + pllc4_enabled |= PLLC4_ENABLED; +} + +static void _clock_disable_pllc4(u32 mask) +{ + pllc4_enabled &= ~mask; + + if (pllc4_enabled & PLLC4_IN_USE) + return; + + // Disable PLLC4. + CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) &= ~PLLCX_BASE_ENABLE; + CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) |= PLLC4_BASE_IDDQ; + + pllc4_enabled = 0; +} + #define L_SWR_SDMMC1_RST (1 << 14) #define L_SWR_SDMMC2_RST (1 << 9) #define L_SWR_SDMMC4_RST (1 << 15) @@ -501,16 +548,32 @@ static int _clock_sdmmc_config_clock_host(u32 *pclock, u32 id, u32 val) divisor = 14; // 8 div. break; case 100000: - *pclock = 90667; - divisor = 7; // 4.5 div. + source = SDMMC_CLOCK_SRC_PLLC4_OUT2; + *pclock = 99840; + divisor = 2; // 2 div. break; case 164000: *pclock = 163200; divisor = 3; // 2.5 div. break; - case 200000: - *pclock = 204000; - divisor = 2; // 2 div. + case 200000: // 240MHz evo+. + switch (id) + { + case SDMMC_1: + source = SDMMC_CLOCK_SRC_PLLC4_OUT2; + break; + case SDMMC_2: + source = SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ; + break; + case SDMMC_3: + source = SDMMC_CLOCK_SRC_PLLC4_OUT2; + break; + case SDMMC_4: + source = SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ; + break; + } + *pclock = 199680; + divisor = 0; // 1 div. break; default: *pclock = 24728; @@ -520,6 +583,10 @@ static int _clock_sdmmc_config_clock_host(u32 *pclock, u32 id, u32 val) _clock_sdmmc_table[id].clock = val; _clock_sdmmc_table[id].real_clock = *pclock; + // Enable PLLC4 if in use by any SDMMC. + if (source) + _clock_enable_pllc4(1 << id); + // Set SDMMC legacy timeout clock. _clock_sdmmc_config_legacy_tm(); @@ -642,4 +709,5 @@ void clock_sdmmc_disable(u32 id) _clock_sdmmc_set_reset(id); _clock_sdmmc_clear_enable(id); _clock_sdmmc_is_reset(id); + _clock_disable_pllc4(1 << id); } diff --git a/bootloader/soc/hw_init.c b/bootloader/soc/hw_init.c index f5df093..b038623 100644 --- a/bootloader/soc/hw_init.c +++ b/bootloader/soc/hw_init.c @@ -25,18 +25,23 @@ #include "i2c.h" #include "pinmux.h" #include "pmc.h" -#include "t210.h" #include "uart.h" +#include "t210.h" +#include "../input/joycon.h" +#include "../input/touch.h" #include "../gfx/di.h" #include "../mem/mc.h" #include "../mem/minerva.h" #include "../mem/sdram.h" -#include "../power/max77620.h" -#include "../power/max7762x.h" #include "../sec/se.h" #include "../sec/se_t210.h" +#include "../power/max77620.h" +#include "../power/max7762x.h" +#include "../gfx/di.h" +#include "../power/regulator_5v.h" #include "../storage/nx_sd.h" #include "../storage/sdmmc.h" +#include "../thermal/fan.h" #include "../utils/util.h" extern boot_cfg_t b_cfg; @@ -326,9 +331,21 @@ void config_hw() void reconfig_hw_workaround(bool extra_reconfig, u32 magic) { - // Flush and disable MMU. - bpmp_mmu_disable(); + // Disable BPMP max clock. bpmp_clk_rate_set(BPMP_CLK_NORMAL); + +#ifdef NYX + // Deinit touchscreen, 5V regulators and Joy-Con. + touch_power_off(); + set_fan_duty(0); + jc_deinit(); + regulator_disable_5v(REGULATOR_5V_ALL); + clock_disable_uart(UART_B); + clock_disable_uart(UART_C); +#endif + + // Flush/disable MMU cache and set DRAM clock to 204MHz. + bpmp_mmu_disable(); minerva_change_freq(FREQ_204); nyx_str->mtc_cfg.init_done = 0; diff --git a/bootloader/soc/kfuse.c b/bootloader/soc/kfuse.c index f2fde5a..cdfba53 100644 --- a/bootloader/soc/kfuse.c +++ b/bootloader/soc/kfuse.c @@ -18,9 +18,6 @@ #include "../soc/clock.h" #include "../soc/t210.h" -#pragma GCC push_options -#pragma GCC optimize ("Os") - int kfuse_wait_ready() { // Wait for KFUSE to finish init and verification of data. @@ -48,9 +45,7 @@ int kfuse_read(u32 *buf) res = 1; -out:; +out: clock_disable_kfuse(); return res; } - -#pragma GCC pop_options diff --git a/bootloader/soc/uart.c b/bootloader/soc/uart.c index 2568d10..3aea2f7 100644 --- a/bootloader/soc/uart.c +++ b/bootloader/soc/uart.c @@ -79,7 +79,7 @@ void uart_send(u32 idx, const u8 *buf, u32 len) while (!(uart->UART_LSR & UART_LSR_THRE)) ; uart->UART_THR_DLAB = buf[i]; - }; + } } u32 uart_recv(u32 idx, u8 *buf, u32 len) diff --git a/bootloader/storage/emummc.c b/bootloader/storage/emummc.c index 4fffd6b..3da09e2 100644 --- a/bootloader/storage/emummc.c +++ b/bootloader/storage/emummc.c @@ -31,7 +31,6 @@ extern hekate_config h_cfg; emummc_cfg_t emu_cfg; - void emummc_load_cfg() { emu_cfg.enabled = 0; diff --git a/bootloader/storage/nx_emmc.c b/bootloader/storage/nx_emmc.c index f5765a1..897a7e3 100644 --- a/bootloader/storage/nx_emmc.c +++ b/bootloader/storage/nx_emmc.c @@ -22,6 +22,10 @@ #include "../mem/heap.h" #include "../utils/list.h" +sdmmc_t emmc_sdmmc; +sdmmc_storage_t emmc_storage; +FATFS emmc_fs; + void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage) { gpt_t *gpt_buf = (gpt_t *)calloc(NX_GPT_NUM_BLOCKS, NX_EMMC_BLOCKSIZE); diff --git a/bootloader/storage/nx_emmc.h b/bootloader/storage/nx_emmc.h index 19bc1ca..380b7a0 100644 --- a/bootloader/storage/nx_emmc.h +++ b/bootloader/storage/nx_emmc.h @@ -18,10 +18,11 @@ #define _NX_EMMC_H_ #include "sdmmc.h" +#include "../libs/fatfs/ff.h" #include "../utils/types.h" #include "../utils/list.h" -#define NX_GPT_FIRST_LBA 1 +#define NX_GPT_FIRST_LBA 1 #define NX_GPT_NUM_BLOCKS 33 #define NX_EMMC_BLOCKSIZE 512 @@ -35,6 +36,10 @@ typedef struct _emmc_part_t link_t link; } emmc_part_t; +extern sdmmc_t emmc_sdmmc; +extern sdmmc_storage_t emmc_storage; +extern FATFS emmc_fs; + void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage); void nx_emmc_gpt_free(link_t *gpt); emmc_part_t *nx_emmc_part_find(link_t *gpt, const char *name); diff --git a/bootloader/storage/sd.h b/bootloader/storage/sd.h index 3ecfc07..a780ec8 100644 --- a/bootloader/storage/sd.h +++ b/bootloader/storage/sd.h @@ -1,6 +1,4 @@ /* - * include/linux/mmc/sd.h - * * Copyright (c) 2005-2007 Pierre Ossman, All Rights Reserved. * Copyright (c) 2018 CTCaer * @@ -10,8 +8,8 @@ * your option) any later version. */ -#ifndef LINUX_MMC_SD_H -#define LINUX_MMC_SD_H +#ifndef MMC_SD_H +#define MMC_SD_H /* SD commands type argument response */ /* class 0 */ diff --git a/bootloader/storage/sdmmc_driver.c b/bootloader/storage/sdmmc_driver.c index 8e32f5d..957a0bc 100644 --- a/bootloader/storage/sdmmc_driver.c +++ b/bootloader/storage/sdmmc_driver.c @@ -30,9 +30,13 @@ #include "../utils/util.h" //#define DPRINTF(...) gfx_printf(__VA_ARGS__) +//#define ERROR_EXTRA_PRINTING #define DPRINTF(...) -u32 sd_power_cycle_time_start; +#ifdef NYX +#define ERROR_EXTRA_PRINTING +#define SDMMC_EMMC_OC +#endif /*! SCMMC controller base addresses. */ static const u32 _sdmmc_bases[4] = { @@ -222,7 +226,11 @@ static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power) sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; } +#ifdef SDMMC_EMMC_OC +static int _sdmmc_dll_cal_execute(sdmmc_t *sdmmc, bool overclock) +#else static int _sdmmc_dll_cal_execute(sdmmc_t *sdmmc) +#endif { int result = 1, should_disable_sd_clock = 0; @@ -232,6 +240,11 @@ static int _sdmmc_dll_cal_execute(sdmmc_t *sdmmc) sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; } +#ifdef SDMMC_EMMC_OC + if (sdmmc->id == SDMMC_4 && overclock) + sdmmc->regs->vendllcalcfg = sdmmc->regs->vendllcalcfg &= 0xFFFFC07F | (0x7C << 7); // Add -4 TX_DLY_CODE_OFFSET if HS533. +#endif + sdmmc->regs->vendllcalcfg |= TEGRA_MMC_DLLCAL_CFG_EN_CALIBRATE; _sdmmc_get_clkcon(sdmmc); @@ -345,7 +358,15 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type) sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; if (type == SDHCI_TIMING_MMC_HS400) + { +#ifdef SDMMC_EMMC_OC + bool overclock_en = clock > 208000; + return _sdmmc_dll_cal_execute(sdmmc, overclock_en); +#else return _sdmmc_dll_cal_execute(sdmmc); +#endif + } + return 1; } @@ -906,7 +927,9 @@ static int _sdmmc_update_dma(sdmmc_t *sdmmc) } if (result != SDMMC_MASKINT_NOERROR) { - DPRINTF("%08X!\n", result); +#ifdef ERROR_EXTRA_PRINTING + EPRINTFARGS("%08X!", result); +#endif _sdmmc_reset(sdmmc); return 0; } @@ -929,7 +952,9 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_ { if (!_sdmmc_config_dma(sdmmc, &blkcnt, req)) { - DPRINTF("SDMMC: DMA Wrong cfg!\n"); +#ifdef ERROR_EXTRA_PRINTING + EPRINTF("SDMMC: DMA Wrong cfg!"); +#endif return 0; } @@ -945,14 +970,18 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_ if (!_sdmmc_send_cmd(sdmmc, cmd, is_data_present)) { - DPRINTF("SDMMC: Wrong Response type %08X!\n", cmd->rsp_type); +#ifdef ERROR_EXTRA_PRINTING + EPRINTFARGS("SDMMC: Wrong Response type %08X!", cmd->rsp_type); +#endif return 0; } int result = _sdmmc_wait_response(sdmmc); if (!result) { - DPRINTF("SDMMC: Transfer timeout!\n"); +#ifdef ERROR_EXTRA_PRINTING + EPRINTF("SDMMC: Transfer timeout!"); +#endif } DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result, sdmmc->regs->rspreg0, sdmmc->regs->rspreg1, sdmmc->regs->rspreg2, sdmmc->regs->rspreg3); @@ -964,7 +993,9 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_ result = _sdmmc_cache_rsp(sdmmc, sdmmc->rsp, 0x10, cmd->rsp_type); if (!result) { - DPRINTF("SDMMC: Unknown response %08X!\n", sdmmc->rsp[0]); +#ifdef ERROR_EXTRA_PRINTING + EPRINTFARGS("SDMMC: Unknown response %08X!", sdmmc->rsp[0]); +#endif } } if (req && result) @@ -972,7 +1003,9 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_ result = _sdmmc_update_dma(sdmmc); if (!result) { - DPRINTF("SDMMC: DMA Update failed!\n"); +#ifdef ERROR_EXTRA_PRINTING + EPRINTF("SDMMC: DMA Update failed!"); +#endif } } } @@ -998,7 +1031,9 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_ result = _sdmmc_wait_card_busy(sdmmc); if (!result) { - DPRINTF("SDMMC: Busy timeout!\n"); +#ifdef ERROR_EXTRA_PRINTING + EPRINTF("SDMMC: Busy timeout!"); +#endif } return result; } diff --git a/bootloader/utils/btn.c b/bootloader/utils/btn.c index 5a1d024..b6e5db3 100644 --- a/bootloader/utils/btn.c +++ b/bootloader/utils/btn.c @@ -70,6 +70,22 @@ u8 btn_wait() } u8 btn_wait_timeout(u32 time_ms, u8 mask) +{ + u32 timeout = get_tmr_ms() + time_ms; + u8 res = btn_read() & mask; + + while (get_tmr_ms() < timeout) + { + if (res == mask) + break; + else + res = btn_read() & mask; + }; + + return res; +} + +u8 btn_wait_timeout_single(u32 time_ms, u8 mask) { u8 single_button = mask & BTN_SINGLE; mask &= ~BTN_SINGLE; diff --git a/bootloader/utils/btn.h b/bootloader/utils/btn.h index 4f6b4d2..1c42cc2 100644 --- a/bootloader/utils/btn.h +++ b/bootloader/utils/btn.h @@ -29,5 +29,6 @@ u8 btn_read(); u8 btn_read_vol(); u8 btn_wait(); u8 btn_wait_timeout(u32 time_ms, u8 mask); +u8 btn_wait_timeout_single(u32 time_ms, u8 mask); #endif diff --git a/bootloader/utils/dirlist.c b/bootloader/utils/dirlist.c index 2bb8eaf..a895c2c 100644 --- a/bootloader/utils/dirlist.c +++ b/bootloader/utils/dirlist.c @@ -21,7 +21,7 @@ #include "../mem/heap.h" #include "../utils/types.h" -char *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles) +char *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs) { u8 max_entries = 61; @@ -40,12 +40,18 @@ char *dirlist(const char *directory, const char *pattern, bool includeHiddenFile res = f_readdir(&dir, &fno); if (res || !fno.fname[0]) break; - if (!(fno.fattrib & AM_DIR) && (fno.fname[0] != '.') && (includeHiddenFiles || !(fno.fattrib & AM_HID))) + + bool curr_parse = parse_dirs ? (fno.fattrib & AM_DIR) : !(fno.fattrib & AM_DIR); + + if (curr_parse) { - strcpy(dir_entries + (k * 256), fno.fname); - k++; - if (k > (max_entries - 1)) - break; + if ((fno.fname[0] != '.') && (includeHiddenFiles || !(fno.fattrib & AM_HID))) + { + strcpy(dir_entries + (k * 256), fno.fname); + k++; + if (k > (max_entries - 1)) + break; + } } } f_closedir(&dir); diff --git a/bootloader/utils/dirlist.h b/bootloader/utils/dirlist.h index 4fb9af7..9ad3c38 100644 --- a/bootloader/utils/dirlist.h +++ b/bootloader/utils/dirlist.h @@ -16,4 +16,4 @@ #include "../utils/types.h" -char *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles); +char *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs); diff --git a/nyx/nyx_gui/frontend/fe_emmc_tools.c b/nyx/nyx_gui/frontend/fe_emmc_tools.c index 5f6f1d1..03a4e53 100644 --- a/nyx/nyx_gui/frontend/fe_emmc_tools.c +++ b/nyx/nyx_gui/frontend/fe_emmc_tools.c @@ -252,7 +252,7 @@ static int _dump_emmc_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage, u32 } manual_system_maintenance(false); se_calc_sha256_finalize(hashEm, NULL); - se_calc_sha256(hashSd, NULL, bufSd, num << 9, 0, SHA_INIT_HASH, true); + se_calc_sha256_oneshot(hashSd, bufSd, num << 9); res = memcmp(hashEm, hashSd, 0x10); if (res) diff --git a/nyx/nyx_gui/frontend/gui.c b/nyx/nyx_gui/frontend/gui.c index 8e40a45..7efc9fc 100644 --- a/nyx/nyx_gui/frontend/gui.c +++ b/nyx/nyx_gui/frontend/gui.c @@ -116,7 +116,7 @@ static gui_status_bar_ctx status_bar; static void _nyx_disp_init() { display_backlight_brightness(0, 1000); - display_init_framebuffer_pitch(); + display_init_framebuffer_pitch_inv(); display_init_framebuffer_log(); display_backlight_brightness(h_cfg.backlight - 20, 1000); } diff --git a/nyx/nyx_gui/frontend/gui_info.c b/nyx/nyx_gui/frontend/gui_info.c index 950e550..0d5b15d 100644 --- a/nyx/nyx_gui/frontend/gui_info.c +++ b/nyx/nyx_gui/frontend/gui_info.c @@ -447,7 +447,7 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn) default: switch (display_id & 0xFF) { - case PANEL_JDI_LPM062M: + case PANEL_JDI_XXX062M: s_printf(txt_buf + strlen(txt_buf), "JDI "); break; case (PANEL_INL_P062CCA_AZ1 & 0xFF): diff --git a/nyx/nyx_gui/gfx/di.c b/nyx/nyx_gui/gfx/di.c index 56b9631..015df23 100644 --- a/nyx/nyx_gui/gfx/di.c +++ b/nyx/nyx_gui/gfx/di.c @@ -145,13 +145,13 @@ void display_init() // Decode Display ID. _display_id = ((_display_id >> 8) & 0xFF00) | (_display_id & 0xFF); - if ((_display_id & 0xFF) == PANEL_JDI_LPM062M) - _display_id = PANEL_JDI_LPM062M; + if ((_display_id & 0xFF) == PANEL_JDI_XXX062M) + _display_id = PANEL_JDI_XXX062M; // Initialize display panel. switch (_display_id) { - case PANEL_JDI_LPM062M: + case PANEL_JDI_XXX062M: exec_cfg((u32 *)DSI_BASE, _display_init_config_jdi, 43); _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000); break; @@ -264,7 +264,7 @@ void display_end() // De-initialize display panel. switch (_display_id) { - case PANEL_JDI_LPM062M: + case PANEL_JDI_XXX062M: exec_cfg((u32 *)DSI_BASE, _display_deinit_config_jdi, 22); break; case PANEL_AUO_A062TAN01: @@ -338,9 +338,21 @@ void display_color_screen(u32 color) } u32 *display_init_framebuffer_pitch() +{ + // Sanitize framebuffer area. + 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_pitch, 32); + usleep(35000); + + return (u32 *)IPL_FB_ADDRESS; +} + +u32 *display_init_framebuffer_pitch_inv() { // This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 1280x720 (line stride 720). - exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_pitch, 34); + exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_pitch_inv, 34); usleep(35000); diff --git a/nyx/nyx_gui/gfx/di.h b/nyx/nyx_gui/gfx/di.h index cefc764..29685c6 100644 --- a/nyx/nyx_gui/gfx/di.h +++ b/nyx/nyx_gui/gfx/di.h @@ -506,7 +506,7 @@ enum { - PANEL_JDI_LPM062M = 0x10, + PANEL_JDI_XXX062M = 0x10, PANEL_JDI_LAM062M109A = 0x0910, PANEL_JDI_LPM062M326A = 0x2610, PANEL_INL_P062CCA_AZ1 = 0x0F20, @@ -528,6 +528,7 @@ void display_backlight_brightness(u32 brightness, u32 step_delay); /*! Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */ u32 *display_init_framebuffer_pitch(); +u32 *display_init_framebuffer_pitch_inv(); u32 *display_init_framebuffer_block(); u32 *display_init_framebuffer_log(); void display_activate_console(); diff --git a/nyx/nyx_gui/gfx/di.inl b/nyx/nyx_gui/gfx/di.inl index 071b489..ef3b1b0 100644 --- a/nyx/nyx_gui/gfx/di.inl +++ b/nyx/nyx_gui/gfx/di.inl @@ -559,8 +559,44 @@ static const cfg_op_t cfg_display_one_color[8] = { {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY} // Continuous display. }; -//Display A config pitch. -static const cfg_op_t cfg_display_framebuffer_pitch[34] = { +//Display A config linear pitch. +static const cfg_op_t cfg_display_framebuffer_pitch[32] = { + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, + {DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, // NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8. + {DC_WIN_WIN_OPTIONS, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_WIN_POSITION, 0}, //(0,0) + {DC_WIN_H_INITIAL_DDA, 0}, + {DC_WIN_V_INITIAL_DDA, 0}, + {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)}, + {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x. + {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, + {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, // 720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. + {DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST}, + {DC_WINBUF_SURFACE_KIND, PITCH}, + {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}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, + {DC_WIN_WIN_OPTIONS, WIN_ENABLE}, // Enable window AD. + {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, // Continuous display. + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ} +}; + +//Display A config linear pitch inverse + Win D support. +static const cfg_op_t cfg_display_framebuffer_pitch_inv[34] = { {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT}, {DC_WIN_WIN_OPTIONS, 0}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, @@ -576,7 +612,7 @@ static const cfg_op_t cfg_display_framebuffer_pitch[34] = { {DC_WIN_POSITION, 0}, //(0,0) {DC_WIN_H_INITIAL_DDA, 0}, {DC_WIN_V_INITIAL_DDA, 0}, - {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(2880)}, + {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)}, {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x. {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, // 720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. @@ -614,7 +650,7 @@ static const cfg_op_t cfg_display_framebuffer_block[34] = { {DC_WIN_POSITION, 0}, //(0,0) {DC_WIN_H_INITIAL_DDA, 0}, {DC_WIN_V_INITIAL_DDA, 0}, - {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(2880)}, + {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)}, {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x. {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(1280 * 2) | LINE_STRIDE(1280 * 4)}, //720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. diff --git a/nyx/nyx_gui/libs/fatfs/ff.c b/nyx/nyx_gui/libs/fatfs/ff.c index c48c036..c6c4d75 100644 --- a/nyx/nyx_gui/libs/fatfs/ff.c +++ b/nyx/nyx_gui/libs/fatfs/ff.c @@ -3906,11 +3906,11 @@ FRESULT f_read ( -#ifdef FF_FASTFS +#if FF_FASTFS && FF_USE_FASTSEEK /*-----------------------------------------------------------------------*/ /* Fast Read Aligned Sized File Without a Cache */ /*-----------------------------------------------------------------------*/ -#if FF_USE_FASTSEEK + FRESULT f_read_fast ( FIL* fp, /* Pointer to the file object */ const void* buff, /* Pointer to the data to be written */ @@ -3988,7 +3988,6 @@ FRESULT f_read_fast ( LEAVE_FF(fs, FR_OK); } #endif -#endif @@ -4132,11 +4131,11 @@ FRESULT f_write ( -#ifdef FF_FASTFS +#if FF_FASTFS && FF_USE_FASTSEEK /*-----------------------------------------------------------------------*/ /* Fast Write Aligned Sized File Without a Cache */ /*-----------------------------------------------------------------------*/ -#if FF_USE_FASTSEEK + FRESULT f_write_fast ( FIL* fp, /* Pointer to the file object */ const void* buff, /* Pointer to the data to be written */ @@ -4219,7 +4218,6 @@ FRESULT f_write_fast ( LEAVE_FF(fs, FR_OK); } #endif -#endif @@ -4680,8 +4678,7 @@ FRESULT f_lseek ( -#ifdef FF_FASTFS -#if FF_USE_FASTSEEK +#if FF_FASTFS && FF_USE_FASTSEEK /*-----------------------------------------------------------------------*/ /* Seek File Read/Write Pointer */ /*-----------------------------------------------------------------------*/ @@ -4708,7 +4705,6 @@ DWORD *f_expand_cltbl ( return fp->cltbl; } #endif -#endif diff --git a/nyx/nyx_gui/libs/fatfs/ff.h b/nyx/nyx_gui/libs/fatfs/ff.h index 6c47c73..af1151f 100644 --- a/nyx/nyx_gui/libs/fatfs/ff.h +++ b/nyx/nyx_gui/libs/fatfs/ff.h @@ -246,7 +246,7 @@ typedef enum { FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */ -#ifdef FF_FASTFS +#if FF_FASTFS FR_INVALID_PARAMETER, /* (19) Given parameter is invalid */ FR_CLTBL_NO_INIT /* (20) The cluster table for fast seek/read/write was not created */ #else @@ -263,10 +263,8 @@ FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a f FRESULT f_close (FIL* fp); /* Close an open file object */ FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */ FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */ -#ifdef FF_FASTFS FRESULT f_read_fast (FIL* fp, const void* buff, UINT btr); /* Fast read data from the file */ FRESULT f_write_fast (FIL* fp, const void* buff, UINT btw); /* Fast write data to the file */ -#endif FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */ FRESULT f_truncate (FIL* fp); /* Truncate the file */ FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */ @@ -288,9 +286,7 @@ FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get numbe FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */ FRESULT f_setlabel (const TCHAR* label); /* Set volume label */ FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */ -#ifdef FF_FASTFS DWORD *f_expand_cltbl (FIL* fp, UINT tblsz, FSIZE_t ofs); /* Expand file and populate cluster table */ -#endif FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt); /* Allocate a contiguous block to the file */ FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */ FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */ diff --git a/nyx/nyx_gui/libs/fatfs/ffconf.h b/nyx/nyx_gui/libs/fatfs/ffconf.h index dc83987..1f79990 100644 --- a/nyx/nyx_gui/libs/fatfs/ffconf.h +++ b/nyx/nyx_gui/libs/fatfs/ffconf.h @@ -41,14 +41,16 @@ #define FF_USE_MKFS 1 /* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ + +#define FF_USE_FASTSEEK 0 +/* This option switches fast seek function. (0:Disable or 1:Enable) */ + #define FF_FASTFS 1 -#ifdef FF_FASTFS +#if FF_FASTFS +#undef FF_USE_FASTSEEK #define FF_USE_FASTSEEK 1 -#else -#define FF_USE_FASTSEEK 0 #endif -/* This option switches fast seek function. (0:Disable or 1:Enable) */ #define FF_USE_EXPAND 0 @@ -245,7 +247,7 @@ #define FF_FS_NORTC 0 #define FF_NORTC_MON 1 #define FF_NORTC_MDAY 1 -#define FF_NORTC_YEAR 2019 +#define FF_NORTC_YEAR 2020 /* The option FF_FS_NORTC switches timestamp function. If the system does not have / any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable / the timestamp function. Every object modified by FatFs will have a fixed timestamp diff --git a/nyx/nyx_gui/mem/minerva.c b/nyx/nyx_gui/mem/minerva.c index 71c9dbf..c399070 100644 --- a/nyx/nyx_gui/mem/minerva.c +++ b/nyx/nyx_gui/mem/minerva.c @@ -37,6 +37,7 @@ u32 minerva_init() minerva_cfg = NULL; mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg; +#ifdef NYX // Set table to nyx storage. mtc_cfg->mtc_table = (emc_table_t *)nyx_str->mtc_table; @@ -69,6 +70,23 @@ u32 minerva_init() if (minerva_cfg) memcpy(mtc_cfg, (void *)&mtc_tmp, sizeof(mtc_config_t)); } +#else + memset(mtc_cfg, 0, sizeof(mtc_config_t)); + + // Set table to nyx storage. + mtc_cfg->mtc_table = (emc_table_t *)nyx_str->mtc_table; + + mtc_cfg->sdram_id = (fuse_read_odm(4) >> 3) & 0x1F; + mtc_cfg->init_done = MTC_NEW_MAGIC; // Initialize mtc table. + + u32 ep_addr = ianos_loader(false, "bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)mtc_cfg); + + // Ensure that Minerva is new. + if (mtc_cfg->init_done == MTC_INIT_MAGIC) + minerva_cfg = (void *)ep_addr; + else + mtc_cfg->init_done = 0; +#endif if (!minerva_cfg) return 1; diff --git a/nyx/nyx_gui/mem/sdram.c b/nyx/nyx_gui/mem/sdram.c index 6c6d264..bf72966 100644 --- a/nyx/nyx_gui/mem/sdram.c +++ b/nyx/nyx_gui/mem/sdram.c @@ -723,11 +723,14 @@ sdram_params_t *sdram_get_params() case DRAM_4GB_SAMSUNG_K4F6E304HB_MGCH: case DRAM_4GB_MICRON_MT53B512M32D2NP_062_WT: break; + case DRAM_4GB_HYNIX_H9HCNNNBPUMLHR_NLN: - case DRAM_4GB_COPPER_UNK_3: case DRAM_6GB_SAMSUNG_K4FHE3D4HM_MFCH: - case DRAM_4GB_COPPER_UNK_5: - case DRAM_4GB_COPPER_UNK_6: +#ifdef CONFIG_SDRAM_COPPER_SUPPORT + case DRAM_4GB_COPPER_SAMSUNG: + case DRAM_4GB_COPPER_HYNIX: + case DRAM_4GB_COPPER_MICRON: +#endif _sdram_patch_model_params(dramid, (u32 *)buf); break; } diff --git a/nyx/nyx_gui/mem/sdram_config.inl b/nyx/nyx_gui/mem/sdram_config.inl index 58eb62d..42e0555 100644 --- a/nyx/nyx_gui/mem/sdram_config.inl +++ b/nyx/nyx_gui/mem/sdram_config.inl @@ -15,15 +15,17 @@ * along with this program. If not, see . */ +#define DRAM_CFG_SIZE 1896 + #define DRAM_ID(x) (1 << (x)) #define DRAM_4GB_SAMSUNG_K4F6E304HB_MGCH 0 #define DRAM_4GB_HYNIX_H9HCNNNBPUMLHR_NLN 1 #define DRAM_4GB_MICRON_MT53B512M32D2NP_062_WT 2 -#define DRAM_4GB_COPPER_UNK_3 3 // Samsung? +#define DRAM_4GB_COPPER_SAMSUNG 3 #define DRAM_6GB_SAMSUNG_K4FHE3D4HM_MFCH 4 -#define DRAM_4GB_COPPER_UNK_5 5 // Samsung? -#define DRAM_4GB_COPPER_UNK_6 6 // Samsung? +#define DRAM_4GB_COPPER_HYNIX 5 +#define DRAM_4GB_COPPER_MICRON 6 typedef struct _sdram_vendor_patch_t { @@ -658,11 +660,22 @@ static const sdram_params_t _dram_cfg_0_samsung_4gb = { }; static const sdram_vendor_patch_t sdram_cfg_vendor_patches[] = { - { 0x0000003A, 59, DRAM_ID(6) }, // emc_rfc. Auto refresh. - { 0x0000001D, 60, DRAM_ID(6) }, // emc_rfc_pb. Bank Auto refresh. + // Hynix timing config. { 0x0000000D, 67, DRAM_ID(1) | DRAM_ID(5) }, // emc_r2w. { 0x00000001, 91, DRAM_ID(1) | DRAM_ID(5) }, // emc_puterm_extra. { 0x80000000, 92, DRAM_ID(1) | DRAM_ID(5) }, // emc_puterm_width. + { 0x00000210, 317, DRAM_ID(1) | DRAM_ID(5) }, // emc_pmacro_data_rx_term_mode. + { 0x00000005, 368, DRAM_ID(1) | DRAM_ID(5) }, // mc_emem_arb_timing_r2w. + + // Samsung 6GB density config. + { 0x000C0302, 347, DRAM_ID(4) }, // mc_emem_adr_cfg_dev0. 768MB sub-partition density. + { 0x000C0302, 348, DRAM_ID(4) }, // mc_emem_adr_cfg_dev1. 768MB sub-partition density. + { 0x00001800, 353, DRAM_ID(4) }, // mc_emem_cfg. 6GB total density. + +#ifdef CONFIG_SDRAM_COPPER_SUPPORT + // Copper prototype Samsung/Hynix/Micron timing configs. + { 0x0000003A, 59, DRAM_ID(6) }, // emc_rfc. Auto refresh. + { 0x0000001D, 60, DRAM_ID(6) }, // emc_rfc_pb. Bank Auto refresh. { 0x00000012, 108, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_rw2pden. { 0x0000003B, 112, DRAM_ID(6) }, // emc_txsr. { 0x0000003B, 113, DRAM_ID(6) }, // emc_txsr_dll. @@ -687,11 +700,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches[] = { { 0x00000015, 237, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_4. { 0x00000012, 295, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_cmd_brlshft2. { 0x00000012, 296, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_cmd_brlshft3. - { 0x00000210, 317, DRAM_ID(1) | DRAM_ID(5) }, // emc_pmacro_data_rx_term_mode. - { 0x000C0302, 347, DRAM_ID(4) }, // mc_emem_adr_cfg_dev0. 768MB sub-partition density. - { 0x000C0302, 348, DRAM_ID(4) }, // mc_emem_adr_cfg_dev1. 768MB sub-partition density. - { 0x00001800, 353, DRAM_ID(4) }, // mc_emem_cfg. 6GB total density. - { 0x00000005, 368, DRAM_ID(1) | DRAM_ID(5) }, // mc_emem_arb_timing_r2w. { 0x00000007, 370, DRAM_ID(6) }, // mc_emem_arb_timing_rfcpb. Bank refresh. - { 0x72A30504, 373, DRAM_ID(6) } // mc_emem_arb_misc0. + { 0x72A30504, 373, DRAM_ID(6) }, // mc_emem_arb_misc0. +#endif }; diff --git a/nyx/nyx_gui/mem/sdram_param_t210.h b/nyx/nyx_gui/mem/sdram_param_t210.h index 4980918..4c6c60a 100644 --- a/nyx/nyx_gui/mem/sdram_param_t210.h +++ b/nyx/nyx_gui/mem/sdram_param_t210.h @@ -113,7 +113,6 @@ typedef struct _sdram_params /* Specifies the value for EMC_AUTO_CAL_CONFIG3 */ u32 emc_auto_cal_config3; - u32 emc_auto_cal_config4; u32 emc_auto_cal_config5; u32 emc_auto_cal_config6; diff --git a/nyx/nyx_gui/sec/se.c b/nyx/nyx_gui/sec/se.c index 9dc4a77..52f8fea 100644 --- a/nyx/nyx_gui/sec/se.c +++ b/nyx/nyx_gui/sec/se.c @@ -384,6 +384,11 @@ int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 return res; } +int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size) +{ + return se_calc_sha256(hash, NULL, src, src_size, 0, SHA_INIT_HASH, true); +} + int se_calc_sha256_finalize(void *hash, u32 *msg_left) { u32 *hash32 = (u32 *)hash; diff --git a/nyx/nyx_gui/sec/se.h b/nyx/nyx_gui/sec/se.h index 3a2b9f5..2184b4d 100644 --- a/nyx/nyx_gui/sec/se.h +++ b/nyx/nyx_gui/sec/se.h @@ -29,6 +29,7 @@ int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src); int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr); int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot); +int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size); int se_calc_sha256_finalize(void *hash, u32 *msg_left); int se_gen_prng128(void *dst); diff --git a/nyx/nyx_gui/soc/clock.c b/nyx/nyx_gui/soc/clock.c index 20c6d62..5d49b33 100644 --- a/nyx/nyx_gui/soc/clock.c +++ b/nyx/nyx_gui/soc/clock.c @@ -276,7 +276,7 @@ void clock_enable_pllc(u32 divn) return; // Take PLLC out of reset and set basic misc parameters. - CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) = + CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) = ((CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) & 0xFFF0000F) & ~PLLC_MISC_RESET) | (0x80000 << 4); // PLLC_EXT_FRU. CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_2) |= 0xF0 << 8; // PLLC_FLL_LD_MEM. @@ -315,7 +315,7 @@ void clock_disable_pllc() #define PLLC4_ENABLED (1 << 31) #define PLLC4_IN_USE (~PLLC4_ENABLED) -static u32 pllc4_enabled = 0; +u32 pllc4_enabled = 0; static void _clock_enable_pllc4(u32 mask) { diff --git a/nyx/nyx_gui/soc/hw_init.c b/nyx/nyx_gui/soc/hw_init.c index 45482cc..ffdb0fc 100644 --- a/nyx/nyx_gui/soc/hw_init.c +++ b/nyx/nyx_gui/soc/hw_init.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2018 naehrwert * Copyright (c) 2018-2020 CTCaer * * This program is free software; you can redistribute it and/or modify it @@ -19,27 +20,333 @@ #include "hw_init.h" #include "bpmp.h" #include "clock.h" +#include "fuse.h" #include "gpio.h" +#include "i2c.h" +#include "pinmux.h" #include "pmc.h" #include "uart.h" #include "t210.h" -#include "../mem/minerva.h" -#include "../gfx/di.h" #include "../input/joycon.h" #include "../input/touch.h" +#include "../gfx/di.h" +#include "../mem/mc.h" +#include "../mem/minerva.h" +#include "../mem/sdram.h" +#include "../sec/se.h" +#include "../sec/se_t210.h" +#include "../power/max77620.h" +#include "../power/max7762x.h" +#include "../gfx/di.h" #include "../power/regulator_5v.h" #include "../storage/nx_sd.h" #include "../storage/sdmmc.h" #include "../thermal/fan.h" #include "../utils/util.h" +extern boot_cfg_t b_cfg; extern volatile nyx_storage_t *nyx_str; +/* + * CLK_OSC - 38.4 MHz crystal. + * CLK_M - 19.2 MHz (osc/2). + * CLK_S - 32.768 KHz (from PMIC). + * SCLK - 204MHz init (-> 408MHz -> OC). + * HCLK - 204MHz init (-> 408MHz -> OC). + * PCLK - 68MHz init (-> 136MHz -> OC/4). + */ + +void _config_oscillators() +{ + CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) = (CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) & 0xFFFFFFF3) | 4; // Set CLK_M_DIVISOR to 2. + SYSCTR0(SYSCTR0_CNTFID0) = 19200000; // Set counter frequency. + TMR(TIMERUS_USEC_CFG) = 0x45F; // For 19.2MHz clk_m. + CLOCK(CLK_RST_CONTROLLER_OSC_CTRL) = 0x50000071; // Set OSC to 38.4MHz and drive strength. + + PMC(APBDEV_PMC_OSC_EDPD_OVER) = (PMC(APBDEV_PMC_OSC_EDPD_OVER) & 0xFFFFFF81) | 0xE; // Set LP0 OSC drive strength. + PMC(APBDEV_PMC_OSC_EDPD_OVER) = (PMC(APBDEV_PMC_OSC_EDPD_OVER) & 0xFFBFFFFF) | PMC_OSC_EDPD_OVER_OSC_CTRL_OVER; + PMC(APBDEV_PMC_CNTRL2) = (PMC(APBDEV_PMC_CNTRL2) & 0xFFFFEFFF) | PMC_CNTRL2_HOLD_CKE_LOW_EN; + PMC(APBDEV_PMC_SCRATCH188) = (PMC(APBDEV_PMC_SCRATCH188) & 0xFCFFFFFF) | (4 << 23); // LP0 EMC2TMC_CFG_XM2COMP_PU_VREF_SEL_RANGE. + + CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 0x10; // Set HCLK div to 2 and PCLK div to 1. + CLOCK(CLK_RST_CONTROLLER_PLLMB_BASE) &= 0xBFFFFFFF; // PLLMB disable. + + PMC(APBDEV_PMC_TSC_MULT) = (PMC(APBDEV_PMC_TSC_MULT) & 0xFFFF0000) | 0x249F; //0x249F = 19200000 * (16 / 32.768 kHz) + + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SYS) = 0; // Set SCLK div to 1. + CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20004444; // Set clk source to Run and PLLP_OUT2 (204MHz). + CLOCK(CLK_RST_CONTROLLER_SUPER_SCLK_DIVIDER) = 0x80000000; // Enable SUPER_SDIV to 1. + CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // Set HCLK div to 1 and PCLK div to 3. +} + +void _config_gpios() +{ + /////////////////put mariko stuff, basically lite. + + PINMUX_AUX(PINMUX_AUX_UART2_TX) = 0; + PINMUX_AUX(PINMUX_AUX_UART3_TX) = 0; + + // Set Joy-Con IsAttached direction. + PINMUX_AUX(PINMUX_AUX_GPIO_PE6) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE; + PINMUX_AUX(PINMUX_AUX_GPIO_PH6) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE; + + // Set pin mode for Joy-Con IsAttached and UARTB/C TX pins. +#if !defined (DEBUG_UART_PORT) || DEBUG_UART_PORT != UART_B + gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO); +#endif +#if !defined (DEBUG_UART_PORT) || DEBUG_UART_PORT != UART_C + gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_GPIO); +#endif + // Set Joy-Con IsAttached mode. + gpio_config(GPIO_PORT_E, GPIO_PIN_6, GPIO_MODE_GPIO); + gpio_config(GPIO_PORT_H, GPIO_PIN_6, GPIO_MODE_GPIO); + + // Enable input logic for Joy-Con IsAttached and UARTB/C TX pins. + gpio_output_enable(GPIO_PORT_G, GPIO_PIN_0, GPIO_OUTPUT_DISABLE); + gpio_output_enable(GPIO_PORT_D, GPIO_PIN_1, GPIO_OUTPUT_DISABLE); + gpio_output_enable(GPIO_PORT_E, GPIO_PIN_6, GPIO_OUTPUT_DISABLE); + gpio_output_enable(GPIO_PORT_H, GPIO_PIN_6, GPIO_OUTPUT_DISABLE); + + pinmux_config_i2c(I2C_1); + pinmux_config_i2c(I2C_5); + pinmux_config_uart(UART_A); + + // Configure volume up/down as inputs. + gpio_config(GPIO_PORT_X, GPIO_PIN_6, GPIO_MODE_GPIO); + gpio_config(GPIO_PORT_X, GPIO_PIN_7, GPIO_MODE_GPIO); + gpio_output_enable(GPIO_PORT_X, GPIO_PIN_6, GPIO_OUTPUT_DISABLE); + gpio_output_enable(GPIO_PORT_X, GPIO_PIN_7, GPIO_OUTPUT_DISABLE); + + // Configure HOME as inputs. + // PINMUX_AUX(PINMUX_AUX_BUTTON_HOME) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE; + // gpio_config(GPIO_PORT_Y, GPIO_PIN_1, GPIO_MODE_GPIO); +} + +void _config_pmc_scratch() +{ + PMC(APBDEV_PMC_SCRATCH20) &= 0xFFF3FFFF; // Unset Debug console from Customer Option. + PMC(APBDEV_PMC_SCRATCH190) &= 0xFFFFFFFE; // Unset DATA_DQ_E_IVREF EMC_PMACRO_DATA_PAD_TX_CTRL + PMC(APBDEV_PMC_SECURE_SCRATCH21) |= PMC_FUSE_PRIVATEKEYDISABLE_TZ_STICKY_BIT; +} + +void _mbist_workaround() +{ + CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= (1 << 10); // Enable AHUB clock. + CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= (1 << 6); // Enable APE clock. + + // Set mux output to SOR1 clock switch. + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SOR1) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SOR1) | 0x8000) & 0xFFFFBFFF; + // Enabled PLLD and set csi to PLLD for test pattern generation. + CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) |= 0x40800000; + + // Clear per-clock resets. + CLOCK(CLK_RST_CONTROLLER_RST_DEV_Y_CLR) = 0x40; // Clear reset APE. + CLOCK(CLK_RST_CONTROLLER_RST_DEV_X_CLR) = 0x40000; // Clear reset VIC. + CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = 0x18000000; // Clear reset DISP1, HOST1X. + usleep(2); + + // I2S channels to master and disable SLCG. + I2S(I2S1_CTRL) |= I2S_CTRL_MASTER_EN; + I2S(I2S1_CG) &= ~I2S_CG_SLCG_ENABLE; + I2S(I2S2_CTRL) |= I2S_CTRL_MASTER_EN; + I2S(I2S2_CG) &= ~I2S_CG_SLCG_ENABLE; + I2S(I2S3_CTRL) |= I2S_CTRL_MASTER_EN; + I2S(I2S3_CG) &= ~I2S_CG_SLCG_ENABLE; + I2S(I2S4_CTRL) |= I2S_CTRL_MASTER_EN; + I2S(I2S4_CG) &= ~I2S_CG_SLCG_ENABLE; + I2S(I2S5_CTRL) |= I2S_CTRL_MASTER_EN; + I2S(I2S5_CG) &= ~I2S_CG_SLCG_ENABLE; + + DISPLAY_A(_DIREG(DC_COM_DSC_TOP_CTL)) |= 4; // DSC_SLCG_OVERRIDE. + VIC(0x8C) = 0xFFFFFFFF; + usleep(2); + + // Set per-clock reset. + CLOCK(CLK_RST_CONTROLLER_RST_DEV_Y_SET) = 0x40; // Set reset APE. + CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = 0x18000000; // Set reset DISP1, HOST1x. + CLOCK(CLK_RST_CONTROLLER_RST_DEV_X_SET) = 0x40000; // Set reset VIC. + + // Enable specific clocks and disable all others. + CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) = 0xC0; // Enable clock PMC, FUSE. + CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) = 0x80000130; // Enable clock RTC, TMR, GPIO, BPMP_CACHE. + //CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) = 0x80400130; // Keep USBD ON. + CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_U) = 0x1F00200; // Enable clock CSITE, IRAMA, IRAMB, IRAMC, IRAMD, BPMP_CACHE_RAM. + CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) = 0x80400808; // Enable clock MSELECT, APB2APE, SPDIF_DOUBLER, SE. + CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_W) = 0x402000FC; // Enable clock PCIERX0, PCIERX1, PCIERX2, PCIERX3, PCIERX4, PCIERX5, ENTROPY, MC1. + CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_X) = 0x23000780; // Enable clock MC_CAPA, MC_CAPB, MC_CPU, MC_BBC, DBGAPB, HPLL_ADSP, PLLG_REF. + CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) = 0x300; // Enable clock MC_CDPA, MC_CCPA. + + // Disable clock gate overrides. + CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA) = 0; + CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB) = 0; + CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRC) = 0; + CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) = 0; + CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRE) = 0; + + // Set child clock sources. + CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) &= 0x1F7FFFFF; // Disable PLLD and set reference clock and csi clock. + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SOR1) &= 0xFFFF3FFF; // Set SOR1 to automatic muxing of safe clock (24MHz) or SOR1 clk switch. + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_VI) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_VI) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT. + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT. + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_NVENC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_NVENC) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT. +} + +void _config_se_brom() +{ + // Enable fuse clock. + clock_enable_fuse(true); + + // Skip SBK/SSK if sept was run. + if (!(b_cfg.boot_cfg & BOOT_CFG_SEPT_RUN)) + { + // Bootrom part we skipped. + u32 sbk[4] = { + FUSE(FUSE_PRIVATE_KEY0), + FUSE(FUSE_PRIVATE_KEY1), + FUSE(FUSE_PRIVATE_KEY2), + FUSE(FUSE_PRIVATE_KEY3) + }; + // Set SBK to slot 14. + se_aes_key_set(14, sbk, 0x10); + + // Lock SBK from being read. + SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 14 * 4) = 0x7E; + + // Lock SSK (although it's not set and unused anyways). + SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 15 * 4) = 0x7E; + } + + // This memset needs to happen here, else TZRAM will behave weirdly later on. + memset((void *)TZRAM_BASE, 0, 0x10000); + PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_ENABLE; + SE(SE_INT_STATUS_REG_OFFSET) = 0x1F; + + // Clear the boot reason to avoid problems later + PMC(APBDEV_PMC_SCRATCH200) = 0x0; + PMC(APBDEV_PMC_RST_STATUS) = 0x0; + APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) = (APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) & 0xF0) | (7 << 10); +} + +void _config_regulators() +{ + // Disable low battery shutdown monitor. + max77620_low_battery_monitor_config(false); + + // Disable SDMMC1 IO power. + gpio_output_enable(GPIO_PORT_E, GPIO_PIN_4, GPIO_OUTPUT_DISABLE); + max77620_regulator_enable(REGULATOR_LDO2, 0); + sd_power_cycle_time_start = get_tmr_ms(); + + 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) | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off. + +///////// not on mariko + // Configure all Flexible Power Sequencers. + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG0, + (7 << MAX77620_FPS_TIME_PERIOD_SHIFT)); + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG1, + (7 << MAX77620_FPS_TIME_PERIOD_SHIFT) | (1 << MAX77620_FPS_EN_SRC_SHIFT)); + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG2, + (7 << MAX77620_FPS_TIME_PERIOD_SHIFT)); + max77620_regulator_config_fps(REGULATOR_LDO4); + max77620_regulator_config_fps(REGULATOR_LDO8); + max77620_regulator_config_fps(REGULATOR_SD0); + max77620_regulator_config_fps(REGULATOR_SD1); + max77620_regulator_config_fps(REGULATOR_SD3); + + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_GPIO3, + (4 << MAX77620_FPS_TIME_PERIOD_SHIFT) | (2 << MAX77620_FPS_PD_PERIOD_SHIFT)); // 3.x+ +//////// + + // Set vdd_core voltage to 1.125V. + max77620_regulator_set_voltage(REGULATOR_SD0, 1125000); // 1050000 on mariko. + + //if (lite) + // ldo8 2.8V enable. + + // Fix CPU/GPU after a L4T warmboot. + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO5, 2); + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO6, 2); + + i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_0_95V); // Disable power. + i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_DVS_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_1_09V); // Enable DVS power. + i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL1_REG, MAX77621_RAMP_50mV_PER_US); + i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL2_REG, + MAX77621_T_JUNCTION_120 | MAX77621_FT_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS | + MAX77621_CKKADV_TRIP_150mV_PER_US | MAX77621_INDUCTOR_NOMINAL); + + i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_0_95V); // Disable power. + i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_VOUT_DVS_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_1_09V); // Enable DVS power. + i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_CONTROL1_REG, MAX77621_RAMP_50mV_PER_US); + i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_CONTROL2_REG, + MAX77621_T_JUNCTION_120 | MAX77621_FT_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS | + MAX77621_CKKADV_TRIP_150mV_PER_US | MAX77621_INDUCTOR_NOMINAL); +} + +void config_hw() +{ + // Bootrom stuff we skipped by going through rcm. + _config_se_brom(); + //FUSE(FUSE_PRIVATEKEYDISABLE) = 0x11; + SYSREG(AHB_AHB_SPARE_REG) &= 0xFFFFFF9F; // Unset APB2JTAG_OVERRIDE_EN and OBS_OVERRIDE_EN. + PMC(APBDEV_PMC_SCRATCH49) = PMC(APBDEV_PMC_SCRATCH49) & 0xFFFFFFFC; + + _mbist_workaround(); // not on mariko. + clock_enable_se(); + // CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SE) |= 0x100; // Lock clock. mariko. + + // Enable fuse clock. + clock_enable_fuse(true); + + // Disable fuse programming. + fuse_disable_program(); + + mc_enable(); + + _config_oscillators(); + APB_MISC(APB_MISC_PP_PINMUX_GLOBAL) = 0; + _config_gpios(); + +#ifdef DEBUG_UART_PORT + clock_enable_uart(DEBUG_UART_PORT); + uart_init(DEBUG_UART_PORT, 115200); +#endif + + clock_enable_cl_dvfs(); + + clock_enable_i2c(I2C_1); + clock_enable_i2c(I2C_5); + + clock_enable_tzram(); + + i2c_init(I2C_1); + i2c_init(I2C_5); + + _config_regulators(); + + _config_pmc_scratch(); // Missing from 4.x+ + + CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; // Set SCLK to PLLP_OUT (408MHz). + + // APBDEV_PMC_UNK_BE8 &= 0xFFFFFFFE; // mariko + // APBDEV_PMC_UNK_BF0 = 3; // mariko + // APBDEV_PMC_UNK_BEC = 3; // mariko + + sdram_init(); + + bpmp_mmu_enable(); + + // Clear flags from PMC_SCRATCH0 + PMC(APBDEV_PMC_SCRATCH0) &= ~PMC_SCRATCH0_MODE_PAYLOAD; +} + void reconfig_hw_workaround(bool extra_reconfig, u32 magic) { // Disable BPMP max clock. bpmp_clk_rate_set(BPMP_CLK_NORMAL); +#ifdef NYX // Deinit touchscreen, 5V regulators and Joy-Con. touch_power_off(); set_fan_duty(0); @@ -47,6 +354,7 @@ void reconfig_hw_workaround(bool extra_reconfig, u32 magic) regulator_disable_5v(REGULATOR_5V_ALL); clock_disable_uart(UART_B); clock_disable_uart(UART_C); +#endif // Flush/disable MMU cache and set DRAM clock to 204MHz. bpmp_mmu_disable(); diff --git a/nyx/nyx_gui/soc/hw_init.h b/nyx/nyx_gui/soc/hw_init.h index fe4defa..b92814b 100644 --- a/nyx/nyx_gui/soc/hw_init.h +++ b/nyx/nyx_gui/soc/hw_init.h @@ -1,4 +1,5 @@ /* + * Copyright (c) 2018 naehrwert * Copyright (c) 2018 CTCaer * * This program is free software; you can redistribute it and/or modify it @@ -19,6 +20,7 @@ #include "../utils/types.h" +void config_hw(); void reconfig_hw_workaround(bool extra_reconfig, u32 magic); #endif diff --git a/nyx/nyx_gui/soc/kfuse.c b/nyx/nyx_gui/soc/kfuse.c index a02acda..cdfba53 100644 --- a/nyx/nyx_gui/soc/kfuse.c +++ b/nyx/nyx_gui/soc/kfuse.c @@ -45,7 +45,7 @@ int kfuse_read(u32 *buf) res = 1; -out:; +out: clock_disable_kfuse(); return res; } diff --git a/nyx/nyx_gui/soc/uart.c b/nyx/nyx_gui/soc/uart.c index 2568d10..3aea2f7 100644 --- a/nyx/nyx_gui/soc/uart.c +++ b/nyx/nyx_gui/soc/uart.c @@ -79,7 +79,7 @@ void uart_send(u32 idx, const u8 *buf, u32 len) while (!(uart->UART_LSR & UART_LSR_THRE)) ; uart->UART_THR_DLAB = buf[i]; - }; + } } u32 uart_recv(u32 idx, u8 *buf, u32 len) diff --git a/nyx/nyx_gui/storage/nx_emmc.h b/nyx/nyx_gui/storage/nx_emmc.h index b3a90dc..380b7a0 100644 --- a/nyx/nyx_gui/storage/nx_emmc.h +++ b/nyx/nyx_gui/storage/nx_emmc.h @@ -22,7 +22,7 @@ #include "../utils/types.h" #include "../utils/list.h" -#define NX_GPT_FIRST_LBA 1 +#define NX_GPT_FIRST_LBA 1 #define NX_GPT_NUM_BLOCKS 33 #define NX_EMMC_BLOCKSIZE 512 diff --git a/nyx/nyx_gui/storage/sd.h b/nyx/nyx_gui/storage/sd.h index 3ecfc07..a780ec8 100644 --- a/nyx/nyx_gui/storage/sd.h +++ b/nyx/nyx_gui/storage/sd.h @@ -1,6 +1,4 @@ /* - * include/linux/mmc/sd.h - * * Copyright (c) 2005-2007 Pierre Ossman, All Rights Reserved. * Copyright (c) 2018 CTCaer * @@ -10,8 +8,8 @@ * your option) any later version. */ -#ifndef LINUX_MMC_SD_H -#define LINUX_MMC_SD_H +#ifndef MMC_SD_H +#define MMC_SD_H /* SD commands type argument response */ /* class 0 */ diff --git a/nyx/nyx_gui/storage/sdmmc_driver.c b/nyx/nyx_gui/storage/sdmmc_driver.c index 9f68bee..957a0bc 100644 --- a/nyx/nyx_gui/storage/sdmmc_driver.c +++ b/nyx/nyx_gui/storage/sdmmc_driver.c @@ -30,8 +30,14 @@ #include "../utils/util.h" //#define DPRINTF(...) gfx_printf(__VA_ARGS__) +//#define ERROR_EXTRA_PRINTING #define DPRINTF(...) +#ifdef NYX +#define ERROR_EXTRA_PRINTING +#define SDMMC_EMMC_OC +#endif + /*! SCMMC controller base addresses. */ static const u32 _sdmmc_bases[4] = { 0x700B0000, @@ -220,7 +226,11 @@ static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power) sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; } +#ifdef SDMMC_EMMC_OC static int _sdmmc_dll_cal_execute(sdmmc_t *sdmmc, bool overclock) +#else +static int _sdmmc_dll_cal_execute(sdmmc_t *sdmmc) +#endif { int result = 1, should_disable_sd_clock = 0; @@ -230,8 +240,10 @@ static int _sdmmc_dll_cal_execute(sdmmc_t *sdmmc, bool overclock) sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; } +#ifdef SDMMC_EMMC_OC if (sdmmc->id == SDMMC_4 && overclock) sdmmc->regs->vendllcalcfg = sdmmc->regs->vendllcalcfg &= 0xFFFFC07F | (0x7C << 7); // Add -4 TX_DLY_CODE_OFFSET if HS533. +#endif sdmmc->regs->vendllcalcfg |= TEGRA_MMC_DLLCAL_CFG_EN_CALIBRATE; _sdmmc_get_clkcon(sdmmc); @@ -347,8 +359,12 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type) if (type == SDHCI_TIMING_MMC_HS400) { +#ifdef SDMMC_EMMC_OC bool overclock_en = clock > 208000; return _sdmmc_dll_cal_execute(sdmmc, overclock_en); +#else + return _sdmmc_dll_cal_execute(sdmmc); +#endif } return 1; @@ -911,7 +927,9 @@ static int _sdmmc_update_dma(sdmmc_t *sdmmc) } if (result != SDMMC_MASKINT_NOERROR) { +#ifdef ERROR_EXTRA_PRINTING EPRINTFARGS("%08X!", result); +#endif _sdmmc_reset(sdmmc); return 0; } @@ -934,7 +952,9 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_ { if (!_sdmmc_config_dma(sdmmc, &blkcnt, req)) { - EPRINTF("DMA CFG Failed!"); +#ifdef ERROR_EXTRA_PRINTING + EPRINTF("SDMMC: DMA Wrong cfg!"); +#endif return 0; } @@ -950,14 +970,18 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_ if (!_sdmmc_send_cmd(sdmmc, cmd, is_data_present)) { - EPRINTFARGS("SDMMC: Wrong Response type %08X!\n", cmd->rsp_type); +#ifdef ERROR_EXTRA_PRINTING + EPRINTFARGS("SDMMC: Wrong Response type %08X!", cmd->rsp_type); +#endif return 0; } int result = _sdmmc_wait_response(sdmmc); if (!result) { +#ifdef ERROR_EXTRA_PRINTING EPRINTF("SDMMC: Transfer timeout!"); +#endif } DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result, sdmmc->regs->rspreg0, sdmmc->regs->rspreg1, sdmmc->regs->rspreg2, sdmmc->regs->rspreg3); @@ -969,7 +993,9 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_ result = _sdmmc_cache_rsp(sdmmc, sdmmc->rsp, 0x10, cmd->rsp_type); if (!result) { +#ifdef ERROR_EXTRA_PRINTING EPRINTFARGS("SDMMC: Unknown response %08X!", sdmmc->rsp[0]); +#endif } } if (req && result) @@ -977,7 +1003,9 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_ result = _sdmmc_update_dma(sdmmc); if (!result) { +#ifdef ERROR_EXTRA_PRINTING EPRINTF("SDMMC: DMA Update failed!"); +#endif } } } @@ -1003,7 +1031,9 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_ result = _sdmmc_wait_card_busy(sdmmc); if (!result) { +#ifdef ERROR_EXTRA_PRINTING EPRINTF("SDMMC: Busy timeout!"); +#endif } return result; } diff --git a/nyx/nyx_gui/utils/btn.c b/nyx/nyx_gui/utils/btn.c index 7ac35ef..b6e5db3 100644 --- a/nyx/nyx_gui/utils/btn.c +++ b/nyx/nyx_gui/utils/btn.c @@ -84,3 +84,31 @@ u8 btn_wait_timeout(u32 time_ms, u8 mask) return res; } + +u8 btn_wait_timeout_single(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(); + + while (get_tmr_ms() < timeout) + { + if ((res & mask) == mask) + { + if (single_button && (res & ~mask)) // Undesired button detected. + res = btn_read(); + else + return (res & mask); + } + else + res = btn_read(); + }; + + // Timed out. + if (!single_button || !time_ms) + return (res & mask); + else + return 0; // Return no button press if single button requested. +} diff --git a/nyx/nyx_gui/utils/btn.h b/nyx/nyx_gui/utils/btn.h index c0f0e08..1c42cc2 100644 --- a/nyx/nyx_gui/utils/btn.h +++ b/nyx/nyx_gui/utils/btn.h @@ -23,10 +23,12 @@ #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_read_vol(); u8 btn_wait(); u8 btn_wait_timeout(u32 time_ms, u8 mask); +u8 btn_wait_timeout_single(u32 time_ms, u8 mask); #endif