From a7712b173c8bd869c6a1f8ce49255263a9692101 Mon Sep 17 00:00:00 2001 From: shchmue Date: Wed, 12 May 2021 15:38:34 -0600 Subject: [PATCH] Update to hekate bdk 5.5.6 --- Makefile | 5 +- bdk/{gfx => display}/di.c | 52 ++- bdk/{gfx => display}/di.h | 12 +- bdk/{gfx => display}/di.inl | 0 bdk/ianos/ianos.c | 5 + bdk/input/als.c | 11 +- bdk/input/joycon.c | 137 ++++--- bdk/input/touch.c | 87 +++-- bdk/input/touch.h | 30 +- bdk/libs/compr/lz4.c | 25 +- bdk/libs/fatfs/diskio.h | 4 +- bdk/libs/fatfs/ff.c | 44 ++- bdk/libs/fatfs/ff.h | 8 +- bdk/libs/lv_conf.h | 2 +- bdk/libs/lvgl/lv_misc/lv_log.c | 2 +- bdk/mem/mc.c | 18 +- bdk/mem/minerva.c | 32 +- bdk/mem/minerva.h | 1 + bdk/mem/sdram.c | 27 +- bdk/mem/sdram.h | 10 +- bdk/mem/sdram_config.inl | 18 +- bdk/mem/sdram_config_t210b01.inl | 30 +- bdk/memory_map.h | 15 +- bdk/module.h | 5 + bdk/power/max77620.h | 244 +++++++----- bdk/power/max7762x.c | 308 +++++++++++---- bdk/power/max7762x.h | 116 +++--- bdk/power/max77812.h | 29 +- bdk/power/regulator_5v.c | 23 +- bdk/power/regulator_5v.h | 7 +- bdk/sec/se.c | 342 ++++++++--------- bdk/sec/se.h | 6 +- bdk/sec/se_t210.h | 637 ++++++++++++++----------------- bdk/sec/tsec.c | 14 +- bdk/soc/bpmp.c | 27 +- bdk/soc/bpmp.h | 5 +- bdk/soc/ccplex.c | 61 +-- bdk/soc/clock.c | 86 ++++- bdk/soc/clock.h | 164 +++++++- bdk/soc/fuse.c | 32 +- bdk/soc/fuse.h | 12 +- bdk/soc/hw_init.c | 93 +++-- bdk/soc/hw_init.h | 5 +- bdk/soc/i2c.c | 8 +- bdk/soc/irq.c | 14 +- bdk/soc/pmc.c | 60 ++- bdk/soc/pmc.h | 52 ++- bdk/soc/uart.c | 7 +- bdk/soc/uart.h | 11 + bdk/storage/mmc.h | 14 +- bdk/storage/nx_sd.h | 5 +- bdk/storage/ramdisk.c | 39 +- bdk/storage/ramdisk.h | 4 +- bdk/storage/sd.h | 115 +++--- bdk/storage/sdmmc.c | 390 ++++++++++--------- bdk/storage/sdmmc.h | 48 ++- bdk/storage/sdmmc_driver.c | 42 +- bdk/storage/sdmmc_driver.h | 2 +- bdk/thermal/fan.c | 22 +- bdk/thermal/tmp451.c | 24 +- bdk/thermal/tmp451.h | 4 + bdk/usb/usb_gadget_hid.c | 2 +- bdk/usb/usb_gadget_ums.c | 197 +++++----- bdk/usb/usb_t210.h | 1 + bdk/usb/usbd.c | 26 +- bdk/usb/usbd.h | 14 +- bdk/usb/xusbd.c | 40 +- bdk/utils/btn.c | 2 +- bdk/utils/dirlist.c | 10 +- bdk/utils/ini.c | 9 +- bdk/utils/sprintf.c | 2 +- bdk/utils/sprintf.h | 2 +- bdk/utils/types.h | 5 +- bdk/utils/util.c | 85 +++-- bdk/utils/util.h | 29 +- source/config.c | 1 + source/config.h | 1 + source/gfx/gfx.c | 43 ++- source/gfx/gfx.h | 7 +- source/gfx/tui.c | 4 +- source/hos/fss.c | 2 +- source/hos/hos.h | 26 +- source/hos/pkg1.c | 4 +- source/hos/sept.c | 2 +- source/keys/keys.c | 45 ++- source/libs/fatfs/ffconf.h | 2 +- source/link.ld | 3 +- source/main.c | 79 ++-- source/start.S | 6 +- source/storage/emummc.c | 31 +- source/storage/emummc.h | 12 +- source/storage/nx_emmc.c | 30 +- source/storage/nx_emmc.h | 7 +- source/storage/nx_emmc_bis.c | 11 +- source/storage/nx_sd.c | 12 +- 95 files changed, 2720 insertions(+), 1684 deletions(-) rename bdk/{gfx => display}/di.c (95%) rename bdk/{gfx => display}/di.h (98%) rename bdk/{gfx => display}/di.inl (100%) diff --git a/Makefile b/Makefile index c32db7e..a7efda8 100644 --- a/Makefile +++ b/Makefile @@ -45,8 +45,11 @@ CUSTOMDEFINES += -DGFX_INC=$(GFX_INC) -DFFCFG_INC=$(FFCFG_INC) #CUSTOMDEFINES += -DDEBUG +#TODO: Considering reinstating some of these when pointer warnings have been fixed. +WARNINGS := -Wall -Wno-array-bounds -Wno-stringop-overread -Wno-stringop-overflow + ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork -CFLAGS = $(ARCH) -Os -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 -Wall $(CUSTOMDEFINES) +CFLAGS = $(ARCH) -Os -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 $(WARNINGS) $(CUSTOMDEFINES) LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=IPL_LOAD_ADDR=$(IPL_LOAD_ADDR) ################################################################################ diff --git a/bdk/gfx/di.c b/bdk/display/di.c similarity index 95% rename from bdk/gfx/di.c rename to bdk/display/di.c index 9d95349..1c79823 100644 --- a/bdk/gfx/di.c +++ b/bdk/display/di.c @@ -20,6 +20,7 @@ #include "di.h" #include #include +#include #include #include #include @@ -170,9 +171,9 @@ int display_dsi_read(u8 cmd, u32 len, void *data, bool video_enabled) void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled) { + u8 *fifo8; + u32 *fifo32; u32 host_control; - u32 fifo32[DSI_STATUS_RX_FIFO_SIZE] = {0}; - u8 *fifo8 = (u8 *)fifo32; // Enable host cmd packets during video and save host control. if (video_enabled) @@ -193,6 +194,8 @@ void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled) break; default: + fifo32 = calloc(DSI_STATUS_RX_FIFO_SIZE * 8, 4); + fifo8 = (u8 *)fifo32; fifo32[0] = (len << 8) | MIPI_DSI_DCS_LONG_WRITE; fifo8[4] = cmd; memcpy(&fifo8[5], data, len); @@ -200,6 +203,7 @@ void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled) for (u32 i = 0; i < (ALIGN(len, 4) / 4); i++) DSI(_DSIREG(DSI_WR_DATA)) = fifo32[i]; DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST; + free(fifo32); break; } @@ -215,29 +219,30 @@ void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled) void display_init() { // Check if display is already initialized. - if (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) & BIT(CLK_L_DISP1)) + if (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & BIT(CLK_L_DISP1)) _display_panel_and_hw_end(true); // Get Chip ID. bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210; - // T210B01: Power on SD2 regulator for supplying LD0. + // T210B01: Power on SD2 regulator for supplying LDO0. if (!tegra_t210) { // Set SD2 regulator voltage. - max77620_regulator_set_voltage(REGULATOR_SD2, 1325000); + max7762x_regulator_set_voltage(REGULATOR_SD2, 1325000); // Set slew rate and enable SD2 regulator. i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD2_CFG, (1 << MAX77620_SD_SR_SHIFT) | MAX77620_SD_CFG1_FSRADE_SD_ENABLE); - max77620_regulator_enable(REGULATOR_SD2, 1); + max7762x_regulator_enable(REGULATOR_SD2, true); } // Enable power to display panel controller. - max77620_regulator_set_volt_and_flags(REGULATOR_LDO0, 1200000, MAX77620_POWER_MODE_NORMAL); // Configure to 1.2V. + max7762x_regulator_set_voltage(REGULATOR_LDO0, 1200000); + max7762x_regulator_enable(REGULATOR_LDO0, true); + if (tegra_t210) - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO7, - MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH | MAX77620_CNFG_GPIO_DRV_PUSHPULL); // T210: LD0 -> GPIO7 -> Display panel. + max77620_config_gpio(7, MAX77620_GPIO_OUTPUT_ENABLE); // T210: LD0 -> GPIO7 -> Display panel. // Enable Display Interface specific clocks. CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI); @@ -293,7 +298,7 @@ void display_init() // Set DISP1 clock source and parent clock. CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DISP1) = 0x40000000; // PLLD_OUT. - u32 plld_div = (3 << 20) | (20 << 11) | 1; // DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 96 MHz. + u32 plld_div = (3 << 20) | (20 << 11) | 1; // DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 97.5 MHz (offset). CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div; if (tegra_t210) @@ -335,9 +340,12 @@ void display_init() #if 0 // Get Display ID. - _display_id = 0xCCCCCC; + _display_id = 0xCCCCCC; // Set initial value. 4th byte cleared. display_dsi_read(MIPI_DCS_GET_DISPLAY_ID, 3, &_display_id, DSI_VIDEO_DISABLED); #else + // Drain RX FIFO. + _display_dsi_read_rx_fifo(NULL); + // Set reply size. _display_dsi_send_cmd(MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, 3, 0); _display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO); @@ -407,11 +415,11 @@ void display_init() _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_SET_DISPLAY_ON, 20000); // Configure PLLD for DISP1. - plld_div = (1 << 20) | (24 << 11) | 1; // DIVM: 1, DIVN: 24, DIVP: 1. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 230.4 MHz. + plld_div = (1 << 20) | (24 << 11) | 1; // DIVM: 1, DIVN: 24, DIVP: 1. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 234 MHz (offset). CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div; if (tegra_t210) - CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0x20; // PLLD_SETUP + CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0x20; // PLLD_SETUP. else CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0; CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = 0x2DFC00; // Use new PLLD_SDM_DIN. @@ -420,7 +428,7 @@ void display_init() DSI(_DSIREG(DSI_PAD_CONTROL_1)) = 0; DSI(_DSIREG(DSI_PHY_TIMING_0)) = tegra_t210 ? 0x6070601 : 0x6070603; exec_cfg((u32 *)DSI_BASE, _display_dsi_packet_config, 19); - // Set pixel clock dividers: 230.4 / 3 / 1 = 76.8 MHz. 60 Hz. + // Set pixel clock dividers: 234 / 3 / 1 = 78 MHz (offset) for 60 Hz. DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4); // 4: div3. exec_cfg((u32 *)DSI_BASE, _display_dsi_mode_config, 10); usleep(10000); @@ -499,6 +507,11 @@ void display_backlight_brightness(u32 brightness, u32 step_delay) PWM(PWM_CONTROLLER_PWM_CSR_0) = 0; } +u32 display_get_backlight_brightness() +{ + return ((PWM(PWM_CONTROLLER_PWM_CSR_0) >> 16) & 0xFF); +} + static void _display_panel_and_hw_end(bool no_panel_deinit) { if (no_panel_deinit) @@ -600,11 +613,20 @@ skip_panel_deinit: void display_end() { _display_panel_and_hw_end(false); }; -u16 display_get_decoded_lcd_id() +u16 display_get_decoded_panel_id() { return _display_id; } +void display_set_decoded_panel_id(u32 id) +{ + // Decode Display ID. + _display_id = ((id >> 8) & 0xFF00) | (id & 0xFF); + + if ((_display_id & 0xFF) == PANEL_JDI_XXX062M) + _display_id = PANEL_JDI_XXX062M; +} + void display_color_screen(u32 color) { exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_one_color, 8); diff --git a/bdk/gfx/di.h b/bdk/display/di.h similarity index 98% rename from bdk/gfx/di.h rename to bdk/display/di.h index e304fb6..7682bdb 100644 --- a/bdk/gfx/di.h +++ b/bdk/display/di.h @@ -650,7 +650,9 @@ * [10] 81 [26]: JDI LPM062M326A * [10] 96 [09]: JDI LAM062M109A * [20] 93 [0F]: InnoLux P062CCA-AZ1 (Rev A1) - * [20] 95 [0F]: InnoLux P062CCA-AZ2 + * [20] 95 [0F]: InnoLux P062CCA-AZ2 (Rev B1) + * [20] 96 [0F]: InnoLux P062CCA-AZ3 [UNCONFIRMED MODEL REV] + * [20] 98 [0F]: InnoLux P062CCA-??? [UNCONFIRMED MODEL REV] * [30] 94 [0F]: AUO A062TAN01 (59.06A33.001) * [30] 95 [0F]: AUO A062TAN02 (59.06A33.002) * @@ -671,10 +673,12 @@ * 20h: InnoLux Corporation * 30h: AU Optronics * 40h: Unknown1 + * 50h: Unknown2 (OLED? Samsung? LG?) * * Boards, Panel Size: * 0Fh: Icosa/Iowa, 6.2" * 10h: Hoag, 5.5" + * 20h: Unknown, x.x" */ enum @@ -693,8 +697,9 @@ void display_init(); void display_backlight_pwm_init(); void display_end(); -/*! Get Display panel ID. */ -u16 display_get_decoded_lcd_id(); +/*! Get/Set Display panel ID. */ +u16 display_get_decoded_panel_id(); +void display_set_decoded_panel_id(u32 id); /*! Show one single color on the display. */ void display_color_screen(u32 color); @@ -702,6 +707,7 @@ void display_color_screen(u32 color); /*! Switches screen backlight ON/OFF. */ void display_backlight(bool enable); void display_backlight_brightness(u32 brightness, u32 step_delay); +u32 display_get_backlight_brightness(); /*! Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */ u32 *display_init_framebuffer_pitch(); diff --git a/bdk/gfx/di.inl b/bdk/display/di.inl similarity index 100% rename from bdk/gfx/di.inl rename to bdk/display/di.inl diff --git a/bdk/ianos/ianos.c b/bdk/ianos/ianos.c index 5eca1b6..8deca45 100644 --- a/bdk/ianos/ianos.c +++ b/bdk/ianos/ianos.c @@ -21,6 +21,7 @@ #include "elfload/elfload.h" #include #include +#include #include #include @@ -43,6 +44,10 @@ static void _ianos_call_ep(moduleEntrypoint_t entrypoint, void *moduleConfig) bdkParameters->memset = (memset_t)&memset; bdkParameters->sharedHeap = &_heap; + // Extra functions. + bdkParameters->extension_magic = IANOS_EXT0; + bdkParameters->reg_voltage_set = (reg_voltage_set_t)&max7762x_regulator_set_voltage; + entrypoint(moduleConfig, bdkParameters); } diff --git a/bdk/input/als.c b/bdk/input/als.c index 97d6432..918661b 100644 --- a/bdk/input/als.c +++ b/bdk/input/als.c @@ -17,7 +17,6 @@ */ #include "als.h" -#include #include #include #include @@ -98,14 +97,16 @@ void get_als_lux(als_table_t *als_val) u8 als_init(als_table_t *als_val) { + // Enable power to ALS IC. + max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000); + max7762x_regulator_enable(REGULATOR_LDO6, true); + + // Init I2C2. pinmux_config_i2c(I2C_2); clock_enable_i2c(I2C_2); i2c_init(I2C_2); - max77620_regulator_set_volt_and_flags(REGULATOR_LDO6, 2900000, MAX77620_POWER_MODE_NORMAL); - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_LDO6_CFG2, - (MAX77620_POWER_MODE_NORMAL << MAX77620_LDO_POWER_MODE_SHIFT | (3 << 3) | MAX77620_LDO_CFG2_ADE_ENABLE)); - + // Initialize ALS. u8 id = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(0x12)); i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_SPEC(BH1730_SPECCMD_RESET), 0); i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_GAIN_REG), HOS_GAIN); diff --git a/bdk/input/joycon.c b/bdk/input/joycon.c index 9a3e11a..825e347 100644 --- a/bdk/input/joycon.c +++ b/bdk/input/joycon.c @@ -1,7 +1,7 @@ /* * Joy-Con UART driver for Nintendo Switch * - * Copyright (c) 2019 CTCaer + * Copyright (c) 2019-2021 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -39,6 +39,9 @@ #define JC_WIRED_INIT_REPLY 0x94 #define JC_INIT_HANDSHAKE 0xA5 +#define JC_HORI_INPUT_RPT_CMD 0x9A +#define JC_HORI_INPUT_RPT 0x00 + #define JC_WIRED_CMD_MAC 0x01 #define JC_WIRED_CMD_10 0x10 @@ -61,8 +64,12 @@ #define JC_BTN_MASK_L 0xFF2900 // 0xFFE900: with charge status. #define JC_BTN_MASK_R 0x0056FF -#define JC_ID_L 1 -#define JC_ID_R 2 +#define JC_ID_L 0x01 +#define JC_ID_R 0x02 +#define JC_ID_HORI 0x20 + +#define JC_CRC8_INIT 0x00 +#define JC_CRC8_POLY 0x8D enum { @@ -80,25 +87,31 @@ static const u8 init_jc[] = { static const u8 init_handshake[] = { 0x19, 0x01, 0x03, 0x07, 0x00, // Uart header. JC_INIT_HANDSHAKE, 0x02, // Wired cmd and wired subcmd. - 0x01, 0x7E, 0x00, 0x00, 0x00 // Wired subcmd data. + 0x01, 0x7E, 0x00, 0x00, 0x00 // Wired subcmd data and crc. }; static const u8 init_get_info[] = { 0x19, 0x01, 0x03, 0x07, 0x00, // Uart header. JC_WIRED_CMD, JC_WIRED_CMD_MAC, // Wired cmd and subcmd. - 0x00, 0x00, 0x00, 0x00, 0x24 // Wired subcmd data. + 0x00, 0x00, 0x00, 0x00, 0x24 // Wired subcmd data and crc. }; -static const u8 init_finilize[] = { +static const u8 init_finalize[] = { 0x19, 0x01, 0x03, 0x07, 0x00, // Uart header. JC_WIRED_CMD, JC_WIRED_CMD_10, // Wired cmd and subcmd. - 0x00, 0x00, 0x00, 0x00, 0x3D // Wired subcmd data. + 0x00, 0x00, 0x00, 0x00, 0x3D // Wired subcmd data and crc. }; static const u8 nx_pad_status[] = { 0x19, 0x01, 0x03, 0x08, 0x00, // Uart header. JC_WIRED_HID, 0x00, // Wired cmd and hid cmd. - 0x01, 0x00, 0x00, 0x69, 0x2D, 0x1F // hid data. + 0x01, 0x00, 0x00, 0x69, 0x2D, 0x1F // hid data and crc. +}; + +static const u8 hori_pad_status[] = { + 0x19, 0x01, 0x03, 0x07, 0x00, // Uart header. + JC_HORI_INPUT_RPT_CMD, 0x01, // Hori cmd and hori subcmd. + 0x00, 0x00, 0x00, 0x00, 0x48 // Hori cmd data and crc. }; typedef struct _jc_uart_hdr_t @@ -185,8 +198,8 @@ typedef struct _joycon_ctxt_t u8 connected; } joycon_ctxt_t; -static joycon_ctxt_t jc_l; -static joycon_ctxt_t jc_r; +static joycon_ctxt_t jc_l = {0}; +static joycon_ctxt_t jc_r = {0}; static bool jc_init_done = false; static u32 hid_pkt_inc = 0; @@ -195,13 +208,29 @@ static jc_gamepad_rpt_t jc_gamepad; void jc_power_supply(u8 uart, bool enable); +static u8 jc_crc(u8 *data, u16 len) +{ + u8 crc = JC_CRC8_INIT; + u16 i, j; + for (i = 0; i < len; i++) { + crc ^= data[i]; + for (j = 0; j < 8; j++) { + if ((crc & 0x80) != 0) + crc = (u8)((crc << 1) ^ JC_CRC8_POLY); + else + crc <<= 1; + } + } + return crc; +} + void joycon_send_raw(u8 uart_port, const u8 *buf, u16 size) { uart_send(uart_port, buf, size); uart_wait_idle(uart_port, UART_TX_IDLE); } -static u16 jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, u16 size) +static u16 jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, u16 size, bool crc) { out->uart_hdr.magic[0] = 0x19; out->uart_hdr.magic[1] = 0x01; @@ -214,14 +243,14 @@ static u16 jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, u if (data) memcpy(out->data, data, size); - out->crc = 0; // wired crc8ccit can be skipped. + out->crc = crc ? jc_crc(&out->uart_hdr.total_size_msb, sizeof(out->uart_hdr.total_size_msb) + sizeof(out->cmd) + sizeof(out->data)) : 0; return sizeof(jc_wired_hdr_t); } -static u16 jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, u8 *payload, u16 size) +static u16 jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, u8 *payload, u16 size, bool crc) { - u16 pkt_size = jc_packet_add_uart_hdr(rpt, JC_WIRED_HID, NULL, 0); + u16 pkt_size = jc_packet_add_uart_hdr(rpt, JC_WIRED_HID, NULL, 0, crc); pkt_size += size; rpt->uart_hdr.total_size_lsb += size; @@ -234,12 +263,12 @@ static u16 jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, u8 *payload, u16 size) return pkt_size; } -void jc_send_hid_output_rpt(u8 uart, u8 *payload, u16 size) +void jc_send_hid_output_rpt(u8 uart, u8 *payload, u16 size, bool crc) { u8 rpt[0x50]; memset(rpt, 0, sizeof(rpt)); - u32 rpt_size = jc_hid_output_rpt_craft((jc_wired_hdr_t *)rpt, payload, size); + u32 rpt_size = jc_hid_output_rpt_craft((jc_wired_hdr_t *)rpt, payload, size, crc); joycon_send_raw(uart, rpt, rpt_size); } @@ -275,18 +304,18 @@ void jc_send_hid_cmd(u8 uart, u8 subcmd, u8 *data, u16 size) hid_pkt->subcmd = JC_HID_SUBCMD_RUMBLE_CTL; hid_pkt->subcmd_data[0] = 1; if (send_r_rumble) - jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10); + jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10, false); if (send_l_rumble) - jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10); + jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10, false); // Send rumble. hid_pkt->cmd = JC_HID_RUMBLE_RPT; hid_pkt->pkt_id = jc_hid_pkt_id_incr(); memcpy(hid_pkt->rumble, rumble_init, sizeof(rumble_init)); if (send_r_rumble) - jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 10); + jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 10, false); if (send_l_rumble) - jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 10); + jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 10, false); msleep(15); @@ -297,21 +326,21 @@ void jc_send_hid_cmd(u8 uart, u8 subcmd, u8 *data, u16 size) hid_pkt->subcmd_data[0] = 0; memcpy(hid_pkt->rumble, rumble_neutral, sizeof(rumble_neutral)); if (send_r_rumble) - jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10); + jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10, false); if (send_l_rumble) - jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10); + jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10, false); } else { + bool crc_needed = (jc_l.uart == uart) ? (jc_l.type & JC_ID_HORI) : (jc_r.type & JC_ID_HORI); + hid_pkt->cmd = JC_HID_OUTPUT_RPT; hid_pkt->pkt_id = jc_hid_pkt_id_incr(); hid_pkt->subcmd = subcmd; if (data) memcpy(hid_pkt->subcmd_data, data, size); - u8 pkt_size = sizeof(jc_hid_out_rpt_t) + size; - - jc_send_hid_output_rpt(uart, (u8 *)hid_pkt, pkt_size); + jc_send_hid_output_rpt(uart, (u8 *)hid_pkt, sizeof(jc_hid_out_rpt_t) + size, crc_needed); } } @@ -333,6 +362,7 @@ static void jc_parse_wired_hid(joycon_ctxt_t *jc, const u8* packet, u32 size) switch (hid_pkt->cmd) { + case JC_HORI_INPUT_RPT: case JC_HID_INPUT_RPT: btn_tmp = hid_pkt->btn_right | hid_pkt->btn_shared << 8 | hid_pkt->btn_left << 16; @@ -412,6 +442,7 @@ static void jc_uart_pkt_parse(joycon_ctxt_t *jc, const u8* packet, size_t size) jc_wired_hdr_t *pkt = (jc_wired_hdr_t *)packet; switch (pkt->cmd) { + case JC_HORI_INPUT_RPT_CMD: case JC_WIRED_HID: jc_parse_wired_hid(jc, pkt->payload, (pkt->data[0] << 8) | pkt->data[1]); break; @@ -432,7 +463,7 @@ static void jc_rcv_pkt(joycon_ctxt_t *jc) // Check if device stopped sending data. u32 uart_irq = uart_get_IIR(jc->uart); - if ((uart_irq & 0x8) != 0x8) + if (uart_irq != UART_IIR_REDI) return; u32 len = uart_recv(jc->uart, (u8 *)jc->buf, 0x100); @@ -474,10 +505,15 @@ static bool jc_send_init_rumble(joycon_ctxt_t *jc) static void jc_req_nx_pad_status(joycon_ctxt_t *jc) { - bool sent_rumble = jc_send_init_rumble(jc); + bool is_nxpad = !(jc->type & JC_ID_HORI); - if (sent_rumble) - return; + if (is_nxpad) + { + bool sent_rumble = jc_send_init_rumble(jc); + + if (sent_rumble) + return; + } if (jc->last_status_req_time > get_tmr_ms() || !jc->connected) return; @@ -488,7 +524,10 @@ static void jc_req_nx_pad_status(joycon_ctxt_t *jc) else gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO); - joycon_send_raw(jc->uart, nx_pad_status, sizeof(nx_pad_status)); + if (is_nxpad) + joycon_send_raw(jc->uart, nx_pad_status, sizeof(nx_pad_status)); + else + joycon_send_raw(jc->uart, hori_pad_status, sizeof(hori_pad_status)); // Turn Joy-Con detect on. if (jc->uart == UART_B) @@ -655,24 +694,31 @@ retry: void jc_deinit() { + // Disable power. + jc_power_supply(UART_B, false); + jc_power_supply(UART_C, false); + + // Turn off Joy-Con detect. gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO); gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO); + // Send sleep command. u8 data = HCI_STATE_SLEEP; - if (jc_r.connected) + if (jc_r.connected && !(jc_r.type & JC_ID_HORI)) { jc_send_hid_cmd(UART_B, JC_HID_SUBCMD_HCI_STATE, &data, 1); jc_rcv_pkt(&jc_r); } - if (jc_l.connected) + if (jc_l.connected && !(jc_l.type & JC_ID_HORI)) { jc_send_hid_cmd(UART_C, JC_HID_SUBCMD_HCI_STATE, &data, 1); jc_rcv_pkt(&jc_l); } - jc_power_supply(UART_B, false); - jc_power_supply(UART_C, false); + // Disable UART B and C clocks. + clock_disable_uart(UART_B); + clock_disable_uart(UART_C); } static void jc_init_conn(joycon_ctxt_t *jc) @@ -709,9 +755,12 @@ static void jc_init_conn(joycon_ctxt_t *jc) msleep(5); jc_rcv_pkt(jc); - joycon_send_raw(jc->uart, init_finilize, sizeof(init_finilize)); - msleep(5); - jc_rcv_pkt(jc); + if (!(jc->type & JC_ID_HORI)) + { + joycon_send_raw(jc->uart, init_finalize, sizeof(init_finalize)); + msleep(5); + jc_rcv_pkt(jc); + } // Turn Joy-Con detect on. if (jc->uart == UART_B) @@ -766,10 +815,10 @@ void jc_power_supply(u8 uart, bool enable) { if (enable) { - if (regulator_get_5v_dev_enabled(1 << uart)) + if (regulator_5v_get_dev_enabled(1 << uart)) return; - regulator_enable_5v(1 << uart); + regulator_5v_enable(1 << uart); if (jc_init_done) { @@ -799,10 +848,10 @@ void jc_power_supply(u8 uart, bool enable) } else { - if (!regulator_get_5v_dev_enabled(1 << uart)) + if (!regulator_5v_get_dev_enabled(1 << uart)) return; - regulator_disable_5v(1 << uart); + regulator_5v_disable(1 << uart); if (uart == UART_C) gpio_write(GPIO_PORT_CC, GPIO_PIN_3, GPIO_LOW); @@ -816,10 +865,10 @@ void jc_init_hw() jc_l.uart = UART_C; jc_r.uart = UART_B; +#if !defined(DEBUG_UART_PORT) || !(DEBUG_UART_PORT) if (fuse_read_hw_type() == FUSE_NX_HW_TYPE_HOAG) return; -#ifndef DEBUG_UART_PORT jc_power_supply(UART_C, true); jc_power_supply(UART_B, true); @@ -836,14 +885,14 @@ void jc_init_hw() pinmux_config_uart(UART_C); // Ease the stress to APB. - bpmp_clk_rate_set(BPMP_CLK_NORMAL); + bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL); // Enable UART B and C clocks. clock_enable_uart(UART_B); clock_enable_uart(UART_C); // Restore OC. - bpmp_clk_rate_set(BPMP_CLK_DEFAULT_BOOST); + bpmp_clk_rate_set(prev_fid); // Turn Joy-Con detect on. gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO); diff --git a/bdk/input/touch.c b/bdk/input/touch.c index f24b53a..17d31b3 100644 --- a/bdk/input/touch.c +++ b/bdk/input/touch.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -34,6 +33,16 @@ #include #define DPRINTF(...) gfx_printf(__VA_ARGS__) +static touch_panel_info_t _panels[] = +{ + { 0, 1, 1, 1, "NISSHA NFT-K12D" }, + { 1, 0, 1, 1, "GiS GGM6 B2X" }, + { 2, 0, 0, 0, "NISSHA NBF-K9A" }, + { 3, 1, 0, 0, "GiS 5.5\"" }, + { 4, 0, 0, 1, "Unknown" }, + { -1, 1, 0, 1, "GiS VA 6.2\"" } +}; + static int touch_command(u8 cmd, u8 *buf, u8 size) { int res = i2c_send_buf_small(I2C_3, STMFTS_I2C_ADDR, cmd, buf, size); @@ -53,7 +62,7 @@ static int touch_read_reg(u8 *cmd, u32 csize, u8 *buf, u32 size) return 0; } -static int touch_wait_event(u8 event, u8 status, u32 timeout) +static int touch_wait_event(u8 event, u8 status, u32 timeout, u8 *buf) { u32 timer = get_tmr_ms() + timeout; while (true) @@ -61,7 +70,11 @@ static int touch_wait_event(u8 event, u8 status, u32 timeout) u8 tmp[8] = {0}; i2c_recv_buf_small(tmp, 8, I2C_3, STMFTS_I2C_ADDR, STMFTS_READ_ONE_EVENT); if (tmp[1] == event && tmp[2] == status) + { + if (buf) + memcpy(buf, &tmp[3], 5); return 0; + } if (get_tmr_ms() > timer) return 1; @@ -147,10 +160,10 @@ static void _touch_parse_event(touch_event *event) event->type = STMFTS_EV_MULTI_TOUCH_LEAVE; } - // gfx_con_setpos(&gfx_con, 0, 300); + // gfx_con_setpos(0, 300); // DPRINTF("x = %d \ny = %d \nz = %d \n", event->x, event->y, event->z); - // DPRINTF("0 = %02X\n1 = %02x\n2 = %02x\n3 = %02x\n", event->raw[0], event->raw[1], event->raw[2], event->raw[3]); - // DPRINTF("4 = %02X\n5 = %02x\n6 = %02x\n7 = %02x\n", event->raw[4], event->raw[5], event->raw[6], event->raw[7]); + // DPRINTF("0 = %02X\n1 = %02X\n2 = %02X\n3 = %02X\n", event->raw[0], event->raw[1], event->raw[2], event->raw[3]); + // DPRINTF("4 = %02X\n5 = %02X\n6 = %02X\n7 = %02X\n", event->raw[4], event->raw[5], event->raw[6], event->raw[7]); } void touch_poll(touch_event *event) @@ -183,16 +196,45 @@ touch_info touch_get_info() info.config_id = buf[4]; info.config_ver = buf[5]; - //DPRINTF("ID: %04X, FW Ver: %d.%02d\nCfg ID: %02x, Cfg Ver: %d\n", + //DPRINTF("ID: %04X, FW Ver: %d.%02d\nCfg ID: %02X, Cfg Ver: %d\n", // info.chip_id, info.fw_ver >> 8, info.fw_ver & 0xFF, info.config_id, info.config_ver); return info; } +touch_panel_info_t *touch_get_panel_vendor() +{ + u8 buf[5] = {0}; + u8 cmd = STMFTS_VENDOR_GPIO_STATE; + static touch_panel_info_t panel_info = { -2, 0, 0, 0, ""}; + + if (touch_command(STMFTS_VENDOR, &cmd, 1)) + return NULL; + + if (touch_wait_event(STMFTS_EV_VENDOR, STMFTS_VENDOR_GPIO_STATE, 2000, buf)) + return NULL; + + for (u32 i = 0; i < ARRAY_SIZE(_panels); i++) + { + touch_panel_info_t *panel = &_panels[i]; + if (buf[0] == panel->gpio0 && buf[1] == panel->gpio1 && buf[2] == panel->gpio2) + return panel; + } + + // Touch panel not found, return current gpios. + panel_info.gpio0 = buf[0]; + panel_info.gpio1 = buf[1]; + panel_info.gpio2 = buf[2]; + + return &panel_info; +} + int touch_get_fw_info(touch_fw_info_t *fw) { u8 buf[8] = {0}; + memset(fw, 0, sizeof(touch_fw_info_t)); + // Get fw address info. u8 cmd[3] = { STMFTS_RW_FRAMEBUFFER_REG, 0, 0x60 }; int res = touch_read_reg(cmd, 3, buf, 3); @@ -227,7 +269,7 @@ int touch_sys_reset() continue; } msleep(10); - if (touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20)) + if (touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20, NULL)) continue; else return 0; @@ -284,7 +326,7 @@ int touch_get_fb_info(u8 *buf) int res = 0; - for (u32 i = 0; i < 0x10000; i+=4) + for (u32 i = 0; i < 0x10000; i += 4) { if (!res) { @@ -301,9 +343,9 @@ int touch_get_fb_info(u8 *buf) int touch_sense_enable() { - // Enable auto tuning calibration and multi-touch sensing. - u8 cmd = 1; - if (touch_command(STMFTS_AUTO_CALIBRATION, &cmd, 1)) + // Switch sense mode and enable multi-touch sensing. + u8 cmd = STMFTS_FINGER_MODE; + if (touch_command(STMFTS_SWITCH_SENSE_MODE, &cmd, 1)) return 0; if (touch_command(STMFTS_MS_MT_SENSE_ON, NULL, 0)) @@ -329,19 +371,19 @@ int touch_execute_autotune() // Apply Mutual Sense Compensation tuning. if (touch_command(STMFTS_MS_CX_TUNING, NULL, 0)) return 0; - if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_MS_CX_TUNING_DONE, 2000)) + if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_MS_CX_TUNING_DONE, 2000, NULL)) return 0; // Apply Self Sense Compensation tuning. if (touch_command(STMFTS_SS_CX_TUNING, NULL, 0)) return 0; - if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_SS_CX_TUNING_DONE, 2000)) + if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_SS_CX_TUNING_DONE, 2000, NULL)) return 0; // Save Compensation data to EEPROM. if (touch_command(STMFTS_SAVE_CX_TUNING, NULL, 0)) return 0; - if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_WRITE_CX_TUNE_DONE, 2000)) + if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_WRITE_CX_TUNE_DONE, 2000, NULL)) return 0; return touch_sense_enable(); @@ -358,12 +400,11 @@ static int touch_init() int touch_power_on() { - // Enables LDO6 for touchscreen VDD/AVDD supply - max77620_regulator_set_volt_and_flags(REGULATOR_LDO6, 2900000, MAX77620_POWER_MODE_NORMAL); - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_LDO6_CFG2, - (MAX77620_POWER_MODE_NORMAL << MAX77620_LDO_POWER_MODE_SHIFT | (3 << 3) | MAX77620_LDO_CFG2_ADE_ENABLE)); + // Enable LDO6 for touchscreen AVDD supply. + max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000); + max7762x_regulator_enable(REGULATOR_LDO6, true); - // Configure touchscreen GPIO. + // Configure touchscreen VDD GPIO. PINMUX_AUX(PINMUX_AUX_DAP4_SCLK) = PINMUX_PULL_DOWN | 1; gpio_config(GPIO_PORT_J, GPIO_PIN_7, GPIO_MODE_GPIO); gpio_output_enable(GPIO_PORT_J, GPIO_PIN_7, GPIO_OUTPUT_ENABLE); @@ -377,7 +418,7 @@ int touch_power_on() // Configure Touscreen and GCAsic shared GPIO. PINMUX_AUX(PINMUX_AUX_CAM_I2C_SDA) = PINMUX_LPDR | PINMUX_INPUT_ENABLE | PINMUX_TRISTATE | PINMUX_PULL_UP | 2; PINMUX_AUX(PINMUX_AUX_CAM_I2C_SCL) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_TRISTATE | PINMUX_PULL_DOWN | 2; - gpio_config(GPIO_PORT_S, GPIO_PIN_3, GPIO_MODE_GPIO); + gpio_config(GPIO_PORT_S, GPIO_PIN_3, GPIO_MODE_GPIO); // GC detect. // Initialize I2C3. pinmux_config_i2c(I2C_3); @@ -385,7 +426,7 @@ int touch_power_on() i2c_init(I2C_3); // Wait for the touchscreen module to get ready. - touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20); + touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20, NULL); // Check for forced boot time calibration. if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN)) @@ -414,9 +455,7 @@ void touch_power_off() gpio_write(GPIO_PORT_J, GPIO_PIN_7, GPIO_LOW); // Disables LDO6 for touchscreen VDD, AVDD supply - max77620_regulator_enable(REGULATOR_LDO6, 0); - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_LDO6_CFG2, - MAX77620_LDO_CFG2_ADE_ENABLE | (2 << 3) | (MAX77620_POWER_MODE_NORMAL << MAX77620_LDO_POWER_MODE_SHIFT)); + max7762x_regulator_enable(REGULATOR_LDO6, false); clock_disable_i2c(I2C_3); } \ No newline at end of file diff --git a/bdk/input/touch.h b/bdk/input/touch.h index 9245be3..3345faa 100644 --- a/bdk/input/touch.h +++ b/bdk/input/touch.h @@ -47,19 +47,26 @@ #define STMFTS_ITO_CHECK 0xA7 #define STMFTS_RELEASEINFO 0xAA #define STMFTS_WRITE_REG 0xB6 -#define STMFTS_AUTO_CALIBRATION 0xC3 +#define STMFTS_SWITCH_SENSE_MODE 0xC3 #define STMFTS_NOISE_WRITE 0xC7 #define STMFTS_NOISE_READ 0xC8 #define STMFTS_RW_FRAMEBUFFER_REG 0xD0 #define STMFTS_SAVE_CX_TUNING 0xFC -#define STMFTS_UNK0 0xB8 //Request compensation -#define STMFTS_UNK1 0xCF -#define STMFTS_UNK2 0xF7 -#define STMFTS_UNK3 0xFA -#define STMFTS_UNK4 0xF9 +#define STMFTS_REQU_COMP_DATA 0xB8 +#define STMFTS_VENDOR 0xCF +#define STMFTS_FLASH_UNLOCK 0xF7 +#define STMFTS_FLASH_WRITE_64K 0xF8 +#define STMFTS_FLASH_STATUS 0xF9 +#define STMFTS_FLASH_OP 0xFA #define STMFTS_UNK5 0x62 +/* cmd parameters */ +#define STMFTS_VENDOR_GPIO_STATE 0x01 +#define STMFTS_VENDOR_SENSE_MODE 0x02 +#define STMFTS_STYLUS_MODE 0x00 +#define STMFTS_FINGER_MODE 0x01 +#define STMFTS_HOVER_MODE 0x02 /* events */ #define STMFTS_EV_NO_EVENT 0x00 @@ -74,6 +81,7 @@ #define STMFTS_EV_ERROR 0x0f #define STMFTS_EV_NOISE_READ 0x17 #define STMFTS_EV_NOISE_WRITE 0x18 +#define STMFTS_EV_VENDOR 0x20 #define STMFTS_EV_CONTROLLER_READY 0x10 #define STMFTS_EV_STATUS 0x16 @@ -131,6 +139,15 @@ typedef struct _touch_event { bool touch; } touch_event; +typedef struct _touch_panel_info_t +{ + u8 idx; + u8 gpio0; + u8 gpio1; + u8 gpio2; + char *vendor; +} touch_panel_info_t; + typedef struct _touch_info { u16 chip_id; u16 fw_ver; @@ -146,6 +163,7 @@ typedef struct _touch_fw_info_t { void touch_poll(touch_event *event); touch_event touch_poll_wait(); +touch_panel_info_t *touch_get_panel_vendor(); int touch_get_fw_info(touch_fw_info_t *fw); touch_info touch_get_info(); int touch_panel_ito_test(u8 *err); diff --git a/bdk/libs/compr/lz4.c b/bdk/libs/compr/lz4.c index ddea3d8..4f6f425 100644 --- a/bdk/libs/compr/lz4.c +++ b/bdk/libs/compr/lz4.c @@ -839,10 +839,12 @@ int LZ4_compress_fast_extState_fastReset(void* state, const char* src, char* dst int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) { int result; - LZ4_stream_t ctx; - LZ4_stream_t* const ctxPtr = &ctx; + LZ4_stream_t* ctx = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t)); + LZ4_stream_t* const ctxPtr = ctx; result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration); + FREEMEM(ctx); + return result; } @@ -857,13 +859,18 @@ int LZ4_compress_default(const char* source, char* dest, int inputSize, int maxO /* strangely enough, gcc generates faster code when this function is uncommented, even if unused */ int LZ4_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) { - LZ4_stream_t ctx; - LZ4_resetStream(&ctx); + int result; + LZ4_stream_t* ctx = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t)); + LZ4_resetStream(ctx); if (inputSize < LZ4_64Klimit) - return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); + result = LZ4_compress_generic(&ctx->internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); else - return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, sizeof(void*)==8 ? byU32 : byPtr, noDict, noDictIssue, acceleration); + result = LZ4_compress_generic(&ctx->internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, sizeof(void*)==8 ? byU32 : byPtr, noDict, noDictIssue, acceleration); + + FREEMEM(ctx); + + return result; } @@ -1045,11 +1052,13 @@ static int LZ4_compress_destSize_extState (LZ4_stream_t* state, const char* src, int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize) { - LZ4_stream_t ctxBody; - LZ4_stream_t* ctx = &ctxBody; + LZ4_stream_t* ctxBody = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));; + LZ4_stream_t* ctx = ctxBody; int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize); + FREEMEM(ctxBody); + return result; } diff --git a/bdk/libs/fatfs/diskio.h b/bdk/libs/fatfs/diskio.h index 6959fb4..b5299c6 100644 --- a/bdk/libs/fatfs/diskio.h +++ b/bdk/libs/fatfs/diskio.h @@ -27,7 +27,8 @@ typedef enum { DRIVE_SD = 0, DRIVE_RAM = 1, DRIVE_EMMC = 2, - DRIVE_BIS = 3 + DRIVE_BIS = 3, + DRIVE_EMU = 4 } DDRIVE; @@ -59,6 +60,7 @@ DRESULT disk_set_info (BYTE pdrv, BYTE cmd, void *buff); #define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */ #define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */ #define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */ +#define SET_SECTOR_OFFSET 5 /* Set media logical offset */ /* Generic command (Not used by FatFs) */ #define CTRL_POWER 5 /* Get/Set power status */ diff --git a/bdk/libs/fatfs/ff.c b/bdk/libs/fatfs/ff.c index 9035f35..75e0271 100644 --- a/bdk/libs/fatfs/ff.c +++ b/bdk/libs/fatfs/ff.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2019 CTCaer + * Copyright (c) 2018-2021 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -38,6 +38,7 @@ #include "ff.h" /* Declarations of FatFs API */ #include "diskio.h" /* Declarations of device I/O functions */ +#include #include #define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF); @@ -3284,6 +3285,7 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */ /* Following code attempts to mount the volume. (analyze BPB and initialize the filesystem object) */ fs->fs_type = 0; /* Clear the filesystem object */ + fs->part_type = 0; /* Clear the Partition object */ fs->pdrv = LD2PD(vol); /* Bind the logical drive and a physical drive */ stat = disk_initialize(fs->pdrv); /* Initialize the physical drive */ if (stat & STA_NOINIT) { /* Check if the initialization succeeded */ @@ -3318,6 +3320,20 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */ EFSPRINTF("BRNL"); return FR_DISK_ERR; /* An error occured in the disk I/O layer */ } +#if FF_SIMPLE_GPT + if (fmt >= 2) { + /* If GPT Check the first partition */ + gpt_header_t *gpt_header = (gpt_header_t *)fs->win; + if (move_window(fs, 1) != FR_OK) return FR_DISK_ERR; + if (!mem_cmp(&gpt_header->signature, "EFI PART", 8)) { + if (move_window(fs, gpt_header->part_ent_lba) != FR_OK) return FR_DISK_ERR; + gpt_entry_t *gpt_entry = (gpt_entry_t *)fs->win; + fs->part_type = 1; + bsect = gpt_entry->lba_start; + fmt = bsect ? check_fs(fs, bsect) : 3; /* Check the partition */ + } + } +#endif if (fmt >= 2) { EFSPRINTF("NOFAT"); return FR_NO_FILESYSTEM; /* No FAT volume is found */ @@ -6169,7 +6185,9 @@ FRESULT f_mkfs ( #endif /* Create FAT VBR */ mem_set(buf, 0, ss); - mem_cpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code (x86), OEM name */ + /* Boot jump code (x86), OEM name */ + if (!(opt & FM_PRF2)) mem_cpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "NYX1.0.0", 11); + else mem_cpy(buf + BS_JmpBoot, "\xEB\xE9\x90\x00\x00\x00\x00\x00\x00\x00\x00", 11); st_word(buf + BPB_BytsPerSec, ss); /* Sector size [byte] */ buf[BPB_SecPerClus] = (BYTE)pau; /* Cluster size [sector] */ st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv); /* Size of reserved area */ @@ -6182,23 +6200,27 @@ FRESULT f_mkfs ( } buf[BPB_Media] = 0xF8; /* Media descriptor byte */ st_word(buf + BPB_SecPerTrk, 63); /* Number of sectors per track (for int13) */ - st_word(buf + BPB_NumHeads, 255); /* Number of heads (for int13) */ + st_word(buf + BPB_NumHeads, (opt & FM_PRF2) ? 16 : 255); /* Number of heads (for int13) */ st_dword(buf + BPB_HiddSec, b_vol); /* Volume offset in the physical drive [sector] */ if (fmt == FS_FAT32) { - st_dword(buf + BS_VolID32, GET_FATTIME()); /* VSN */ + st_dword(buf + BS_VolID32, (opt & FM_PRF2) ? 0 : GET_FATTIME()); /* VSN */ st_dword(buf + BPB_FATSz32, sz_fat); /* FAT size [sector] */ st_dword(buf + BPB_RootClus32, 2); /* Root directory cluster # (2) */ st_word(buf + BPB_FSInfo32, 1); /* Offset of FSINFO sector (VBR + 1) */ st_word(buf + BPB_BkBootSec32, 6); /* Offset of backup VBR (VBR + 6) */ buf[BS_DrvNum32] = 0x80; /* Drive number (for int13) */ buf[BS_BootSig32] = 0x29; /* Extended boot signature */ - mem_cpy(buf + BS_VolLab32, "SWITCH SD " "FAT32 ", 19); /* Volume label, FAT signature */ + /* Volume label, FAT signature */ + if (!(opt & FM_PRF2)) mem_cpy(buf + BS_VolLab32, FF_MKFS_LABEL "FAT32 ", 19); + else mem_cpy(buf + BS_VolLab32, "NO NAME " "FAT32 ", 19); } else { st_dword(buf + BS_VolID, GET_FATTIME()); /* VSN */ st_word(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */ buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */ buf[BS_BootSig] = 0x29; /* Extended boot signature */ - mem_cpy(buf + BS_VolLab, "SWITCH SD " "FAT ", 19); /* Volume label, FAT signature */ + /* Volume label, FAT signature */ + if (!(opt & FM_PRF2)) mem_cpy(buf + BS_VolLab, FF_MKFS_LABEL "FAT ", 19); + else mem_cpy(buf + BS_VolLab, "NO NAME " "FAT ", 19); } st_word(buf + BS_55AA, 0xAA55); /* Signature (offset is fixed here regardless of sector size) */ if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the VBR sector */ @@ -6216,6 +6238,16 @@ FRESULT f_mkfs ( disk_write(pdrv, buf, b_vol + 1, 1); /* Write original FSINFO (VBR + 1) */ } + /* Create PRF2SAFE info */ + if (fmt == FS_FAT32 && opt & FM_PRF2) { + mem_set(buf, 0, ss); + buf[16] = 0x64; /* Record type */ + st_dword(buf + 32, 0x03); /* Unknown. SYSTEM: 0x3F00. USER: 0x03. Volatile. */ + st_dword(buf + 36, 25); /* Entries. SYSTEM: 22. USER: 25.Static? */ + st_dword(buf + 508, 0x517BBFE0); /* Custom CRC32. SYSTEM: 0x6B673904. USER: 0x517BBFE0. */ + disk_write(pdrv, buf, b_vol + 3, 1); /* Write PRF2SAFE info (VBR + 3) */ + } + /* Initialize FAT area */ mem_set(buf, 0, (UINT)szb_buf); sect = b_fat; /* FAT start sector */ diff --git a/bdk/libs/fatfs/ff.h b/bdk/libs/fatfs/ff.h index a83cf63..f8e3475 100644 --- a/bdk/libs/fatfs/ff.h +++ b/bdk/libs/fatfs/ff.h @@ -97,6 +97,7 @@ typedef DWORD FSIZE_t; typedef struct { BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ BYTE fs_type; /* Filesystem type (0:not mounted) */ + BYTE part_type; /* Partition type (0:MBR, 1:GPT) */ BYTE pdrv; /* Associated physical drive */ BYTE n_fats; /* Number of FATs (1 or 2) */ BYTE wflag; /* win[] flag (b0:dirty) */ @@ -168,9 +169,6 @@ typedef struct { /* File object structure (FIL) */ typedef struct { -#if !FF_FS_TINY - BYTE buf[FF_MAX_SS]; /* File private data read/write window */ -#endif FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */ BYTE flag; /* File status flags */ BYTE err; /* Abort flag (error code) */ @@ -184,6 +182,9 @@ typedef struct { #if FF_USE_FASTSEEK DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */ #endif +#if !FF_FS_TINY + BYTE buf[FF_MAX_SS] __attribute__((aligned(8))); /* File private data read/write window. DMA aligned. */ +#endif } FIL; @@ -365,6 +366,7 @@ int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */ #define FM_EXFAT 0x04 #define FM_ANY 0x07 #define FM_SFD 0x08 +#define FM_PRF2 0x10 /* Filesystem type (FATFS.fs_type) */ #define FS_FAT12 1 diff --git a/bdk/libs/lv_conf.h b/bdk/libs/lv_conf.h index dcc437d..7af36a4 100644 --- a/bdk/libs/lv_conf.h +++ b/bdk/libs/lv_conf.h @@ -155,7 +155,7 @@ /*Log settings*/ -#ifdef DEBUG_UART_PORT +#ifdef DEBUG_UART_LV_LOG # define USE_LV_LOG 1 /*Enable/disable the log module*/ #else # define USE_LV_LOG 0 /*Enable/disable the log module*/ diff --git a/bdk/libs/lvgl/lv_misc/lv_log.c b/bdk/libs/lvgl/lv_misc/lv_log.c index d2db0c7..9cd3d49 100644 --- a/bdk/libs/lvgl/lv_misc/lv_log.c +++ b/bdk/libs/lvgl/lv_misc/lv_log.c @@ -63,7 +63,7 @@ void lv_log_add(lv_log_level_t level, const char * file, int line, const char * if(level >= LV_LOG_LEVEL) { -#if LV_LOG_PRINTF +#if LV_LOG_PRINTF && defined(DEBUG_UART_PORT) static const char * lvl_prefix[] = {"Trace", "Info", "Warn", "Error"}; char *log = (char *)malloc(0x1000); s_printf(log, "%s: %s \t(%s #%d)\r\n", lvl_prefix[level], dsc, file, line); diff --git a/bdk/mem/mc.c b/bdk/mem/mc.c index cc136dc..4db3a30 100644 --- a/bdk/mem/mc.c +++ b/bdk/mem/mc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018 CTCaer + * Copyright (c) 2018-2020 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -20,6 +20,8 @@ #include #include +#define CONFIG_ENABLE_AHB_REDIRECT + void mc_config_tsec_carveout(u32 bom, u32 size1mb, bool lock) { MC(MC_SEC_CARVEOUT_BOM) = bom; @@ -143,17 +145,19 @@ void mc_disable_ahb_redirect() void mc_enable() { + // Reset EMC source to PLLP. CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF) | 0x40000000; // Enable memory clocks. - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & ~BIT(CLK_H_EMC)) | BIT(CLK_H_EMC); - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & ~BIT(CLK_H_MEM)) | BIT(CLK_H_MEM); - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) & ~BIT(CLK_X_EMC_DLL)) | BIT(CLK_X_EMC_DLL); + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_EMC); + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_MEM); + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = BIT(CLK_X_EMC_DLL); // Clear clock resets for memory. CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM); usleep(5); - //#ifdef CONFIG_ENABLE_AHB_REDIRECT +#ifdef CONFIG_ENABLE_AHB_REDIRECT + mc_enable_ahb_redirect(); +#else mc_disable_ahb_redirect(); - //mc_enable_ahb_redirect(); - //#endif +#endif } diff --git a/bdk/mem/minerva.c b/bdk/mem/minerva.c index 183b633..2560dfe 100644 --- a/bdk/mem/minerva.c +++ b/bdk/mem/minerva.c @@ -60,7 +60,7 @@ u32 minerva_init() 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.sdram_id = fuse_read_dramid(false); mtc_tmp.init_done = MTC_NEW_MAGIC; u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)&mtc_tmp); @@ -81,7 +81,7 @@ u32 minerva_init() // 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->sdram_id = fuse_read_dramid(false); mtc_cfg->init_done = MTC_NEW_MAGIC; // Initialize mtc table. u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)mtc_cfg); @@ -104,21 +104,21 @@ u32 minerva_init() } mtc_cfg->rate_from = mtc_cfg->mtc_table[curr_ram_idx].rate_khz; - mtc_cfg->rate_to = 204000; + mtc_cfg->rate_to = FREQ_204; mtc_cfg->train_mode = OP_TRAIN; minerva_cfg(mtc_cfg, NULL); - mtc_cfg->rate_to = 800000; + mtc_cfg->rate_to = FREQ_800; minerva_cfg(mtc_cfg, NULL); - mtc_cfg->rate_to = 1600000; + mtc_cfg->rate_to = FREQ_1600; minerva_cfg(mtc_cfg, NULL); // FSP WAR. mtc_cfg->train_mode = OP_SWITCH; - mtc_cfg->rate_to = 800000; + mtc_cfg->rate_to = FREQ_800; minerva_cfg(mtc_cfg, NULL); // Switch to max. - mtc_cfg->rate_to = 1600000; + mtc_cfg->rate_to = FREQ_1600; minerva_cfg(mtc_cfg, NULL); return 0; @@ -129,6 +129,7 @@ void minerva_change_freq(minerva_freq_t freq) if (!minerva_cfg) return; + // Check if requested frequency is different. Do not allow otherwise because it will hang. mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg; if (mtc_cfg->rate_from != freq) { @@ -138,6 +139,23 @@ void minerva_change_freq(minerva_freq_t freq) } } +void minerva_prep_boot_freq() +{ + if (!minerva_cfg) + return; + + mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg; + + // Check if there's RAM OC. If not exit. + if (mtc_cfg->mtc_table[mtc_cfg->table_entries - 1].rate_khz == FREQ_1600) + return; + + // FSP WAR. + minerva_change_freq(FREQ_204); + // Scale down to 800 MHz boot freq. + minerva_change_freq(FREQ_800); +} + void minerva_periodic_training() { if (!minerva_cfg) diff --git a/bdk/mem/minerva.h b/bdk/mem/minerva.h index ed80b95..51cb215 100644 --- a/bdk/mem/minerva.h +++ b/bdk/mem/minerva.h @@ -60,6 +60,7 @@ typedef enum extern void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *); u32 minerva_init(); void minerva_change_freq(minerva_freq_t freq); +void minerva_prep_boot_freq(); void minerva_periodic_training(); #endif diff --git a/bdk/mem/sdram.c b/bdk/mem/sdram.c index aad98db..b119f46 100644 --- a/bdk/mem/sdram.c +++ b/bdk/mem/sdram.c @@ -54,11 +54,6 @@ typedef struct _sdram_vendor_patch_t #include "sdram_config_t210b01.inl" -static u32 _sdram_get_id() -{ - return ((fuse_read_odm(4) & 0xF8) >> 3); -} - static bool _sdram_wait_emc_status(u32 reg_offset, u32 bit_mask, bool updated_state, s32 emc_channel) { bool err = true; @@ -1374,9 +1369,7 @@ static void _sdram_patch_model_params_t210b01(u32 dramid, u32 *params) static void *_sdram_get_params_t210() { // Check if id is proper. - u32 dramid = _sdram_get_id(); - if (dramid > 6) - dramid = 0; + u32 dramid = fuse_read_dramid(false); #ifdef CONFIG_SDRAM_COMPRESS_CFG @@ -1413,9 +1406,7 @@ static void *_sdram_get_params_t210() void *sdram_get_params_t210b01() { // Check if id is proper. - u32 dramid = _sdram_get_id(); - if (dramid > 27) - dramid = 8; + u32 dramid = fuse_read_dramid(false); u32 *buf = (u32 *)SDRAM_PARAMS_ADDR; memcpy(buf, &_dram_cfg_08_10_12_14_samsung_hynix_4gb, sizeof(sdram_params_t210b01_t)); @@ -1439,12 +1430,12 @@ void *sdram_get_params_t210b01() case LPDDR4X_HOAG_4GB_SAMSUNG_1Y_X: case LPDDR4X_IOWA_4GB_SAMSUNG_1Y_Y: case LPDDR4X_IOWA_8GB_SAMSUNG_1Y_Y: - case LPDDR4X_SDS_4GB_SAMSUNG_1Y_A: - case LPDDR4X_SDS_8GB_SAMSUNG_1Y_X: - case LPDDR4X_SDS_4GB_SAMSUNG_1Y_X: + case LPDDR4X_AULA_4GB_SAMSUNG_1Y_A: + case LPDDR4X_AULA_8GB_SAMSUNG_1Y_X: + case LPDDR4X_AULA_4GB_SAMSUNG_1Y_X: case LPDDR4X_IOWA_4GB_MICRON_1Y_A: case LPDDR4X_HOAG_4GB_MICRON_1Y_A: - case LPDDR4X_SDS_4GB_MICRON_1Y_A: + case LPDDR4X_AULA_4GB_MICRON_1Y_A: _sdram_patch_model_params_t210b01(dramid, (u32 *)buf); break; } @@ -1494,7 +1485,7 @@ static void _sdram_init_t210() const sdram_params_t210_t *params = (const sdram_params_t210_t *)_sdram_get_params_t210(); // Set DRAM voltage. - max77620_regulator_set_voltage(REGULATOR_SD1, 1100000); + max7762x_regulator_set_voltage(REGULATOR_SD1, 1100000); // VDDP Select. PMC(APBDEV_PMC_VDDP_SEL) = params->pmc_vddp_sel; @@ -1539,8 +1530,8 @@ static void _sdram_init_t210b01() void sdram_init() { - // Configure SD regulator for DRAM. - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, 0x05); + // Disable remote sense for SD1. + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, MAX77620_SD_CNF2_ROVS_EN_SD0 | MAX77620_SD_CNF2_RSVD); if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210) _sdram_init_t210(); diff --git a/bdk/mem/sdram.h b/bdk/mem/sdram.h index 77db819..8455862 100644 --- a/bdk/mem/sdram.h +++ b/bdk/mem/sdram.h @@ -45,7 +45,7 @@ enum sdram_ids_erista LPDDR4_ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH = 0, LPDDR4_ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 1, LPDDR4_ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WT = 2, - LPDDR4_COPPER_4GB_SAMSUNG_K4F6E304HB_MGCH = 3, + LPDDR4_COPPER_4GB_SAMSUNG_K4F6E304HB_MGCH = 3, // Changed to AULA Hynix 4GB 1Y-A. LPDDR4_ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH = 4, LPDDR4_COPPER_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 5, LPDDR4_COPPER_4GB_MICRON_MT53B512M32D2NP_062_WT = 6, @@ -76,14 +76,14 @@ enum sdram_ids_mariko LPDDR4X_IOWA_4GB_SAMSUNG_1Y_Y = 20, LPDDR4X_IOWA_8GB_SAMSUNG_1Y_Y = 21, - LPDDR4X_SDS_4GB_SAMSUNG_1Y_A = 22, + LPDDR4X_AULA_4GB_SAMSUNG_1Y_A = 22, - LPDDR4X_SDS_8GB_SAMSUNG_1Y_X = 23, - LPDDR4X_SDS_4GB_SAMSUNG_1Y_X = 24, + LPDDR4X_AULA_8GB_SAMSUNG_1Y_X = 23, + LPDDR4X_AULA_4GB_SAMSUNG_1Y_X = 24, LPDDR4X_IOWA_4GB_MICRON_1Y_A = 25, LPDDR4X_HOAG_4GB_MICRON_1Y_A = 26, - LPDDR4X_SDS_4GB_MICRON_1Y_A = 27 + LPDDR4X_AULA_4GB_MICRON_1Y_A = 27 }; void sdram_init(); diff --git a/bdk/mem/sdram_config.inl b/bdk/mem/sdram_config.inl index 727ec60..97c723a 100644 --- a/bdk/mem/sdram_config.inl +++ b/bdk/mem/sdram_config.inl @@ -97,7 +97,7 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = { * DRAM size information * Specifies the value for EMC_ADR_CFG */ - .emc_adr_cfg = 0x00000001, // 2 populated DRAM Devices. + .emc_adr_cfg = 0x00000001, // 2 Ranks. /* * Specifies the time to wait after asserting pin @@ -243,7 +243,7 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = { .emc_cfg_dig_dll = 0x002C00A0, .emc_cfg_dig_dll_1 = 0x00003701, .emc_cfg_dig_dll_period = 0x00008000, - .emc_dev_select = 0x00000000, // Both devices. + .emc_dev_select = 0x00000000, // Both Ranks. .emc_sel_dpd_ctrl = 0x00040008, /* Pads trimmer delays */ @@ -406,7 +406,7 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = { .pmc_ddr_ctrl = 0x0007FF8B, .emc_acpd_control = 0x00000000, - .emc_swizzle_rank0_byte0 = 0x76543201, + .emc_swizzle_rank0_byte0 = 0x76543201, // Overridden to 0x76543201 by spare6/7. .emc_swizzle_rank0_byte1 = 0x65324710, .emc_swizzle_rank0_byte2 = 0x25763410, .emc_swizzle_rank0_byte3 = 0x25673401, @@ -454,7 +454,7 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = { .emc_pmacro_data_rx_term_mode = 0x00000010, .emc_pmacro_cmd_rx_term_mode = 0x00003000, .emc_pmacro_data_pad_tx_ctrl = 0x02000111, - .emc_pmacro_common_pad_tx_ctrl = 0x00000008, + .emc_pmacro_common_pad_tx_ctrl = 0x00000008, // Overridden to 0x0000000A by spare4/5. .emc_pmacro_cmd_pad_tx_ctrl = 0x0A000000, .emc_cfg3 = 0x00000040, @@ -490,9 +490,9 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = { .emc_pmacro_cmd_ctrl2 = 0x0A0A0A0A, /* DRAM size information */ - .mc_emem_adr_cfg = 0x00000001, // 2 populated DRAM Devices. - .mc_emem_adr_cfg_dev0 = 0x00070302, // Density 512MB. - .mc_emem_adr_cfg_dev1 = 0x00070302, // Density 512MB. + .mc_emem_adr_cfg = 0x00000001, // 2 Ranks. + .mc_emem_adr_cfg_dev0 = 0x00070302, // Rank 0 Density 512MB. + .mc_emem_adr_cfg_dev1 = 0x00070302, // Rank 1 Density 512MB. .mc_emem_adr_cfg_channel_mask = 0xFFFF2400, .mc_emem_adr_cfg_bank_mask0 = 0x6E574400, .mc_emem_adr_cfg_bank_mask1 = 0x39722800, @@ -653,8 +653,8 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210[] = { { 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. + { 0x000C0302, 347, DRAM_ID(4) }, // mc_emem_adr_cfg_dev0. 768MB Rank 0 density. + { 0x000C0302, 348, DRAM_ID(4) }, // mc_emem_adr_cfg_dev1. 768MB Rank 1 density. { 0x00001800, 353, DRAM_ID(4) }, // mc_emem_cfg. 6GB total density. #ifdef CONFIG_SDRAM_COPPER_SUPPORT diff --git a/bdk/mem/sdram_config_t210b01.inl b/bdk/mem/sdram_config_t210b01.inl index 983c93a..e5c197e 100644 --- a/bdk/mem/sdram_config_t210b01.inl +++ b/bdk/mem/sdram_config_t210b01.inl @@ -122,7 +122,7 @@ static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = { * DRAM size information * Specifies the value for EMC_ADR_CFG */ - .emc_adr_cfg = 0x00000000, // 1 populated DRAM Device. + .emc_adr_cfg = 0x00000000, // 1 Rank. /* * Specifies the time to wait after asserting pin @@ -273,7 +273,7 @@ static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = { .emc_cfg_dig_dll = 0x002C00A0, .emc_cfg_dig_dll_1 = 0x000F3701, .emc_cfg_dig_dll_period = 0x00008000, - .emc_dev_select = 0x00000002, // Dev0 only. + .emc_dev_select = 0x00000002, // Rank 0 only. .emc_sel_dpd_ctrl = 0x0004000C, /* Pads trimmer delays */ @@ -543,9 +543,9 @@ static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = { .emc_pmacro_cmd_ctrl2 = 0x00000000, /* DRAM size information */ - .mc_emem_adr_cfg = 0x00000000, // 1 populated DRAM Device. - .mc_emem_adr_cfg_dev0 = 0x00080302, // Density 1024MB. - .mc_emem_adr_cfg_dev1 = 0x00080302, // Density 1024MB. + .mc_emem_adr_cfg = 0x00000000, // 1 Rank. + .mc_emem_adr_cfg_dev0 = 0x00080302, // Rank 0 Density 1024MB. + .mc_emem_adr_cfg_dev1 = 0x00080302, // Rank 1 Density 1024MB. .mc_emem_adr_cfg_channel_mask = 0xFFFF2400, .mc_emem_adr_cfg_bank_mask0 = 0x6E574400, .mc_emem_adr_cfg_bank_mask1 = 0x39722800, @@ -733,7 +733,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = { // Samsung LPDDR4X 8GB K4UBE3D4AM-MGCJ for SDEV Iowa and Hoag. { 0x05500000, 0x0D4 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_auto_cal_config2. { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_auto_cal_vref_sel0. - { 0x00000001, 0x134 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_adr_cfg. 2 populated DRAM Devices. + { 0x00000001, 0x134 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_adr_cfg. 2 Ranks. { 0x00000006, 0x1CC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_quse. { 0x00000005, 0x1D0 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_quse_width. { 0x00000003, 0x1DC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_einput. @@ -764,7 +764,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = { { 0x40000001, 0x45C / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_zcal_init_dev1. { 0x00000000, 0x594 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_tx_pwrd4. { 0x00001000, 0x598 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_tx_pwrd5. - { 0x00000001, 0x630 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_adr_cfg. 2 populated DRAM Devices. + { 0x00000001, 0x630 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_adr_cfg. 2 Ranks. { 0x00002000, 0x64C / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_cfg. 8GB total density. { 0x00000002, 0x680 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_arb_timing_r2r. { 0x02020001, 0x694 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_arb_da_turns. @@ -810,7 +810,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = { { 0x2A800000, 0x6DC / 4, DRAM_ID2(16) }, // mc_video_protect_gpu_override0. { 0x00000002, 0x6E0 / 4, DRAM_ID2(16) }, // mc_video_protect_gpu_override1. - // Samsung LPDDR4X 4GB 10nm-class (1y) Die-X for Iowa, Hoag and SDS. + // Samsung LPDDR4X 4GB 10nm-class (1y) Die-X for Iowa, Hoag and Aula. { 0x05500000, 0x0D4 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_auto_cal_config2. { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_auto_cal_vref_sel0. { 0x00000006, 0x1CC / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_quse. @@ -822,10 +822,10 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = { { 0x2A800000, 0x6DC / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // mc_video_protect_gpu_override0. { 0x00000002, 0x6E0 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // mc_video_protect_gpu_override1. - // Samsung LPDDR4X 8GB 10nm-class (1y) Die-X for SDEV Iowa and SDS. + // Samsung LPDDR4X 8GB 10nm-class (1y) Die-X for SDEV Iowa and Aula. { 0x05500000, 0x0D4 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_auto_cal_config2. { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_auto_cal_vref_sel0. - { 0x00000001, 0x134 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_adr_cfg. 2 populated DRAM Devices. + { 0x00000001, 0x134 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_adr_cfg. 2 Ranks. { 0x00000006, 0x1CC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_quse. { 0x00000005, 0x1D0 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_quse_width. { 0x00000003, 0x1DC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_einput. @@ -847,7 +847,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = { { 0x40000001, 0x45C / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_zcal_init_dev1. { 0x00000000, 0x594 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_pmacro_tx_pwrd4. { 0x00001000, 0x598 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_pmacro_tx_pwrd5. - { 0x00000001, 0x630 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_adr_cfg. 2 populated DRAM Devices. + { 0x00000001, 0x630 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_adr_cfg. 2 Ranks. { 0x00002000, 0x64C / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_cfg. 8GB total density. { 0x00000001, 0x670 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_arb_timing_faw. { 0x00000002, 0x680 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_arb_timing_r2r. @@ -881,7 +881,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = { // Samsung LPDDR4X 8GB 10nm-class (1y) Die-Y for SDEV Iowa. { 0x05500000, 0x0D4 / 4, DRAM_ID2(21) }, // emc_auto_cal_config2. { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(21) }, // emc_auto_cal_vref_sel0. - { 0x00000001, 0x134 / 4, DRAM_ID2(21) }, // emc_adr_cfg. 2 populated DRAM Devices. + { 0x00000001, 0x134 / 4, DRAM_ID2(21) }, // emc_adr_cfg. 2 Ranks. { 0x00000008, 0x24C / 4, DRAM_ID2(21) }, // emc_tfaw. { 0x08010004, 0x2B8 / 4, DRAM_ID2(21) }, // emc_mrw1. { 0x08020000, 0x2BC / 4, DRAM_ID2(21) }, // emc_mrw2. @@ -914,7 +914,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = { { 0x40000001, 0x45C / 4, DRAM_ID2(21) }, // emc_zcal_init_dev1. { 0x00000000, 0x594 / 4, DRAM_ID2(21) }, // emc_pmacro_tx_pwrd4. { 0x00001000, 0x598 / 4, DRAM_ID2(21) }, // emc_pmacro_tx_pwrd5. - { 0x00000001, 0x630 / 4, DRAM_ID2(21) }, // mc_emem_adr_cfg. 2 populated DRAM Devices. + { 0x00000001, 0x630 / 4, DRAM_ID2(21) }, // mc_emem_adr_cfg. 2 Ranks. { 0x00002000, 0x64C / 4, DRAM_ID2(21) }, // mc_emem_cfg. 8GB total density. { 0x00000001, 0x670 / 4, DRAM_ID2(21) }, // mc_emem_arb_timing_faw. { 0x00000002, 0x680 / 4, DRAM_ID2(21) }, // mc_emem_arb_timing_r2r. @@ -922,7 +922,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = { { 0x2A800000, 0x6DC / 4, DRAM_ID2(21) }, // mc_video_protect_gpu_override0. { 0x00000002, 0x6E0 / 4, DRAM_ID2(21) }, // mc_video_protect_gpu_override1. - // Samsung LPDDR4X 4GB 10nm-class (1y) Die-A for Unknown SDS. + // Samsung LPDDR4X 4GB 10nm-class (1y) Die-A for Unknown Aula. { 0x05500000, 0x0D4 / 4, DRAM_ID2(22) }, // emc_auto_cal_config2. { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(22) }, // emc_auto_cal_vref_sel0. { 0x00000008, 0x24C / 4, DRAM_ID2(22) }, // emc_tfaw. @@ -986,7 +986,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = { { 0x00000002, 0x6E0 / 4, DRAM_ID2(22) }, // mc_video_protect_gpu_override1. { 0x0000009C, 0x814 / 4, DRAM_ID2(22) }, // swizzle_rank_byte_encode. - // Micron LPDDR4X 4GB 10nm-class (1y) Die-A for Unknown Iowa/Hoag/SDS. + // Micron LPDDR4X 4GB 10nm-class (1y) Die-A for Unknown Iowa/Hoag/Aula. { 0x05500000, 0x0D4 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_auto_cal_config2. { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_auto_cal_vref_sel0. { 0x00000006, 0x1CC / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_quse. diff --git a/bdk/memory_map.h b/bdk/memory_map.h index f72a0c5..d0bfd7b 100644 --- a/bdk/memory_map.h +++ b/bdk/memory_map.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 CTCaer + * Copyright (c) 2019-2021 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -49,8 +49,14 @@ // Virtual disk / Chainloader buffers. #define RAM_DISK_ADDR 0xA4000000 -#define NX_BIS_CACHE_ADDR RAM_DISK_ADDR #define RAM_DISK_SZ 0x41000000 // 1040MB. +#define RAM_DISK2_SZ 0x21000000 // 528MB. + +// NX BIS driver sector cache. +#define NX_BIS_CACHE_ADDR 0xC5000000 +#define NX_BIS_CACHE_SZ 0x10020000 // 256MB. +#define NX_BIS_LOOKUP_ADDR 0xD6000000 +#define NX_BIS_LOOKUP_SZ 0xF000000 // 240MB. // L4T Kernel Panic Storage (PSTORE). #define PSTORE_ADDR 0xB0000000 @@ -91,15 +97,10 @@ #define NYX_FB_SZ 0x384000 // 1280 x 720 x 4. #define DRAM_MEM_HOLE_ADR 0xF6A00000 -#define NX_BIS_LOOKUP_ADR DRAM_MEM_HOLE_ADR #define DRAM_MEM_HOLE_SZ 0x8140000 /* --- Hole: 129MB 0xF6A00000 - 0xFEB3FFFF --- */ #define DRAM_START2 0xFEB40000 -// NX BIS driver sector cache. -// #define NX_BIS_CACHE_ADDR 0xFEE00000 -// #define NX_BIS_CACHE_SZ 0x100000 - // USB buffers. #define USBD_ADDR 0xFEF00000 #define USB_DESCRIPTOR_ADDR 0xFEF40000 diff --git a/bdk/module.h b/bdk/module.h index 6ec303f..acc048c 100644 --- a/bdk/module.h +++ b/bdk/module.h @@ -21,10 +21,13 @@ #include #include +#define IANOS_EXT0 0x304E4149 + // Module Callback typedef void (*cbMainModule_t)(const char *s); typedef void (*memcpy_t)(void *, void *, size_t); typedef void (*memset_t)(void *, int, size_t); +typedef int (*reg_voltage_set_t)(u32, u32); typedef struct _bdkParams_t { @@ -33,6 +36,8 @@ typedef struct _bdkParams_t heap_t *sharedHeap; memcpy_t memcpy; memset_t memset; + u32 extension_magic; + reg_voltage_set_t reg_voltage_set; } *bdkParams_t; // Module Entrypoint diff --git a/bdk/power/max77620.h b/bdk/power/max77620.h index 23ee299..d54909f 100644 --- a/bdk/power/max77620.h +++ b/bdk/power/max77620.h @@ -1,8 +1,7 @@ /* * Defining registers address and its bit definitions of MAX77620 and MAX20024 * - * Copyright (c) 2016 NVIDIA CORPORATION. All rights reserved. - * Copyright (c) 2019 CTCaer + * Copyright (c) 2019-2020 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -30,24 +29,33 @@ #define MAX77620_CNFGGLBL1_LBHYST_200 (1 << 4) #define MAX77620_CNFGGLBL1_LBHYST_300 (2 << 4) #define MAX77620_CNFGGLBL1_LBHYST_400 (3 << 4) -#define MAX77620_CNFGGLBL1_LBHYST (BIT(5) | BIT(4)) #define MAX77620_CNFGGLBL1_MPPLD BIT(6) #define MAX77620_CNFGGLBL1_LBDAC_EN BIT(7) #define MAX77620_REG_CNFGGLBL2 0x01 -#define MAX77620_REG_CNFGGLBL3 0x02 -#define MAX77620_WDTC_MASK 0x3 -#define MAX77620_WDTEN BIT(2) -#define MAX77620_WDTSLPC BIT(3) -#define MAX77620_WDTOFFC BIT(4) #define MAX77620_TWD_MASK 0x3 #define MAX77620_TWD_2s 0x0 #define MAX77620_TWD_16s 0x1 #define MAX77620_TWD_64s 0x2 #define MAX77620_TWD_128s 0x3 +#define MAX77620_WDTEN BIT(2) +#define MAX77620_WDTSLPC BIT(3) +#define MAX77620_WDTOFFC BIT(4) +#define MAX77620_GLBL_LPM BIT(5) +#define MAX77620_I2CTWD_MASK 0xC0 +#define MAX77620_I2CTWD_DISABLED 0x00 +#define MAX77620_I2CTWD_1_33ms 0x40 +#define MAX77620_I2CTWD_35_7ms 0x80 +#define MAX77620_I2CTWD_41_7ms 0xC0 + +#define MAX77620_REG_CNFGGLBL3 0x02 +#define MAX77620_WDTC_MASK 0x3 #define MAX77620_REG_CNFG1_32K 0x03 +#define MAX77620_CNFG1_PWR_MD_32K_MASK 0x3 #define MAX77620_CNFG1_32K_OUT0_EN BIT(2) +#define MAX77620_CNFG1_32KLOAD_MASK 0x30 +#define MAX77620_CNFG1_32K_OK BIT(7) #define MAX77620_REG_CNFGBBC 0x04 #define MAX77620_CNFGBBC_ENABLE BIT(0) @@ -64,6 +72,7 @@ #define MAX77620_CNFGBBC_RESISTOR_6K (3 << MAX77620_CNFGBBC_RESISTOR_SHIFT) #define MAX77620_REG_IRQTOP 0x05 +#define MAX77620_REG_IRQTOPM 0x0D #define MAX77620_IRQ_TOP_ONOFF_MASK BIT(1) #define MAX77620_IRQ_TOP_32K_MASK BIT(2) #define MAX77620_IRQ_TOP_RTC_MASK BIT(3) @@ -73,28 +82,53 @@ #define MAX77620_IRQ_TOP_GLBL_MASK BIT(7) #define MAX77620_REG_INTLBT 0x06 -#define MAX77620_REG_IRQTOPM 0x0D +#define MAX77620_REG_INTENLBT 0x0E +#define MAX77620_IRQ_GLBLM_MASK BIT(0) #define MAX77620_IRQ_TJALRM2_MASK BIT(1) #define MAX77620_IRQ_TJALRM1_MASK BIT(2) #define MAX77620_IRQ_LBM_MASK BIT(3) #define MAX77620_REG_IRQSD 0x07 -#define MAX77620_REG_IRQ_LVL2_L0_7 0x08 -#define MAX77620_REG_IRQ_LVL2_L8 0x09 -#define MAX77620_REG_IRQ_LVL2_GPIO 0x0A -#define MAX77620_REG_ONOFFIRQ 0x0B -#define MAX77620_REG_NVERC 0x0C - -#define MAX77620_REG_INTENLBT 0x0E -#define MAX77620_GLBLM_MASK BIT(0) - #define MAX77620_REG_IRQMASKSD 0x0F +#define MAX77620_IRQSD_PFI_SD3 BIT(4) +#define MAX77620_IRQSD_PFI_SD2 BIT(5) +#define MAX77620_IRQSD_PFI_SD1 BIT(6) +#define MAX77620_IRQSD_PFI_SD0 BIT(7) + +#define MAX77620_REG_IRQ_LVL2_L0_7 0x08 // LDO number that irq occured. #define MAX77620_REG_IRQ_MSK_L0_7 0x10 +#define MAX77620_REG_IRQ_LVL2_L8 0x09 // LDO number that irq occured. Only bit0: LDO8 is valid. #define MAX77620_REG_IRQ_MSK_L8 0x11 +#define MAX77620_REG_IRQ_LVL2_GPIO 0x0A // Edge detection interrupt. + +#define MAX77620_REG_ONOFFIRQ 0x0B #define MAX77620_REG_ONOFFIRQM 0x12 +#define MAX77620_ONOFFIRQ_MRWRN BIT(0) +#define MAX77620_ONOFFIRQ_EN0_1SEC BIT(1) +#define MAX77620_ONOFFIRQ_EN0_F BIT(2) +#define MAX77620_ONOFFIRQ_EN0_R BIT(3) +#define MAX77620_ONOFFIRQ_LID_F BIT(4) +#define MAX77620_ONOFFIRQ_LID_R BIT(5) +#define MAX77620_ONOFFIRQ_ACOK_F BIT(6) +#define MAX77620_ONOFFIRQ_ACOK_R BIT(7) + +#define MAX77620_REG_NVERC 0x0C // Shutdown reason (non-volatile). +#define MAX77620_NVERC_SHDN BIT(0) +#define MAX77620_NVERC_WTCHDG BIT(1) +#define MAX77620_NVERC_HDRST BIT(2) +#define MAX77620_NVERC_TOVLD BIT(3) +#define MAX77620_NVERC_MBLSD BIT(4) +#define MAX77620_NVERC_MBO BIT(5) +#define MAX77620_NVERC_MBU BIT(6) +#define MAX77620_NVERC_RSTIN BIT(7) + #define MAX77620_REG_STATLBT 0x13 #define MAX77620_REG_STATSD 0x14 + #define MAX77620_REG_ONOFFSTAT 0x15 +#define MAX77620_ONOFFSTAT_LID BIT(0) +#define MAX77620_ONOFFSTAT_ACOK BIT(1) +#define MAX77620_ONOFFSTAT_EN0 BIT(2) /* SD and LDO Registers */ #define MAX77620_REG_SD0 0x16 @@ -102,18 +136,42 @@ #define MAX77620_REG_SD2 0x18 #define MAX77620_REG_SD3 0x19 #define MAX77620_REG_SD4 0x1A +#define MAX77620_REG_DVSSD0 0x1B +#define MAX77620_REG_DVSSD1 0x1C #define MAX77620_SDX_VOLT_MASK 0xFF #define MAX77620_SD0_VOLT_MASK 0x3F #define MAX77620_SD1_VOLT_MASK 0x7F #define MAX77620_LDO_VOLT_MASK 0x3F -#define MAX77620_REG_DVSSD0 0x1B -#define MAX77620_REG_DVSSD1 0x1C -#define MAX77620_REG_SD0_CFG 0x1D // SD CNFG1. -#define MAX77620_REG_SD1_CFG 0x1E // SD CNFG1. -#define MAX77620_REG_SD2_CFG 0x1F // SD CNFG1. -#define MAX77620_REG_SD3_CFG 0x20 // SD CNFG1. -#define MAX77620_REG_SD4_CFG 0x21 // SD CNFG1. + +#define MAX77620_REG_SD0_CFG 0x1D +#define MAX77620_REG_SD1_CFG 0x1E +#define MAX77620_REG_SD2_CFG 0x1F +#define MAX77620_REG_SD3_CFG 0x20 +#define MAX77620_REG_SD4_CFG 0x21 +#define MAX77620_SD_SR_MASK 0xC0 +#define MAX77620_SD_SR_SHIFT 6 +#define MAX77620_SD_POWER_MODE_MASK 0x30 +#define MAX77620_SD_POWER_MODE_SHIFT 4 +#define MAX77620_SD_CFG1_ADE_MASK BIT(3) +#define MAX77620_SD_CFG1_ADE_DISABLE 0 +#define MAX77620_SD_CFG1_ADE_ENABLE BIT(3) +#define MAX77620_SD_FPWM_MASK 0x04 +#define MAX77620_SD_FPWM_SHIFT 2 +#define MAX77620_SD_FSRADE_MASK 0x01 +#define MAX77620_SD_FSRADE_SHIFT 0 +#define MAX77620_SD_CFG1_FPWM_SD_MASK BIT(2) +#define MAX77620_SD_CFG1_FPWM_SD_SKIP 0 +#define MAX77620_SD_CFG1_FPWM_SD_FPWM BIT(2) +#define MAX77620_SD_CFG1_MPOK_MASK BIT(1) +#define MAX77620_SD_CFG1_FSRADE_SD_MASK BIT(0) +#define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0 +#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE BIT(0) + #define MAX77620_REG_SD_CFG2 0x22 +#define MAX77620_SD_CNF2_RSVD BIT(0) +#define MAX77620_SD_CNF2_ROVS_EN_SD1 BIT(1) +#define MAX77620_SD_CNF2_ROVS_EN_SD0 BIT(2) + #define MAX77620_REG_LDO0_CFG 0x23 #define MAX77620_REG_LDO0_CFG2 0x24 #define MAX77620_REG_LDO1_CFG 0x25 @@ -132,26 +190,36 @@ #define MAX77620_REG_LDO7_CFG2 0x32 #define MAX77620_REG_LDO8_CFG 0x33 #define MAX77620_REG_LDO8_CFG2 0x34 -#define MAX77620_LDO_CFG2_SS_MASK (1 << 0) -#define MAX77620_LDO_CFG2_SS_FAST (1 << 0) -#define MAX77620_LDO_CFG2_SS_SLOW 0 -#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1) -#define MAX77620_LDO_CFG2_ADE_DISABLE (0 << 1) -#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1) -#define MAX20024_LDO_CFG2_MPOK_MASK BIT(2) -#define MAX77620_LDO_POWER_MODE_MASK 0xC0 +/*! LDO CFG */ #define MAX77620_LDO_POWER_MODE_SHIFT 6 +#define MAX77620_LDO_POWER_MODE_MASK (3 << MAX77620_LDO_POWER_MODE_SHIFT) #define MAX77620_POWER_MODE_NORMAL 3 #define MAX77620_POWER_MODE_LPM 2 #define MAX77620_POWER_MODE_GLPM 1 #define MAX77620_POWER_MODE_DISABLE 0 +/*! LDO CFG2 */ +#define MAX77620_LDO_CFG2_SS_MASK (1 << 0) +#define MAX77620_LDO_CFG2_SS_FAST (0 << 0) +#define MAX77620_LDO_CFG2_SS_SLOW (1 << 0) +#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1) +#define MAX77620_LDO_CFG2_ADE_DISABLE (0 << 1) +#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1) +#define MAX77620_LDO_CFG2_MPOK_MASK BIT(2) +#define MAX77620_LDO_CFG2_POK_MASK BIT(3) +#define MAX77620_LDO_CFG2_COMP_SHIFT 4 +#define MAX77620_LDO_CFG2_COMP_MASK (3 << MAX77620_LDO_COMP_SHIFT) +#define MAX77620_LDO_CFG2_COMP_SLOW 3 +#define MAX77620_LDO_CFG2_COMP_MID_SLOW 2 +#define MAX77620_LDO_CFG2_COMP_MID_FAST 1 +#define MAX77620_LDO_CFG2_COMP_FAST 0 +#define MAX77620_LDO_CFG2_ALPM_EN_MASK BIT(6) +#define MAX77620_LDO_CFG2_OVCLMP_MASK BIT(7) #define MAX77620_REG_LDO_CFG3 0x35 +#define MAX77620_LDO_BIAS_EN BIT(0) #define MAX77620_TRACK4_SHIFT 5 #define MAX77620_TRACK4_MASK (1 << MAX77620_TRACK4_SHIFT) -#define MAX77620_LDO_SLEW_RATE_MASK 0x1 - #define MAX77620_REG_GPIO0 0x36 #define MAX77620_REG_GPIO1 0x37 #define MAX77620_REG_GPIO2 0x38 @@ -160,9 +228,6 @@ #define MAX77620_REG_GPIO5 0x3B #define MAX77620_REG_GPIO6 0x3C #define MAX77620_REG_GPIO7 0x3D -#define MAX77620_REG_PUE_GPIO 0x3E -#define MAX77620_REG_PDE_GPIO 0x3F -#define MAX77620_REG_AME_GPIO 0x40 #define MAX77620_CNFG_GPIO_DRV_MASK (1 << 0) #define MAX77620_CNFG_GPIO_DRV_PUSHPULL (1 << 0) #define MAX77620_CNFG_GPIO_DRV_OPENDRAIN (0 << 0) @@ -181,6 +246,13 @@ #define MAX77620_CNFG_GPIO_DBNC_8ms (0x1 << 6) #define MAX77620_CNFG_GPIO_DBNC_16ms (0x2 << 6) #define MAX77620_CNFG_GPIO_DBNC_32ms (0x3 << 6) +#define MAX77620_GPIO_OUTPUT_DISABLE 0 +#define MAX77620_GPIO_OUTPUT_ENABLE 1 + +#define MAX77620_REG_PUE_GPIO 0x3E // Gpio Pullup resistor enable. +#define MAX77620_REG_PDE_GPIO 0x3F // Gpio Pulldown resistor enable. + +#define MAX77620_REG_AME_GPIO 0x40 // Gpio pinmuxing. Clear bits are Standard GPIO. #define MAX77620_REG_ONOFFCNFG1 0x41 #define MAX20024_ONOFFCNFG1_CLRSE 0x18 @@ -188,19 +260,30 @@ #define MAX77620_ONOFFCNFG1_SLPEN BIT(2) #define MAX77620_ONOFFCNFG1_MRT_SHIFT 0x3 #define MAX77620_ONOFFCNFG1_MRT_MASK 0x38 +#define MAX77620_ONOFFCNFG1_RSVD BIT(6) #define MAX77620_ONOFFCNFG1_SFT_RST BIT(7) #define MAX77620_REG_ONOFFCNFG2 0x42 #define MAX77620_ONOFFCNFG2_WK_EN0 BIT(0) +#define MAX77620_ONOFFCNFG2_WK_ALARM2 BIT(1) #define MAX77620_ONOFFCNFG2_WK_ALARM1 BIT(2) +#define MAX77620_ONOFFCNFG2_WK_MBATT BIT(3) // MBATT event generates a wakeup signal. use it in android/l4t? +#define MAX77620_ONOFFCNFG2_WK_ACOK BIT(4) #define MAX77620_ONOFFCNFG2_SLP_LPM_MSK BIT(5) #define MAX77620_ONOFFCNFG2_WD_RST_WK BIT(6) #define MAX77620_ONOFFCNFG2_SFT_RST_WK BIT(7) /* FPS Registers */ -#define MAX77620_REG_FPS_CFG0 0x43 -#define MAX77620_REG_FPS_CFG1 0x44 -#define MAX77620_REG_FPS_CFG2 0x45 +#define MAX77620_REG_FPS_CFG0 0x43 // FPS0. +#define MAX77620_REG_FPS_CFG1 0x44 // FPS1. +#define MAX77620_REG_FPS_CFG2 0x45 // FPS2. +#define MAX77620_FPS_ENFPS_SW_MASK 0x01 +#define MAX77620_FPS_ENFPS_SW 0x01 +#define MAX77620_FPS_EN_SRC_SHIFT 1 +#define MAX77620_FPS_EN_SRC_MASK 0x06 +#define MAX77620_FPS_TIME_PERIOD_SHIFT 3 +#define MAX77620_FPS_TIME_PERIOD_MASK 0x38 + #define MAX77620_REG_FPS_LDO0 0x46 #define MAX77620_REG_FPS_LDO1 0x47 #define MAX77620_REG_FPS_LDO2 0x48 @@ -215,77 +298,39 @@ #define MAX77620_REG_FPS_SD2 0x51 #define MAX77620_REG_FPS_SD3 0x52 #define MAX77620_REG_FPS_SD4 0x53 -#define MAX77620_REG_FPS_NONE 0 -#define MAX77620_FPS_SRC_MASK 0xC0 -#define MAX77620_FPS_SRC_SHIFT 6 -#define MAX77620_FPS_PU_PERIOD_MASK 0x38 -#define MAX77620_FPS_PU_PERIOD_SHIFT 3 -#define MAX77620_FPS_PD_PERIOD_MASK 0x07 -#define MAX77620_FPS_PD_PERIOD_SHIFT 0 - -/* Minimum and maximum FPS period time (in microseconds) are - * different for MAX77620 and Max20024. - */ -#define MAX77620_FPS_COUNT 3 - -#define MAX77620_FPS_PERIOD_MIN_US 40 -#define MAX20024_FPS_PERIOD_MIN_US 20 - -#define MAX77620_FPS_PERIOD_MAX_US 2560 -#define MAX20024_FPS_PERIOD_MAX_US 5120 - #define MAX77620_REG_FPS_GPIO1 0x54 #define MAX77620_REG_FPS_GPIO2 0x55 #define MAX77620_REG_FPS_GPIO3 0x56 -#define MAX77620_FPS_TIME_PERIOD_MASK 0x38 -#define MAX77620_FPS_TIME_PERIOD_SHIFT 3 -#define MAX77620_FPS_EN_SRC_MASK 0x06 -#define MAX77620_FPS_EN_SRC_SHIFT 1 -#define MAX77620_FPS_ENFPS_SW_MASK 0x01 -#define MAX77620_FPS_ENFPS_SW 0x01 - #define MAX77620_REG_FPS_RSO 0x57 +#define MAX77620_FPS_PD_PERIOD_SHIFT 0 +#define MAX77620_FPS_PD_PERIOD_MASK 0x07 +#define MAX77620_FPS_PU_PERIOD_SHIFT 3 +#define MAX77620_FPS_PU_PERIOD_MASK 0x38 +#define MAX77620_FPS_SRC_SHIFT 6 +#define MAX77620_FPS_SRC_MASK 0xC0 + +#define MAX77620_FPS_COUNT 3 +#define MAX77620_FPS_PERIOD_MIN_US 40 +#define MAX77620_FPS_PERIOD_MAX_US 2560 + #define MAX77620_REG_CID0 0x58 #define MAX77620_REG_CID1 0x59 #define MAX77620_REG_CID2 0x5A #define MAX77620_REG_CID3 0x5B -#define MAX77620_REG_CID4 0x5C +#define MAX77620_REG_CID4 0x5C // OTP version. #define MAX77620_REG_CID5 0x5D - -#define MAX77620_REG_DVSSD4 0x5E -#define MAX20024_REG_MAX_ADD 0x70 - -#define MAX77620_CID_DIDM_MASK 0xF0 -#define MAX77620_CID_DIDM_SHIFT 4 - -/* CNCG2SD */ -#define MAX77620_SD_CNF2_ROVS_EN_SD1 BIT(1) -#define MAX77620_SD_CNF2_ROVS_EN_SD0 BIT(2) +#define MAX77620_CID_DIDO_MASK 0xF +#define MAX77620_CID_DIDO_SHIFT 0 +#define MAX77620_CID_DIDM_MASK 0xF0 +#define MAX77620_CID_DIDM_SHIFT 4 /* Device Identification Metal */ #define MAX77620_CID5_DIDM(n) (((n) >> 4) & 0xF) /* Device Indentification OTP */ #define MAX77620_CID5_DIDO(n) ((n) & 0xF) -/* SD CNFG1 */ -#define MAX77620_SD_SR_MASK 0xC0 -#define MAX77620_SD_SR_SHIFT 6 -#define MAX77620_SD_POWER_MODE_MASK 0x30 -#define MAX77620_SD_POWER_MODE_SHIFT 4 -#define MAX77620_SD_CFG1_ADE_MASK BIT(3) -#define MAX77620_SD_CFG1_ADE_DISABLE 0 -#define MAX77620_SD_CFG1_ADE_ENABLE BIT(3) -#define MAX77620_SD_FPWM_MASK 0x04 -#define MAX77620_SD_FPWM_SHIFT 2 -#define MAX77620_SD_FSRADE_MASK 0x01 -#define MAX77620_SD_FSRADE_SHIFT 0 -#define MAX77620_SD_CFG1_FPWM_SD_MASK BIT(2) -#define MAX77620_SD_CFG1_FPWM_SD_SKIP 0 -#define MAX77620_SD_CFG1_FPWM_SD_FPWM BIT(2) -#define MAX20024_SD_CFG1_MPOK_MASK BIT(1) -#define MAX77620_SD_CFG1_FSRADE_SD_MASK BIT(0) -#define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0 -#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE BIT(0) +#define MAX77620_REG_DVSSD4 0x5E +#define MAX20024_REG_MAX_ADD 0x70 #define MAX77620_IRQ_LVL2_GPIO_EDGE0 BIT(0) #define MAX77620_IRQ_LVL2_GPIO_EDGE1 BIT(1) @@ -332,9 +377,4 @@ enum max77620_fps_src { MAX77620_FPS_SRC_DEF, }; -enum max77620_chip_id { - MAX77620, - MAX20024, -}; - #endif /* _MFD_MAX77620_H_ */ diff --git a/bdk/power/max7762x.c b/bdk/power/max7762x.c index c32cf76..a7d30ce 100644 --- a/bdk/power/max7762x.c +++ b/bdk/power/max7762x.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2019 CTCaer + * Copyright (c) 2019-2020 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -17,163 +17,323 @@ #include #include +#include +#include #include +#include #include -#define REGULATOR_SD 0 +#define REGULATOR_SD 0 #define REGULATOR_LDO 1 +#define REGULATOR_BC0 2 +#define REGULATOR_BC1 3 -typedef struct _max77620_regulator_t +typedef struct _max77620_fps_t { - u8 type; - const char *name; - u8 reg_sd; - - u32 mv_step; - u32 mv_min; - u32 mv_default; - u32 mv_max; - - u8 volt_addr; - u8 cfg_addr; - - u8 volt_mask; - u8 enable_mask; - u8 enable_shift; - u8 status_mask; - u8 fps_addr; u8 fps_src; u8 pd_period; u8 pu_period; +} max77620_fps_t; + +typedef struct _max77621_ctrl_t +{ + u8 ctrl1_por; + u8 ctrl1_hos; + u8 ctrl2_por; + u8 ctrl2_hos; +} max77621_ctrl_t; + +typedef struct _max77812_ctrl_t +{ + u8 mask; + u8 shift; + u8 rsvd0; + u8 rsvd1; +} max77812_en_t; + +typedef struct _max77620_regulator_t +{ + const char *name; + + u32 uv_step; + u32 uv_min; + u32 uv_default; + u32 uv_max; + + u8 type; + u8 volt_addr; + u8 cfg_addr; + u8 volt_mask; + + union { + max77620_fps_t fps; + max77621_ctrl_t ctrl; + max77812_en_t enable; + }; } max77620_regulator_t; static const max77620_regulator_t _pmic_regulators[] = { - { REGULATOR_SD, "sd0", 0x16, 12500, 600000, 625000, 1400000, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, MAX77620_SD0_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x80, MAX77620_REG_FPS_SD0, 1, 7, 1 }, - { REGULATOR_SD, "sd1", 0x17, 12500, 600000, 1125000, 1125000, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x40, MAX77620_REG_FPS_SD1, 0, 1, 5 }, - { REGULATOR_SD, "sd2", 0x18, 12500, 600000, 1325000, 1350000, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x20, MAX77620_REG_FPS_SD2, 1, 5, 2 }, - { REGULATOR_SD, "sd3", 0x19, 12500, 600000, 1800000, 1800000, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x10, MAX77620_REG_FPS_SD3, 0, 3, 3 }, - { REGULATOR_LDO, "ldo0", 0x00, 25000, 800000, 1200000, 1200000, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO0, 3, 7, 0 }, - { REGULATOR_LDO, "ldo1", 0x00, 25000, 800000, 1050000, 1050000, MAX77620_REG_LDO1_CFG, MAX77620_REG_LDO1_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO1, 3, 7, 0 }, - { REGULATOR_LDO, "ldo2", 0x00, 50000, 800000, 1800000, 3300000, MAX77620_REG_LDO2_CFG, MAX77620_REG_LDO2_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO2, 3, 7, 0 }, - { REGULATOR_LDO, "ldo3", 0x00, 50000, 800000, 3100000, 3100000, MAX77620_REG_LDO3_CFG, MAX77620_REG_LDO3_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO3, 3, 7, 0 }, - { REGULATOR_LDO, "ldo4", 0x00, 12500, 800000, 850000, 850000, MAX77620_REG_LDO4_CFG, MAX77620_REG_LDO4_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO4, 0, 7, 1 }, - { REGULATOR_LDO, "ldo5", 0x00, 50000, 800000, 1800000, 1800000, MAX77620_REG_LDO5_CFG, MAX77620_REG_LDO5_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO5, 3, 7, 0 }, - { REGULATOR_LDO, "ldo6", 0x00, 50000, 800000, 2900000, 2900000, MAX77620_REG_LDO6_CFG, MAX77620_REG_LDO6_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO6, 3, 7, 0 }, - { REGULATOR_LDO, "ldo7", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO7, 1, 4, 3 }, - { REGULATOR_LDO, "ldo8", 0x00, 50000, 800000, 1050000, 2800000, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO8, 3, 7, 0 } + { "sd0", 12500, 600000, 625000, 1400000, REGULATOR_SD, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, MAX77620_SD0_VOLT_MASK, {{ MAX77620_REG_FPS_SD0, 1, 7, 1 }} }, + { "sd1", 12500, 600000, 1125000, 1250000, REGULATOR_SD, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, {{ MAX77620_REG_FPS_SD1, 0, 1, 5 }} }, + { "sd2", 12500, 600000, 1325000, 1350000, REGULATOR_SD, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD2, 1, 5, 2 }} }, + { "sd3", 12500, 600000, 1800000, 1800000, REGULATOR_SD, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD3, 0, 3, 3 }} }, + { "ldo0", 25000, 800000, 1200000, 1200000, REGULATOR_LDO, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO0, 3, 7, 0 }} }, + { "ldo1", 25000, 800000, 1050000, 1050000, REGULATOR_LDO, MAX77620_REG_LDO1_CFG, MAX77620_REG_LDO1_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO1, 3, 7, 0 }} }, + { "ldo2", 50000, 800000, 1800000, 3300000, REGULATOR_LDO, MAX77620_REG_LDO2_CFG, MAX77620_REG_LDO2_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO2, 3, 7, 0 }} }, + { "ldo3", 50000, 800000, 3100000, 3100000, REGULATOR_LDO, MAX77620_REG_LDO3_CFG, MAX77620_REG_LDO3_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO3, 3, 7, 0 }} }, + { "ldo4", 12500, 800000, 850000, 1000000, REGULATOR_LDO, MAX77620_REG_LDO4_CFG, MAX77620_REG_LDO4_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO4, 0, 7, 1 }} }, + { "ldo5", 50000, 800000, 1800000, 1800000, REGULATOR_LDO, MAX77620_REG_LDO5_CFG, MAX77620_REG_LDO5_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO5, 3, 7, 0 }} }, + { "ldo6", 50000, 800000, 2900000, 2900000, REGULATOR_LDO, MAX77620_REG_LDO6_CFG, MAX77620_REG_LDO6_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO6, 3, 7, 0 }} }, + { "ldo7", 50000, 800000, 1050000, 1050000, REGULATOR_LDO, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO7, 1, 4, 3 }} }, + { "ldo8", 50000, 800000, 1050000, 2800000, REGULATOR_LDO, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO8, 3, 7, 0 }} }, + + { "max77621_CPU", 6250, 606250, 1000000, 1400000, REGULATOR_BC0, MAX77621_VOUT_REG, MAX77621_VOUT_DVS_REG, MAX77621_DVC_DVS_VOLT_MASK, {{ MAX77621_CPU_CTRL1_POR_DEFAULT, MAX77621_CPU_CTRL1_HOS_DEFAULT, MAX77621_CPU_CTRL2_POR_DEFAULT, MAX77621_CPU_CTRL2_HOS_DEFAULT }} }, + { "max77621_GPU", 6250, 606250, 1200000, 1400000, REGULATOR_BC0, MAX77621_VOUT_REG, MAX77621_VOUT_DVS_REG, MAX77621_DVC_DVS_VOLT_MASK, {{ MAX77621_CPU_CTRL1_POR_DEFAULT, MAX77621_CPU_CTRL1_HOS_DEFAULT, MAX77621_CPU_CTRL2_POR_DEFAULT, MAX77621_CPU_CTRL2_HOS_DEFAULT }} }, + { "max77812_CPU", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M4_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M4_MASK, MAX77812_EN_CTRL_EN_M4_SHIFT, 0, 0 }} }, + //{ "max77812_GPU", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M1_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M1_MASK, MAX77812_EN_CTRL_EN_M1_SHIFT, 0, 0 }} }, + //{ "max77812_RAM", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M3_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M3_MASK, MAX77812_EN_CTRL_EN_M3_SHIFT, 0, 0 }} } // Only on PHASE211 configuration. }; -static void _max77620_set_reg(u8 reg, u8 val) +static u8 _max77812_get_address() +{ + static u8 max77812_i2c_addr = 0; + + if (max77812_i2c_addr) + return max77812_i2c_addr; + + max77812_i2c_addr = + !(FUSE(FUSE_RESERVED_ODM28_T210B01) & 1) ? MAX77812_PHASE31_CPU_I2C_ADDR : MAX77812_PHASE211_CPU_I2C_ADDR; + + return max77812_i2c_addr; +} + +static u8 _max7762x_get_i2c_address(u32 id) +{ + const max77620_regulator_t *reg = &_pmic_regulators[id]; + + // Choose the correct i2c address. + switch (reg->type) + { + case REGULATOR_SD: + case REGULATOR_LDO: + return MAX77620_I2C_ADDR; + case REGULATOR_BC0: + return (id == REGULATOR_CPU0 ? MAX77621_CPU_I2C_ADDR : MAX77621_GPU_I2C_ADDR); + case REGULATOR_BC1: + return _max77812_get_address(); + default: + return 0; + } +} + +static void _max7762x_set_reg(u8 addr, u8 reg, u8 val) { u32 retries = 100; while (retries) { - if (i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, reg, val)) + if (i2c_send_byte(I2C_5, addr, reg, val)) break; - usleep(100); + + usleep(50); retries--; } } int max77620_regulator_get_status(u32 id) { - if (id > REGULATOR_MAX) + if (id > REGULATOR_LDO8) return 0; const max77620_regulator_t *reg = &_pmic_regulators[id]; + // SD power OK status. if (reg->type == REGULATOR_SD) - return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_STATSD) & reg->status_mask) ? 0 : 1; - return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->cfg_addr) & 8) ? 1 : 0; + { + u8 mask = 1u << (7 - id); + return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_STATSD) & mask) ? 0 : 1; + } + + // LDO power OK status. + return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->cfg_addr) & MAX77620_LDO_CFG2_POK_MASK) ? 1 : 0; } int max77620_regulator_config_fps(u32 id) { - if (id > REGULATOR_MAX) + if (id > REGULATOR_LDO8) return 0; const max77620_regulator_t *reg = &_pmic_regulators[id]; - _max77620_set_reg(reg->fps_addr, - (reg->fps_src << MAX77620_FPS_SRC_SHIFT) | (reg->pu_period << MAX77620_FPS_PU_PERIOD_SHIFT) | (reg->pd_period)); + // Set FPS configuration. + _max7762x_set_reg(MAX77620_I2C_ADDR, + reg->fps.fps_addr, + (reg->fps.fps_src << MAX77620_FPS_SRC_SHIFT) | + (reg->fps.pu_period << MAX77620_FPS_PU_PERIOD_SHIFT) | + (reg->fps.pd_period << MAX77620_FPS_PD_PERIOD_SHIFT)); return 1; } -int max77620_regulator_set_voltage(u32 id, u32 mv) +int max7762x_regulator_set_voltage(u32 id, u32 mv) { if (id > REGULATOR_MAX) return 0; const max77620_regulator_t *reg = &_pmic_regulators[id]; - if (mv < reg->mv_min || mv > reg->mv_max) + if (mv < reg->uv_min || mv > reg->uv_max) return 0; - u32 mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step; - u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->volt_addr); + u8 addr = _max7762x_get_i2c_address(id); + + // Calculate voltage multiplier. + u32 mult = (mv + reg->uv_step - 1 - reg->uv_min) / reg->uv_step; + u8 val = i2c_recv_byte(I2C_5, addr, reg->volt_addr); val = (val & ~reg->volt_mask) | (mult & reg->volt_mask); - _max77620_set_reg(reg->volt_addr, val); + + // Set voltage. + _max7762x_set_reg(addr, reg->volt_addr, val); + + // If max77621 set DVS voltage also. + if (reg->type == REGULATOR_BC0) + _max7762x_set_reg(addr, reg->cfg_addr, MAX77621_VOUT_ENABLE_MASK | val); + + // Wait for ramp up/down delay. usleep(1000); return 1; } -int max77620_regulator_enable(u32 id, int enable) +int max7762x_regulator_enable(u32 id, bool enable) { + u8 reg_addr; + u8 enable_val; + u8 enable_mask; + u8 enable_shift; + if (id > REGULATOR_MAX) return 0; const max77620_regulator_t *reg = &_pmic_regulators[id]; - u32 addr = reg->type == REGULATOR_SD ? reg->cfg_addr : reg->volt_addr; - u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, addr); + // Choose the correct i2c and register addresses and mask/shift for each type. + switch (reg->type) + { + case REGULATOR_SD: + reg_addr = reg->cfg_addr; + enable_val = MAX77620_POWER_MODE_NORMAL; + enable_mask = MAX77620_SD_POWER_MODE_MASK; + enable_shift = MAX77620_SD_POWER_MODE_SHIFT; + break; + case REGULATOR_LDO: + reg_addr = reg->volt_addr; + enable_val = MAX77620_POWER_MODE_NORMAL; + enable_mask = MAX77620_LDO_POWER_MODE_MASK; + enable_shift = MAX77620_LDO_POWER_MODE_SHIFT; + break; + case REGULATOR_BC0: + reg_addr = reg->volt_addr; + enable_val = MAX77621_VOUT_ENABLE; + enable_mask = MAX77621_DVC_DVS_ENABLE_MASK; + enable_shift = MAX77621_DVC_DVS_ENABLE_SHIFT; + break; + case REGULATOR_BC1: + reg_addr = reg->cfg_addr; + enable_val = MAX77812_EN_CTRL_ENABLE; + enable_mask = reg->enable.mask; + enable_shift = reg->enable.shift; + break; + default: + return 0; + } + + u8 addr = _max7762x_get_i2c_address(id); + + // Read and enable/disable. + u8 val = i2c_recv_byte(I2C_5, addr, reg_addr); + val &= ~enable_mask; + if (enable) - val = (val & ~reg->enable_mask) | ((MAX77620_POWER_MODE_NORMAL << reg->enable_shift) & reg->enable_mask); - else - val &= ~reg->enable_mask; - _max77620_set_reg(addr, val); + val |= (enable_val << enable_shift); + + // Set enable. + _max7762x_set_reg(addr, reg_addr, val); + + // Wait for enable/disable ramp delay. usleep(1000); return 1; } -// LDO only. -int max77620_regulator_set_volt_and_flags(u32 id, u32 mv, u8 flags) +void max77620_config_gpio(u32 gpio_id, bool enable) { - if (id > REGULATOR_MAX) - return 0; + if (gpio_id > 7) + return; + // Configure as standard GPIO. + u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO); + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO, val & ~BIT(gpio_id)); + + // Set GPIO configuration. + if (enable) + val = MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH | MAX77620_CNFG_GPIO_DIR_OUTPUT | MAX77620_CNFG_GPIO_DRV_PUSHPULL; + else + val = MAX77620_CNFG_GPIO_DIR_INPUT | MAX77620_CNFG_GPIO_DRV_OPENDRAIN; + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO0 + gpio_id, val); +} + +void max77621_config_default(u32 id, bool por) +{ const max77620_regulator_t *reg = &_pmic_regulators[id]; - if (mv < reg->mv_min || mv > reg->mv_max) - return 0; + if (reg->type != REGULATOR_BC0) + return; - u32 mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step; - u8 val = ((flags << reg->enable_shift) & ~reg->volt_mask) | (mult & reg->volt_mask); - _max77620_set_reg(reg->volt_addr, val); - usleep(1000); + u8 addr = _max7762x_get_i2c_address(id); - return 1; + if (por) + { + // Set voltage and disable power before changing the inductor. + max7762x_regulator_set_voltage(id, 1000000); + max7762x_regulator_enable(id, false); + + // Configure to default. + i2c_send_byte(I2C_5, addr, MAX77621_CONTROL1_REG, reg->ctrl.ctrl1_por); + i2c_send_byte(I2C_5, addr, MAX77621_CONTROL2_REG, reg->ctrl.ctrl2_por); + } + else + { + i2c_send_byte(I2C_5, addr, MAX77621_CONTROL1_REG, reg->ctrl.ctrl1_hos); + i2c_send_byte(I2C_5, addr, MAX77621_CONTROL2_REG, reg->ctrl.ctrl2_hos); + } } void max77620_config_default() { - for (u32 i = 1; i <= REGULATOR_MAX; i++) + // Check if Erista OTP. + if (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CID4) != 0x35) + return; + + // Set default voltages and enable regulators. + for (u32 i = 1; i <= REGULATOR_LDO8; i++) { - i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CID4); max77620_regulator_config_fps(i); - max77620_regulator_set_voltage(i, _pmic_regulators[i].mv_default); - if (_pmic_regulators[i].fps_src != MAX77620_FPS_SRC_NONE) - max77620_regulator_enable(i, 1); + max7762x_regulator_set_voltage(i, _pmic_regulators[i].uv_default); + if (_pmic_regulators[i].fps.fps_src != MAX77620_FPS_SRC_NONE) + max7762x_regulator_enable(i, true); } - _max77620_set_reg(MAX77620_REG_SD_CFG2, 4); + + // Enable SD0 output voltage sense and disable for SD1. Additionally disable the reserved bit. + _max7762x_set_reg(MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, MAX77620_SD_CNF2_ROVS_EN_SD0); } +// Stock HOS: disabled. void max77620_low_battery_monitor_config(bool enable) { - _max77620_set_reg(MAX77620_REG_CNFGGLBL1, - MAX77620_CNFGGLBL1_LBDAC_EN | (enable ? MAX77620_CNFGGLBL1_MPPLD : 0) | - MAX77620_CNFGGLBL1_LBHYST_200 | MAX77620_CNFGGLBL1_LBDAC_2800); + _max7762x_set_reg(MAX77620_I2C_ADDR, MAX77620_REG_CNFGGLBL1, + MAX77620_CNFGGLBL1_LBDAC_EN | + (enable ? MAX77620_CNFGGLBL1_MPPLD : 0) | + MAX77620_CNFGGLBL1_LBHYST_200 | + MAX77620_CNFGGLBL1_LBDAC_2800); } diff --git a/bdk/power/max7762x.h b/bdk/power/max7762x.h index dd06bf7..3478530 100644 --- a/bdk/power/max7762x.h +++ b/bdk/power/max7762x.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2019 CTCaer + * Copyright (c) 2019-2020 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -32,11 +32,11 @@ * ldo1 | XUSB, PCIE | 25000 | 800000 | 1050000 | 1050000 | 1.05V (pcv) * ldo2 | SDMMC1 | 50000 | 800000 | 1800000 | 3300000 | * ldo3 | GC ASIC | 50000 | 800000 | 3100000 | 3100000 | 3.1V (pcv) -* ldo4 | RTC | 12500 | 800000 | 850000 | 850000 | +* ldo4 | RTC | 12500 | 800000 | 850000 | 850000 | 0.85V (AO, pcv) * ldo5 | GC Card | 50000 | 800000 | 1800000 | 1800000 | 1.8V (pcv) -* ldo6 | Touch, ALS | 50000 | 800000 | 2900000 | 2900000 | 2.9V -* ldo7 | XUSB | 50000 | 800000 | 1050000 | 1050000 | -* ldo8 | XUSB, DC | 50000 | 800000 | 1050000 | 1050000 | +* ldo6 | Touch, ALS | 50000 | 800000 | 2900000 | 2900000 | 2.9V (pcv) +* ldo7 | XUSB | 50000 | 800000 | 1050000 | 1050000 | 1.05V (pcv) +* ldo8 | XUSB, DP, MCU | 50000 | 800000 | 1050000 | 2800000 | 1.05V/2.8V (pcv) */ /* @@ -45,10 +45,10 @@ */ /*! MAX77620 partitions. */ -#define REGULATOR_SD0 0 -#define REGULATOR_SD1 1 -#define REGULATOR_SD2 2 -#define REGULATOR_SD3 3 +#define REGULATOR_SD0 0 +#define REGULATOR_SD1 1 +#define REGULATOR_SD2 2 +#define REGULATOR_SD3 3 #define REGULATOR_LDO0 4 #define REGULATOR_LDO1 5 #define REGULATOR_LDO2 6 @@ -58,26 +58,40 @@ #define REGULATOR_LDO6 10 #define REGULATOR_LDO7 11 #define REGULATOR_LDO8 12 -#define REGULATOR_MAX 12 +#define REGULATOR_CPU0 13 +#define REGULATOR_GPU0 14 +#define REGULATOR_CPU1 15 +//#define REGULATOR_GPU1 16 +//#define REGULATOR_GPU1 17 +#define REGULATOR_MAX 15 #define MAX77621_CPU_I2C_ADDR 0x1B #define MAX77621_GPU_I2C_ADDR 0x1C -#define MAX77621_VOUT_REG 0 -#define MAX77621_VOUT_DVS_REG 1 -#define MAX77621_CONTROL1_REG 2 -#define MAX77621_CONTROL2_REG 3 - -/* MAX77621_VOUT */ -#define MAX77621_VOUT_ENABLE BIT(7) -#define MAX77621_VOUT_MASK 0x7F -#define MAX77621_VOUT_0_95V 0x37 -#define MAX77621_VOUT_1_09V 0x4F +#define MAX77621_VOUT_REG 0x00 +#define MAX77621_VOUT_DVS_REG 0x01 +#define MAX77621_CONTROL1_REG 0x02 +#define MAX77621_CONTROL2_REG 0x03 +#define MAX77621_CHIPID1_REG 0x04 +#define MAX77621_CHIPID2_REG 0x05 /* MAX77621_VOUT_DVC_DVS */ -#define MAX77621_DVS_VOUT_MASK 0x7F +#define MAX77621_DVC_DVS_VOLT_MASK 0x7F +#define MAX77621_DVC_DVS_ENABLE_SHIFT 7 +#define MAX77621_DVC_DVS_ENABLE_MASK (1 << MAX77621_DVC_DVS_ENABLE_SHIFT) + +/* MAX77621_VOUT */ +#define MAX77621_VOUT_DISABLE 0 +#define MAX77621_VOUT_ENABLE 1 +#define MAX77621_VOUT_ENABLE_MASK (MAX77621_VOUT_ENABLE << MAX77621_DVC_DVS_ENABLE_SHIFT) /* MAX77621_CONTROL1 */ +#define MAX77621_RAMP_12mV_PER_US 0x0 +#define MAX77621_RAMP_25mV_PER_US 0x1 +#define MAX77621_RAMP_50mV_PER_US 0x2 +#define MAX77621_RAMP_200mV_PER_US 0x3 +#define MAX77621_RAMP_MASK 0x3 + #define MAX77621_FREQSHIFT_9PER BIT(2) #define MAX77621_BIAS_ENABLE BIT(3) #define MAX77621_AD_ENABLE BIT(4) @@ -85,34 +99,50 @@ #define MAX77621_FPWM_EN_M BIT(6) #define MAX77621_SNS_ENABLE BIT(7) -#define MAX77621_RAMP_12mV_PER_US 0x0 -#define MAX77621_RAMP_25mV_PER_US 0x1 -#define MAX77621_RAMP_50mV_PER_US 0x2 -#define MAX77621_RAMP_200mV_PER_US 0x3 -#define MAX77621_RAMP_MASK 0x3 - /* MAX77621_CONTROL2 */ -#define MAX77621_FT_ENABLE BIT(4) -#define MAX77621_DISCH_ENBABLE BIT(5) -#define MAX77621_WDTMR_ENABLE BIT(6) -#define MAX77621_T_JUNCTION_120 BIT(7) +#define MAX77621_INDUCTOR_MIN_30_PER 0 +#define MAX77621_INDUCTOR_NOMINAL 1 +#define MAX77621_INDUCTOR_PLUS_30_PER 2 +#define MAX77621_INDUCTOR_PLUS_60_PER 3 +#define MAX77621_INDUCTOR_MASK 3 -#define MAX77621_CKKADV_TRIP_DISABLE 0xC #define MAX77621_CKKADV_TRIP_75mV_PER_US 0x0 -#define MAX77621_CKKADV_TRIP_150mV_PER_US 0x4 -#define MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS 0x8 +#define MAX77621_CKKADV_TRIP_150mV_PER_US BIT(2) +#define MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS BIT(3) +#define MAX77621_CKKADV_TRIP_DISABLE (BIT(2) | BIT(3)) +#define MAX77621_CKKADV_TRIP_MASK (BIT(2) | BIT(3)) -#define MAX77621_INDUCTOR_MIN_30_PER 0x0 -#define MAX77621_INDUCTOR_NOMINAL 0x1 -#define MAX77621_INDUCTOR_PLUS_30_PER 0x2 -#define MAX77621_INDUCTOR_PLUS_60_PER 0x3 +#define MAX77621_FT_ENABLE BIT(4) +#define MAX77621_DISCH_ENABLE BIT(5) +#define MAX77621_WDTMR_ENABLE BIT(6) +#define MAX77621_T_JUNCTION_120 BIT(7) -int max77620_regulator_get_status(u32 id); -int max77620_regulator_config_fps(u32 id); -int max77620_regulator_set_voltage(u32 id, u32 mv); -int max77620_regulator_enable(u32 id, int enable); -int max77620_regulator_set_volt_and_flags(u32 id, u32 mv, u8 flags); +#define MAX77621_CPU_CTRL1_POR_DEFAULT (MAX77621_RAMP_50mV_PER_US) +#define MAX77621_CPU_CTRL1_HOS_DEFAULT (MAX77621_AD_ENABLE | \ + MAX77621_NFSR_ENABLE | \ + MAX77621_SNS_ENABLE | \ + MAX77621_RAMP_12mV_PER_US) +#define MAX77621_CPU_CTRL2_POR_DEFAULT (MAX77621_T_JUNCTION_120 | \ + MAX77621_FT_ENABLE | \ + MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS | \ + MAX77621_CKKADV_TRIP_150mV_PER_US | \ + MAX77621_INDUCTOR_NOMINAL) +#define MAX77621_CPU_CTRL2_HOS_DEFAULT (MAX77621_T_JUNCTION_120 | \ + MAX77621_WDTMR_ENABLE | \ + MAX77621_CKKADV_TRIP_75mV_PER_US | \ + MAX77621_INDUCTOR_NOMINAL) + +#define MAX77621_CTRL_HOS_CFG 0 +#define MAX77621_CTRL_POR_CFG 1 + +int max77620_regulator_get_status(u32 id); +int max77620_regulator_config_fps(u32 id); +int max7762x_regulator_set_voltage(u32 id, u32 mv); +int max7762x_regulator_enable(u32 id, bool enable); +void max77620_config_gpio(u32 id, bool enable); void max77620_config_default(); void max77620_low_battery_monitor_config(bool enable); +void max77621_config_default(u32 id, bool por); + #endif diff --git a/bdk/power/max77812.h b/bdk/power/max77812.h index f8ac3fb..89c3baf 100644 --- a/bdk/power/max77812.h +++ b/bdk/power/max77812.h @@ -17,8 +17,8 @@ #ifndef _MAX77812_H_ #define _MAX77812_H_ -#define MAX77812_PHASE31_CPU_I2C_ADDR 0x31 -#define MAX77812_PHASE211_CPU_I2C_ADDR 0x33 +#define MAX77812_PHASE31_CPU_I2C_ADDR 0x31 // 2 Outputs: 3-phase M1 + 1-phase M4. +#define MAX77812_PHASE211_CPU_I2C_ADDR 0x33 // 3 Outputs: 2-phase M1 + 1-phase M3 + 1-phase M4. #define MAX77812_REG_RSET 0x00 #define MAX77812_REG_INT_SRC 0x01 @@ -27,7 +27,15 @@ #define MAX77812_REG_TOPSYS_INT_M 0x04 #define MAX77812_REG_TOPSYS_STAT 0x05 #define MAX77812_REG_EN_CTRL 0x06 -#define MAX77812_EN_CTRL_EN_M4 BIT(6) +#define MAX77812_EN_CTRL_ENABLE 1 +#define MAX77812_EN_CTRL_EN_M1_SHIFT 0 +#define MAX77812_EN_CTRL_EN_M1_MASK (1 << MAX77812_EN_CTRL_EN_M1_SHIFT) +#define MAX77812_EN_CTRL_EN_M2_SHIFT 2 +#define MAX77812_EN_CTRL_EN_M2_MASK (1 << MAX77812_EN_CTRL_EN_M2_SHIFT) +#define MAX77812_EN_CTRL_EN_M3_SHIFT 4 +#define MAX77812_EN_CTRL_EN_M3_MASK (1 << MAX77812_EN_CTRL_EN_M3_SHIFT) +#define MAX77812_EN_CTRL_EN_M4_SHIFT 6 +#define MAX77812_EN_CTRL_EN_M4_MASK (1 << MAX77812_EN_CTRL_EN_M4_SHIFT) #define MAX77812_REG_STUP_DLY2 0x07 #define MAX77812_REG_STUP_DLY3 0x08 #define MAX77812_REG_STUP_DLY4 0x09 @@ -46,11 +54,10 @@ #define MAX77812_REG_BUCK_INT 0x20 #define MAX77812_REG_BUCK_INT_M 0x21 #define MAX77812_REG_BUCK_STAT 0x22 -#define MAX77812_REG_M1_VOUT 0x23 +#define MAX77812_REG_M1_VOUT 0x23 // GPU. #define MAX77812_REG_M2_VOUT 0x24 -#define MAX77812_REG_M3_VOUT 0x25 -#define MAX77812_REG_M4_VOUT 0x26 -#define MAX77812_M4_VOUT_0_80V 0x6E +#define MAX77812_REG_M3_VOUT 0x25 // DRAM on PHASE211. +#define MAX77812_REG_M4_VOUT 0x26 // CPU. #define MAX77812_REG_M1_VOUT_D 0x27 #define MAX77812_REG_M2_VOUT_D 0x28 #define MAX77812_REG_M3_VOUT_D 0x29 @@ -66,6 +73,8 @@ #define MAX77812_REG_GLB_CFG1 0x33 #define MAX77812_REG_GLB_CFG2 0x34 #define MAX77812_REG_GLB_CFG3 0x35 + +/*! Protected area and settings only for MAX77812_REG_VERSION 4 */ #define MAX77812_REG_GLB_CFG4 0x36 #define MAX77812_REG_GLB_CFG5 0x37 #define MAX77812_REG_GLB_CFG6 0x38 @@ -91,10 +100,6 @@ #define MAX77812_ES2_VERSION 0x04 #define MAX77812_QS_VERSION 0x05 -#define MAX77812_VOUT_MASK 0xFF -#define MAX77812_VOUT_N_VOLTAGE 0xFF -#define MAX77812_VOUT_VMIN 250000 -#define MAX77812_VOUT_VMAX 1525000 -#define MAX77812_VOUT_STEP 5000 +#define MAX77812_BUCK_VOLT_MASK 0xFF #endif diff --git a/bdk/power/regulator_5v.c b/bdk/power/regulator_5v.c index c61db64..64fd7d7 100644 --- a/bdk/power/regulator_5v.c +++ b/bdk/power/regulator_5v.c @@ -21,8 +21,9 @@ #include static u8 reg_5v_dev = 0; +static bool batt_src = false; -void regulator_enable_5v(u8 dev) +void regulator_5v_enable(u8 dev) { // The power supply selection from battery or USB is automatic. if (!reg_5v_dev) @@ -32,6 +33,7 @@ void regulator_enable_5v(u8 dev) gpio_config(GPIO_PORT_A, GPIO_PIN_5, GPIO_MODE_GPIO); gpio_output_enable(GPIO_PORT_A, GPIO_PIN_5, GPIO_OUTPUT_ENABLE); gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH); + batt_src = true; // Fan and Rail power from USB 5V VDD. PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_LPDR | 1; @@ -47,7 +49,7 @@ void regulator_enable_5v(u8 dev) reg_5v_dev |= dev; } -void regulator_disable_5v(u8 dev) +void regulator_5v_disable(u8 dev) { reg_5v_dev &= ~dev; @@ -58,6 +60,7 @@ void regulator_disable_5v(u8 dev) gpio_output_enable(GPIO_PORT_A, GPIO_PIN_5, GPIO_OUTPUT_DISABLE); gpio_config(GPIO_PORT_A, GPIO_PIN_5, GPIO_MODE_SPIO); PINMUX_AUX(PINMUX_AUX_SATA_LED_ACTIVE) = PINMUX_PARKED | PINMUX_INPUT_ENABLE; + batt_src = false; // Rail power from USB 5V VDD. gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW); @@ -70,7 +73,21 @@ void regulator_disable_5v(u8 dev) } } -bool regulator_get_5v_dev_enabled(u8 dev) +bool regulator_5v_get_dev_enabled(u8 dev) { return (reg_5v_dev & dev); } + +void regulator_5v_batt_src_enable(bool enable) +{ + if (enable && !batt_src) + { + gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH); + batt_src = true; + } + else if (!enable && batt_src) + { + gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_LOW); + batt_src = false; + } +} diff --git a/bdk/power/regulator_5v.h b/bdk/power/regulator_5v.h index 6bb837a..b7d7490 100644 --- a/bdk/power/regulator_5v.h +++ b/bdk/power/regulator_5v.h @@ -27,8 +27,9 @@ enum REGULATOR_5V_ALL = 0xFF }; -void regulator_enable_5v(u8 dev); -void regulator_disable_5v(u8 dev); -bool regulator_get_5v_dev_enabled(u8 dev); +void regulator_5v_enable(u8 dev); +void regulator_5v_disable(u8 dev); +bool regulator_5v_get_dev_enabled(u8 dev); +void regulator_5v_batt_src_enable(bool enable); #endif \ No newline at end of file diff --git a/bdk/sec/se.c b/bdk/sec/se.c index 2f76985..92767b9 100644 --- a/bdk/sec/se.c +++ b/bdk/sec/se.c @@ -1,8 +1,8 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018 CTCaer + * Copyright (c) 2018-2021 CTCaer * Copyright (c) 2018 Atmosphère-NX - * Copyright (c) 2019-2020 shchmue + * Copyright (c) 2019-2021 shchmue * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -35,8 +35,8 @@ typedef struct _se_ll_t vu32 size; } se_ll_t; -static u32 _se_rsa_mod_sizes[TEGRA_SE_RSA_KEYSLOT_COUNT]; -static u32 _se_rsa_exp_sizes[TEGRA_SE_RSA_KEYSLOT_COUNT]; +static u32 _se_rsa_mod_sizes[SE_RSA_KEYSLOT_COUNT]; +static u32 _se_rsa_exp_sizes[SE_RSA_KEYSLOT_COUNT]; static void _gf256_mul_x(void *block) { @@ -79,17 +79,17 @@ static void _se_ll_init(se_ll_t *ll, u32 addr, u32 size) static void _se_ll_set(se_ll_t *dst, se_ll_t *src) { - SE(SE_IN_LL_ADDR_REG_OFFSET) = (u32)src; - SE(SE_OUT_LL_ADDR_REG_OFFSET) = (u32)dst; + SE(SE_IN_LL_ADDR_REG) = (u32)src; + SE(SE_OUT_LL_ADDR_REG) = (u32)dst; } static int _se_wait() { - while (!(SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_OP_DONE(INT_SET))) + while (!(SE(SE_INT_STATUS_REG) & SE_INT_OP_DONE)) ; - if (SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_ERROR(INT_SET) || - SE(SE_STATUS_0) & SE_STATUS_0_STATE_WAIT_IN || - SE(SE_ERR_STATUS_0) != SE_ERR_STATUS_0_SE_NS_ACCESS_CLEAR) + if (SE(SE_INT_STATUS_REG) & SE_INT_ERR_STAT || + (SE(SE_STATUS_REG) & SE_STATUS_STATE_MASK) != SE_STATUS_STATE_IDLE || + SE(SE_ERR_STATUS_REG) != 0) return 0; return 1; } @@ -114,12 +114,12 @@ static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src _se_ll_set(ll_dst, ll_src); - SE(SE_ERR_STATUS_0) = SE(SE_ERR_STATUS_0); - SE(SE_INT_STATUS_REG_OFFSET) = SE(SE_INT_STATUS_REG_OFFSET); + SE(SE_ERR_STATUS_REG) = SE(SE_ERR_STATUS_REG); + SE(SE_INT_STATUS_REG) = SE(SE_INT_STATUS_REG); bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); - SE(SE_OPERATION_REG_OFFSET) = SE_OPERATION(op); + SE(SE_OPERATION_REG) = op; if (is_oneshot) { @@ -168,13 +168,13 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr if (!src || !dst) return 0; - u8 *block = (u8 *)malloc(0x10); - memset(block, 0, 0x10); + u8 *block = (u8 *)malloc(SE_AES_BLOCK_SIZE); + memset(block, 0, SE_AES_BLOCK_SIZE); - SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; + SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1; memcpy(block, src, src_size); - int res = _se_execute_oneshot(op, block, 0x10, block, 0x10); + int res = _se_execute_oneshot(op, block, SE_AES_BLOCK_SIZE, block, SE_AES_BLOCK_SIZE); memcpy(dst, block, dst_size); free(block); @@ -183,21 +183,21 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr static void _se_aes_ctr_set(void *ctr) { - u32 data[TEGRA_SE_AES_BLOCK_SIZE / 4]; - memcpy(data, ctr, TEGRA_SE_AES_BLOCK_SIZE); + u32 data[SE_AES_IV_SIZE / 4]; + memcpy(data, ctr, SE_AES_IV_SIZE); - for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++) - SE(SE_CRYPTO_CTR_REG_OFFSET + (4 * i)) = data[i]; + for (u32 i = 0; i < SE_CRYPTO_LINEAR_CTR_REG_COUNT; i++) + SE(SE_CRYPTO_LINEAR_CTR_REG + (4 * i)) = data[i]; } void se_rsa_acc_ctrl(u32 rs, u32 flags) { - if (flags & SE_RSA_KEY_TBL_DIS_KEY_ALL_FLAG) - SE(SE_RSA_KEYTABLE_ACCESS_REG_OFFSET + 4 * rs) = - ((flags >> SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) | - ((flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG) ^ SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG); - if (flags & SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG) - SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) &= ~BIT(rs); + if (flags & SE_RSA_KEY_TBL_DIS_KEY_ACCESS_FLAG) + SE(SE_RSA_KEYTABLE_ACCESS_REG + 4 * rs) = + (((flags >> 4) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) |(flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG)) ^ + SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_USE_FLAG; + if (flags & SE_RSA_KEY_LOCK_FLAG) + SE(SE_RSA_SECURITY_PERKEY_REG) &= ~BIT(rs); } // se_rsa_key_set() was derived from Atmosphère's set_rsa_keyslot @@ -206,15 +206,15 @@ void se_rsa_key_set(u32 ks, const void *mod, u32 mod_size, const void *exp, u32 u32 *data = (u32 *)mod; for (u32 i = 0; i < mod_size / 4; i++) { - SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_MOD) | i; - SE(SE_RSA_KEYTABLE_DATA) = byte_swap_32(data[mod_size / 4 - i - 1]); + SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_MOD) | i; + SE(SE_RSA_KEYTABLE_DATA_REG) = byte_swap_32(data[mod_size / 4 - i - 1]); } data = (u32 *)exp; for (u32 i = 0; i < exp_size / 4; i++) { - SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_EXP) | i; - SE(SE_RSA_KEYTABLE_DATA) = byte_swap_32(data[exp_size / 4 - i - 1]); + SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_EXP) | i; + SE(SE_RSA_KEYTABLE_DATA_REG) = byte_swap_32(data[exp_size / 4 - i - 1]); } _se_rsa_mod_sizes[ks] = mod_size; @@ -224,15 +224,15 @@ void se_rsa_key_set(u32 ks, const void *mod, u32 mod_size, const void *exp, u32 // se_rsa_key_clear() was derived from Atmosphère's clear_rsa_keyslot void se_rsa_key_clear(u32 ks) { - for (u32 i = 0; i < TEGRA_SE_RSA2048_DIGEST_SIZE / 4; i++) + for (u32 i = 0; i < SE_RSA2048_DIGEST_SIZE / 4; i++) { - SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_MOD) | i; - SE(SE_RSA_KEYTABLE_DATA) = 0; + SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_MOD) | i; + SE(SE_RSA_KEYTABLE_DATA_REG) = 0; } - for (u32 i = 0; i < TEGRA_SE_RSA2048_DIGEST_SIZE / 4; i++) + for (u32 i = 0; i < SE_RSA2048_DIGEST_SIZE / 4; i++) { - SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_EXP) | i; - SE(SE_RSA_KEYTABLE_DATA) = 0; + SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_EXP) | i; + SE(SE_RSA_KEYTABLE_DATA_REG) = 0; } } @@ -240,22 +240,22 @@ void se_rsa_key_clear(u32 ks) int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size) { int res; - u8 stack_buf[TEGRA_SE_RSA2048_DIGEST_SIZE]; + u8 stack_buf[SE_RSA2048_DIGEST_SIZE]; for (u32 i = 0; i < src_size; i++) stack_buf[i] = *((u8 *)src + src_size - i - 1); - SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RSA) | SE_CONFIG_DST(DST_RSAREG); + SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RSA) | SE_CONFIG_DST(DST_RSAREG); SE(SE_RSA_CONFIG) = RSA_KEY_SLOT(ks); - SE(SE_RSA_KEY_SIZE_REG_OFFSET) = (_se_rsa_mod_sizes[ks] >> 6) - 1; - SE(SE_RSA_EXP_SIZE_REG_OFFSET) = _se_rsa_exp_sizes[ks] >> 2; + SE(SE_RSA_KEY_SIZE_REG) = (_se_rsa_mod_sizes[ks] >> 6) - 1; + SE(SE_RSA_EXP_SIZE_REG) = _se_rsa_exp_sizes[ks] >> 2; - res = _se_execute_oneshot(OP_START, NULL, 0, stack_buf, src_size); + res = _se_execute_oneshot(SE_OP_START, NULL, 0, stack_buf, src_size); // Copy output hash. u32 *dst32 = (u32 *)dst; for (u32 i = 0; i < dst_size / 4; i++) - dst32[dst_size / 4 - i - 1] = byte_swap_32(SE(SE_RSA_OUTPUT + (i << 2))); + dst32[dst_size / 4 - i - 1] = byte_swap_32(SE(SE_RSA_OUTPUT_REG + (i << 2))); return res; } @@ -263,54 +263,54 @@ int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_siz void se_key_acc_ctrl(u32 ks, u32 flags) { if (flags & SE_KEY_TBL_DIS_KEY_ACCESS_FLAG) - SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 4 * ks) = ~flags; - if (flags & SE_KEY_TBL_DIS_KEY_LOCK_FLAG) - SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) &= ~BIT(ks); + SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + 4 * ks) = ~flags; + if (flags & SE_KEY_LOCK_FLAG) + SE(SE_CRYPTO_SECURITY_PERKEY_REG) &= ~BIT(ks); } u32 se_key_acc_ctrl_get(u32 ks) { - return SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 4 * ks); + return SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + 4 * ks); } void se_aes_key_set(u32 ks, const void *key, u32 size) { - u32 data[TEGRA_SE_AES_MAX_KEY_SIZE / 4]; + u32 data[SE_AES_MAX_KEY_SIZE / 4]; memcpy(data, key, size); for (u32 i = 0; i < (size / 4); i++) { - SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i; - SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i]; + SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT. + SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data[i]; } } void se_aes_key_partial_set(u32 ks, u32 index, u32 data) { - SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | index; - SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data; + SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | index; + SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data; } void se_aes_iv_set(u32 ks, const void *iv) { - u32 data[TEGRA_SE_AES_BLOCK_SIZE / 4]; - memcpy(data, iv, TEGRA_SE_AES_BLOCK_SIZE); + u32 data[SE_AES_IV_SIZE / 4]; + memcpy(data, iv, SE_AES_IV_SIZE); - for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++) + for (u32 i = 0; i < (SE_AES_IV_SIZE / 4); i++) { - SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(QUAD_ORG_IV) | i; - SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i]; + SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i); + SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data[i]; } } void se_aes_key_get(u32 ks, void *key, u32 size) { - u32 data[TEGRA_SE_AES_MAX_KEY_SIZE / 4]; + u32 data[SE_AES_MAX_KEY_SIZE / 4]; for (u32 i = 0; i < (size / 4); i++) { - SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i; - data[i] = SE(SE_KEYTABLE_DATA0_REG_OFFSET); + SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT. + data[i] = SE(SE_CRYPTO_KEYTABLE_DATA_REG); } memcpy(key, data, size); @@ -318,77 +318,77 @@ void se_aes_key_get(u32 ks, void *key, u32 size) void se_aes_key_clear(u32 ks) { - for (u32 i = 0; i < (TEGRA_SE_AES_MAX_KEY_SIZE / 4); i++) + for (u32 i = 0; i < (SE_AES_MAX_KEY_SIZE / 4); i++) { - SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i; - SE(SE_KEYTABLE_DATA0_REG_OFFSET) = 0; + SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT. + SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0; } } void se_aes_iv_clear(u32 ks) { - for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++) + for (u32 i = 0; i < (SE_AES_IV_SIZE / 4); i++) { - SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(QUAD_ORG_IV) | i; - SE(SE_KEYTABLE_DATA0_REG_OFFSET) = 0; + SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i); + SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0; } } int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input) { - SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTAB); - SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT); - SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; - SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst); + SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTABLE); + SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT); + SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1; + SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst) | SE_KEYTABLE_DST_WORD_QUAD(KEYS_0_3); - return _se_execute_oneshot(OP_START, NULL, 0, input, 0x10); + return _se_execute_oneshot(SE_OP_START, NULL, 0, input, SE_KEY_128_SIZE); } int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size) { if (enc) { - SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); - SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT); + SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); + SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT); } else { - SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY); - SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT); + SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY); + SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT); } - SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1; - return _se_execute_oneshot(OP_START, dst, dst_size, src, src_size); + SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1; + return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size); } int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size) { if (enc) { - SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); - SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | + SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); + SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_TOP); } else { - SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY); - SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVAHB) | + SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY); + SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVMEM) | 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_oneshot(OP_START, dst, dst_size, src, src_size); + SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1; + return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size); } int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src) { - return se_aes_crypt_ecb(ks, enc, dst, 0x10, src, 0x10); + return se_aes_crypt_ecb(ks, enc, dst, SE_AES_BLOCK_SIZE, src, SE_AES_BLOCK_SIZE); } int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr) { - SE(SE_SPARE_0_REG_OFFSET) = 1; - SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); - SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | - SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_VAL(1); + SE(SE_SPARE_REG) = SE_ECO(SE_ERRATA_FIX_ENABLE); + SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); + SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | + SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_CNTN(1); _se_aes_ctr_set(ctr); u32 src_size_aligned = src_size & 0xFFFFFFF0; @@ -396,13 +396,13 @@ 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_oneshot(OP_START, dst, dst_size, src, src_size_aligned)) + SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1; + if (!_se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size_aligned)) return 0; } if (src_size - src_size_aligned && src_size_aligned < dst_size) - return _se_execute_one_block(OP_START, dst + src_size_aligned, + return _se_execute_one_block(SE_OP_START, dst + src_size_aligned, MIN(src_size_delta, dst_size - src_size_aligned), src + src_size_aligned, src_size_delta); @@ -419,15 +419,15 @@ int se_initialize_rng() u8 *output_buf = (u8 *)malloc(0x10); - SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY); - SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); - SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_FORCE_INSTANTION) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY); - SE(SE_RNG_RESEED_INTERVAL_REG_OFFSET) = 70001; - SE(SE_RNG_SRC_CONFIG_REG_OFFSET) = SE_RNG_SRC_CONFIG_ENT_SRC(RNG_SRC_RO_ENT_ENABLE) | - SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(RNG_SRC_RO_ENT_LOCK_ENABLE); - SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; + SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY); + SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); + SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_MODE(MODE_FORCE_INSTANTION) | SE_RNG_CONFIG_SRC(SRC_ENTROPY); + SE(SE_RNG_RESEED_INTERVAL_REG) = 70001; + SE(SE_RNG_SRC_CONFIG_REG) = SE_RNG_SRC_CONFIG_ENTR_SRC(RO_ENTR_ENABLE) | + SE_RNG_SRC_CONFIG_ENTR_SRC_LOCK(RO_ENTR_LOCK_ENABLE); + SE(SE_CRYPTO_BLOCK_COUNT_REG) = 0; - int res =_se_execute_oneshot(OP_START, output_buf, 0x10, NULL, 0); + int res =_se_execute_oneshot(SE_OP_START, output_buf, 0x10, NULL, 0); free(output_buf); if (res) @@ -437,35 +437,35 @@ int se_initialize_rng() int se_generate_random(void *dst, u32 size) { - SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY); - SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); - SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_NORMAL) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY); + SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY); + SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); + SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_MODE(MODE_NORMAL) | SE_RNG_CONFIG_SRC(SRC_ENTROPY); u32 num_blocks = size >> 4; u32 aligned_size = num_blocks << 4; if (num_blocks) { - SE(SE_BLOCK_COUNT_REG_OFFSET) = num_blocks - 1; - if (!_se_execute_oneshot(OP_START, dst, aligned_size, NULL, 0)) + SE(SE_CRYPTO_BLOCK_COUNT_REG) = num_blocks - 1; + if (!_se_execute_oneshot(SE_OP_START, dst, aligned_size, NULL, 0)) return 0; } if (size > aligned_size) - return _se_execute_one_block(OP_START, dst + aligned_size, size - aligned_size, NULL, 0); + return _se_execute_one_block(SE_OP_START, dst + aligned_size, size - aligned_size, NULL, 0); return 1; } int se_generate_random_key(u32 ks_dst, u32 ks_src) { - SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY); - SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | + SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY); + SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); - SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_NORMAL) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY); + SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_MODE(MODE_NORMAL) | SE_RNG_CONFIG_SRC(SRC_ENTROPY); - SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst); - if (!_se_execute_oneshot(OP_START, NULL, 0, NULL, 0)) + SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst); + if (!_se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0)) return 0; - SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst) | 1; - if (!_se_execute_oneshot(OP_START, NULL, 0, NULL, 0)) + SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst) | 1; + if (!_se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0)) return 0; return 1; @@ -544,8 +544,8 @@ int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size) if (src_size & 0xF) _gf256_mul_x(key); - SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_HASHREG); - SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_INPUT_SEL(INPUT_AHB) | + SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_HASHREG); + SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_INPUT_SEL(INPUT_MEMORY) | SE_CRYPTO_XOR_POS(XOR_TOP) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | SE_CRYPTO_HASH(HASH_ENABLE) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT); se_aes_iv_clear(ks); @@ -553,10 +553,10 @@ int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size) u32 num_blocks = (src_size + 0xf) >> 4; if (num_blocks > 1) { - SE(SE_BLOCK_COUNT_REG_OFFSET) = num_blocks - 2; - if (!_se_execute_oneshot(OP_START, NULL, 0, src, src_size)) + SE(SE_CRYPTO_BLOCK_COUNT_REG) = num_blocks - 2; + if (!_se_execute_oneshot(SE_OP_START, NULL, 0, src, src_size)) goto out; - SE(SE_CRYPTO_REG_OFFSET) |= SE_CRYPTO_IV_SEL(IV_UPDATED); + SE(SE_CRYPTO_CONFIG_REG) |= SE_CRYPTO_IV_SEL(IV_UPDATED); } if (src_size & 0xf) @@ -572,12 +572,12 @@ int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size) for (u32 i = 0; i < 0x10; i++) last_block[i] ^= key[i]; - SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; - res = _se_execute_oneshot(OP_START, NULL, 0, last_block, 0x10); + SE(SE_CRYPTO_BLOCK_COUNT_REG) = 0; + res = _se_execute_oneshot(SE_OP_START, NULL, 0, last_block, 0x10); u32 *dst32 = (u32 *)dst; for (u32 i = 0; i < (dst_size >> 2); i++) - dst32[i] = SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)); + dst32[i] = SE(SE_HASH_RESULT_REG + (i << 2)); out:; free(key); @@ -588,62 +588,62 @@ out:; 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; - u32 hash32[TEGRA_SE_SHA_256_SIZE / 4]; + u32 hash32[SE_SHA_256_SIZE / 4]; //! TODO: src_size must be 512 bit aligned if continuing and not last block for SHA256. if (src_size > 0xFFFFFF || !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_cfg; - SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; + SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG); + SE(SE_SHA_CONFIG_REG) = sha_cfg; + SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1; // 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_LENGTH_0_REG) = (u32)(total_size << 3); + SE(SE_SHA_MSG_LENGTH_1_REG) = (u32)(total_size >> 29); + SE(SE_SHA_MSG_LENGTH_2_REG) = 0; + SE(SE_SHA_MSG_LENGTH_3_REG) = 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; + SE(SE_SHA_MSG_LEFT_0_REG) = (u32)(total_size << 3); + SE(SE_SHA_MSG_LEFT_1_REG) = (u32)(total_size >> 29); + SE(SE_SHA_MSG_LEFT_2_REG) = 0; + SE(SE_SHA_MSG_LEFT_3_REG) = 0; // If we hash in chunks, copy over the intermediate. if (sha_cfg == SHA_CONTINUE && msg_left) { // 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]; + SE(SE_SHA_MSG_LEFT_0_REG) = msg_left[0]; + SE(SE_SHA_MSG_LEFT_1_REG) = msg_left[1]; // Restore hash reg. - memcpy(hash32, hash, TEGRA_SE_SHA_256_SIZE); - for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++) - SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)) = byte_swap_32(hash32[i]); + memcpy(hash32, hash, SE_SHA_256_SIZE); + for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++) + SE(SE_HASH_RESULT_REG + (i * 4)) = byte_swap_32(hash32[i]); } // Trigger the operation. - res = _se_execute(OP_START, NULL, 0, src, src_size, is_oneshot); + res = _se_execute(SE_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); + msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG); + msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG); } // Copy output hash. - for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++) - hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2))); - memcpy(hash, hash32, TEGRA_SE_SHA_256_SIZE); + for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++) + hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG + (i * 4))); + memcpy(hash, hash32, SE_SHA_256_SIZE); } return res; @@ -656,20 +656,20 @@ int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size) int se_calc_sha256_finalize(void *hash, u32 *msg_left) { - u32 hash32[TEGRA_SE_SHA_256_SIZE / 4]; + u32 hash32[SE_SHA_256_SIZE / 4]; 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); + msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG); + msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG); } // Copy output hash. - for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++) - hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2))); - memcpy(hash, hash32, TEGRA_SE_SHA_256_SIZE); + for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++) + hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG + (i << 2))); + memcpy(hash, hash32, SE_SHA_256_SIZE); return res; } @@ -793,43 +793,43 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize) u8 *aligned_buf = (u8 *)ALIGN((u32)buf, 0x40); // Set Secure Random Key. - SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_SRK); - 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_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_SRK); + SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(0) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); + SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_SRC(SRC_ENTROPY) | SE_RNG_CONFIG_MODE(MODE_FORCE_RESEED); SE(SE_CRYPTO_LAST_BLOCK) = 0; - _se_execute_oneshot(OP_START, NULL, 0, NULL, 0); + _se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0); // 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); + SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); - for (u32 i = 0; i < TEGRA_SE_KEYSLOT_COUNT; i++) + for (u32 i = 0; i < SE_AES_KEYSLOT_COUNT; i++) { - SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(AES_KEYTABLE) | - (i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_0_3); + SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) | + SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_0_3); SE(SE_CRYPTO_LAST_BLOCK) = 0; - _se_execute_oneshot(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0); - memcpy(keys + i * keysize, aligned_buf, 0x10); + _se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0); + memcpy(keys + i * keysize, aligned_buf, SE_AES_BLOCK_SIZE); - if (keysize > 0x10) + if (keysize > SE_KEY_128_SIZE) { - SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(AES_KEYTABLE) | - (i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_4_7); + SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) | + SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_4_7); SE(SE_CRYPTO_LAST_BLOCK) = 0; - _se_execute_oneshot(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0); - memcpy(keys + i * keysize + 0x10, aligned_buf, 0x10); + _se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0); + memcpy(keys + i * keysize + SE_AES_BLOCK_SIZE, aligned_buf, SE_AES_BLOCK_SIZE); } } // Save SRK to PMC secure scratches. - SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(SRK); - SE(SE_CRYPTO_LAST_BLOCK) = 0; - _se_execute_oneshot(OP_CTX_SAVE, NULL, 0, NULL, 0); + SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(SRK); + SE(SE_CRYPTO_LAST_BLOCK) = 0; + _se_execute_oneshot(SE_OP_CTX_SAVE, NULL, 0, NULL, 0); // End context save. - SE(SE_CONFIG_REG_OFFSET) = 0; - _se_execute_oneshot(OP_CTX_SAVE, NULL, 0, NULL, 0); + SE(SE_CONFIG_REG) = 0; + _se_execute_oneshot(SE_OP_CTX_SAVE, NULL, 0, NULL, 0); // Get SRK. u32 srk[4]; @@ -840,7 +840,7 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize) // Decrypt context. se_aes_key_clear(3); - se_aes_key_set(3, srk, 0x10); - se_aes_crypt_cbc(3, 0, keys, TEGRA_SE_KEYSLOT_COUNT * keysize, keys, TEGRA_SE_KEYSLOT_COUNT * keysize); + se_aes_key_set(3, srk, SE_KEY_128_SIZE); + se_aes_crypt_cbc(3, 0, keys, SE_AES_KEYSLOT_COUNT * keysize, keys, SE_AES_KEYSLOT_COUNT * keysize); se_aes_key_clear(3); } diff --git a/bdk/sec/se.h b/bdk/sec/se.h index 400d865..a52fd53 100644 --- a/bdk/sec/se.h +++ b/bdk/sec/se.h @@ -1,5 +1,7 @@ /* * Copyright (c) 2018 naehrwert +* Copyright (c) 2019-2021 CTCaer +* Copyright (c) 2019-2021 shchmue * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -25,6 +27,7 @@ void se_rsa_key_clear(u32 ks); int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size); void se_key_acc_ctrl(u32 ks, u32 flags); u32 se_key_acc_ctrl_get(u32 ks); +void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize); void se_aes_key_set(u32 ks, const void *key, u32 size); void se_aes_iv_set(u32 ks, const void *iv); void se_aes_key_partial_set(u32 ks, u32 index, u32 data); @@ -35,10 +38,10 @@ int se_initialize_rng(); int se_generate_random(void *dst, u32 size); int se_generate_random_key(u32 ks_dst, u32 ks_src); int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input); +int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size); 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_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size); int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size); int se_aes_xts_crypt(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size, u32 num_secs); int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size); @@ -47,6 +50,5 @@ 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_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size); u32 se_rsa_oaep_decode(void *dst, u32 dst_size, const void *label_digest, u32 label_digest_size, u8 *buf, u32 buf_size); -void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize); #endif diff --git a/bdk/sec/se_t210.h b/bdk/sec/se_t210.h index 6fbf1b0..0233e1d 100644 --- a/bdk/sec/se_t210.h +++ b/bdk/sec/se_t210.h @@ -1,400 +1,323 @@ /* -* Driver for Tegra Security Engine -* -* Copyright (c) 2011-2013, NVIDIA Corporation. All Rights Reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along -* with this program; if not, write to the Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018-2021 CTCaer + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ -#ifndef _CRYPTO_TEGRA_SE_H -#define _CRYPTO_TEGRA_SE_H +#ifndef _SE_T210_H +#define _SE_T210_H #include -#define TEGRA_SE_CRA_PRIORITY 300 -#define TEGRA_SE_COMPOSITE_PRIORITY 400 -#define TEGRA_SE_CRYPTO_QUEUE_LENGTH 50 -#define SE_MAX_SRC_SG_COUNT 50 -#define SE_MAX_DST_SG_COUNT 50 +#define SE_CRYPTO_QUEUE_LENGTH 50 +#define SE_MAX_SRC_SG_COUNT 50 +#define SE_MAX_DST_SG_COUNT 50 -#define TEGRA_SE_KEYSLOT_COUNT 16 -#define SE_MAX_LAST_BLOCK_SIZE 0xFFFFF +#define SE_AES_KEYSLOT_COUNT 16 +#define SE_RSA_KEYSLOT_COUNT 2 +#define SE_MAX_LAST_BLOCK_SIZE 0xFFFFF + +#define SE_AES_BLOCK_SIZE 16 +#define SE_AES_IV_SIZE 16 +#define SE_AES_MIN_KEY_SIZE 16 +#define SE_AES_MAX_KEY_SIZE 32 +#define SE_KEY_128_SIZE 16 +#define SE_KEY_192_SIZE 24 +#define SE_KEY_256_SIZE 32 +#define SE_SHA_192_SIZE 24 +#define SE_SHA_256_SIZE 32 +#define SE_SHA_384_SIZE 48 +#define SE_SHA_512_SIZE 64 +#define SE_RNG_IV_SIZE 16 +#define SE_RNG_DT_SIZE 16 +#define SE_RNG_KEY_SIZE 16 +#define SE_RNG_SEED_SIZE (SE_RNG_IV_SIZE + SE_RNG_KEY_SIZE + SE_RNG_DT_SIZE) + +#define SE_AES_CMAC_DIGEST_SIZE 16 +#define SE_RSA512_DIGEST_SIZE 64 +#define SE_RSA1024_DIGEST_SIZE 128 +#define SE_RSA1536_DIGEST_SIZE 192 +#define SE_RSA2048_DIGEST_SIZE 256 /* SE register definitions */ -#define SE_SECURITY_0 0x000 -#define SE_KEY_SCHED_READ_SHIFT 3 +#define SE_SE_SECURITY_REG 0x000 +#define SE_HARD_SETTING BIT(0) +#define SE_ENG_DIS BIT(1) +#define SE_PERKEY_SETTING BIT(2) +#define SE_SOFT_SETTING BIT(16) -#define SE_TZRAM_SECURITY_0 0x004 +#define SE_TZRAM_SECURITY_REG 0x004 +#define SE_TZRAM_HARD_SETTING BIT(0) +#define SE_TZRAM_ENG_DIS BIT(1) -#define SE_CONFIG_REG_OFFSET 0x014 -#define SE_CONFIG_ENC_ALG_SHIFT 12 -#define SE_CONFIG_DEC_ALG_SHIFT 8 -#define ALG_AES_ENC 1 -#define ALG_RNG 2 -#define ALG_SHA 3 -#define ALG_RSA 4 -#define ALG_NOP 0 -#define ALG_AES_DEC 1 -#define SE_CONFIG_ENC_ALG(x) ((x) << SE_CONFIG_ENC_ALG_SHIFT) -#define SE_CONFIG_DEC_ALG(x) ((x) << SE_CONFIG_DEC_ALG_SHIFT) -#define SE_CONFIG_DST_SHIFT 2 -#define DST_MEMORY 0 -#define DST_HASHREG 1 -#define DST_KEYTAB 2 -#define DST_SRK 3 -#define DST_RSAREG 4 -#define SE_CONFIG_DST(x) ((x) << SE_CONFIG_DST_SHIFT) -#define SE_CONFIG_ENC_MODE_SHIFT 24 -#define SE_CONFIG_DEC_MODE_SHIFT 16 -#define MODE_KEY128 0 -#define MODE_KEY192 1 -#define MODE_KEY256 2 -#define MODE_SHA1 0 -#define MODE_SHA224 4 -#define MODE_SHA256 5 -#define MODE_SHA384 6 -#define MODE_SHA512 7 -#define SE_CONFIG_ENC_MODE(x) ((x) << SE_CONFIG_ENC_MODE_SHIFT) -#define SE_CONFIG_DEC_MODE(x) ((x) << SE_CONFIG_DEC_MODE_SHIFT) +#define SE_OPERATION_REG 0x008 +#define SE_OP_ABORT 0 +#define SE_OP_START 1 +#define SE_OP_RESTART_OUT 2 +#define SE_OP_CTX_SAVE 3 +#define SE_OP_RESTART_IN 4 -#define SE_RNG_CONFIG_REG_OFFSET 0x340 -#define RNG_MODE_SHIFT 0 -#define RNG_MODE_NORMAL 0 -#define RNG_MODE_FORCE_INSTANTION 1 -#define RNG_MODE_FORCE_RESEED 2 -#define SE_RNG_CONFIG_MODE(x) ((x) << RNG_MODE_SHIFT) -#define RNG_SRC_SHIFT 2 -#define RNG_SRC_NONE 0 -#define RNG_SRC_ENTROPY 1 -#define RNG_SRC_LFSR 2 -#define SE_RNG_CONFIG_SRC(x) ((x) << RNG_SRC_SHIFT) +#define SE_INT_ENABLE_REG 0x00C +#define SE_INT_STATUS_REG 0x010 +#define SE_INT_IN_LL_BUF_RD BIT(0) +#define SE_INT_IN_DONE BIT(1) +#define SE_INT_OUT_LL_BUF_WR BIT(2) +#define SE_INT_OUT_DONE BIT(3) +#define SE_INT_OP_DONE BIT(4) +#define SE_INT_RESEED_NEEDED BIT(5) +#define SE_INT_ERR_STAT BIT(16) -#define SE_RNG_SRC_CONFIG_REG_OFFSET 0x344 -#define RNG_SRC_RO_ENT_SHIFT 1 -#define RNG_SRC_RO_ENT_ENABLE 1 -#define RNG_SRC_RO_ENT_DISABLE 0 -#define SE_RNG_SRC_CONFIG_ENT_SRC(x) ((x) << RNG_SRC_RO_ENT_SHIFT) -#define RNG_SRC_RO_ENT_LOCK_SHIFT 0 -#define RNG_SRC_RO_ENT_LOCK_ENABLE 1 -#define RNG_SRC_RO_ENT_LOCK_DISABLE 0 -#define SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(x) ((x) << RNG_SRC_RO_ENT_LOCK_SHIFT) +#define SE_CONFIG_REG 0x014 +#define DST_MEMORY 0 +#define DST_HASHREG 1 +#define DST_KEYTABLE 2 +#define DST_SRK 3 +#define DST_RSAREG 4 +#define SE_CONFIG_DST(x) ((x) << 2) +#define ALG_NOP 0 +#define ALG_AES_DEC 1 +#define SE_CONFIG_DEC_ALG(x) ((x) << 8) +#define ALG_NOP 0 +#define ALG_AES_ENC 1 +#define ALG_RNG 2 +#define ALG_SHA 3 +#define ALG_RSA 4 +#define SE_CONFIG_ENC_ALG(x) ((x) << 12) +#define MODE_KEY128 0 +#define MODE_KEY192 1 +#define MODE_KEY256 2 +#define MODE_SHA1 0 +#define MODE_SHA224 4 +#define MODE_SHA256 5 +#define MODE_SHA384 6 +#define MODE_SHA512 7 +#define SE_CONFIG_DEC_MODE(x) ((x) << 16) +#define SE_CONFIG_ENC_MODE(x) ((x) << 24) -#define SE_RNG_RESEED_INTERVAL_REG_OFFSET 0x348 +#define SE_IN_LL_ADDR_REG 0x018 +#define SE_IN_CUR_BYTE_ADDR_REG 0x01C +#define SE_IN_CUR_LL_ID_REG 0x020 +#define SE_OUT_LL_ADDR_REG 0x024 +#define SE_OUT_CUR_BYTE_ADDR_REG 0x028 +#define SE_OUT_CUR_LL_ID_REG 0x02C -#define SE_KEYTABLE_REG_OFFSET 0x31c -#define SE_KEYTABLE_SLOT_SHIFT 4 -#define SE_KEYTABLE_SLOT(x) ((x) << SE_KEYTABLE_SLOT_SHIFT) -#define SE_KEYTABLE_QUAD_SHIFT 2 -#define QUAD_KEYS_128 0 -#define QUAD_KEYS_192 1 -#define QUAD_KEYS_256 1 -#define QUAD_ORG_IV 2 -#define QUAD_UPDTD_IV 3 -#define SE_KEYTABLE_QUAD(x) ((x) << SE_KEYTABLE_QUAD_SHIFT) -#define SE_KEYTABLE_OP_TYPE_SHIFT 9 -#define OP_READ 0 -#define OP_WRITE 1 -#define SE_KEYTABLE_OP_TYPE(x) ((x) << SE_KEYTABLE_OP_TYPE_SHIFT) -#define SE_KEYTABLE_TABLE_SEL_SHIFT 8 -#define TABLE_KEYIV 0 -#define TABLE_SCHEDULE 1 -#define SE_KEYTABLE_TABLE_SEL(x) ((x) << SE_KEYTABLE_TABLE_SEL_SHIFT) -#define SE_KEYTABLE_PKT_SHIFT 0 -#define SE_KEYTABLE_PKT(x) ((x) << SE_KEYTABLE_PKT_SHIFT) +#define SE_HASH_RESULT_REG 0x030 +#define SE_HASH_RESULT_REG_COUNT 16 -#define SE_OP_DONE_SHIFT 4 -#define OP_DONE 1 -#define SE_OP_DONE(x, y) ((x) && ((y) << SE_OP_DONE_SHIFT)) +#define SE_CONTEXT_SAVE_CONFIG_REG 0x070 +#define KEYS_0_3 0 +#define KEYS_4_7 1 +#define ORIGINAL_IV 2 +#define UPDATED_IV 3 +#define SE_CONTEXT_AES_WORD_QUAD(x) ((x) << 0) +#define SE_CONTEXT_AES_KEY_INDEX(x) ((x) << 8) +#define KEYS_0_3 0 +#define KEYS_4_7 1 +#define KEYS_8_11 2 +#define KEYS_12_15 3 +#define SE_CONTEXT_RSA_WORD_QUAD(x) ((x) << 12) +#define SLOT0_EXPONENT 0 +#define SLOT0_MODULUS 1 +#define SLOT1_EXPONENT 2 +#define SLOT1_MODULUS 3 +#define SE_CONTEXT_RSA_KEY_INDEX(x) ((x) << 16) +#define STICKY_0_3 0 +#define STICKY_4_7 1 +#define SE_CONTEXT_STICKY_WORD_QUAD(x) ((x) << 24) +#define STICKY_BITS 0 +#define RSA_KEYTABLE 1 +#define AES_KEYTABLE 2 +#define MEM 4 +#define SRK 6 +#define SE_CONTEXT_SRC(x) ((x) << 29) -#define SE_CRYPTO_LAST_BLOCK 0x080 +#define SE_CTX_SAVE_AUTO_T210B01_REG 0x074 +#define SE_CTX_SAVE_AUTO_ENABLE BIT(0) +#define SE_CTX_SAVE_AUTO_LOCK BIT(8) +#define SE_CTX_SAVE_AUTO_CURR_CNT_MASK (0x3FF << 16) -#define SE_CRYPTO_REG_OFFSET 0x304 -#define SE_CRYPTO_HASH_SHIFT 0 -#define HASH_DISABLE 0 -#define HASH_ENABLE 1 -#define SE_CRYPTO_HASH(x) ((x) << SE_CRYPTO_HASH_SHIFT) -#define SE_CRYPTO_XOR_POS_SHIFT 1 -#define XOR_BYPASS 0 -#define XOR_TOP 2 -#define XOR_BOTTOM 3 -#define SE_CRYPTO_XOR_POS(x) ((x) << SE_CRYPTO_XOR_POS_SHIFT) -#define SE_CRYPTO_INPUT_SEL_SHIFT 3 -#define INPUT_AHB 0 -#define INPUT_RANDOM 1 -#define INPUT_AESOUT 2 -#define INPUT_LNR_CTR 3 -#define SE_CRYPTO_INPUT_SEL(x) ((x) << SE_CRYPTO_INPUT_SEL_SHIFT) -#define SE_CRYPTO_VCTRAM_SEL_SHIFT 5 -#define VCTRAM_AHB 0 -#define VCTRAM_AESOUT 2 -#define VCTRAM_PREVAHB 3 -#define SE_CRYPTO_VCTRAM_SEL(x) ((x) << SE_CRYPTO_VCTRAM_SEL_SHIFT) -#define SE_CRYPTO_IV_SEL_SHIFT 7 -#define IV_ORIGINAL 0 -#define IV_UPDATED 1 -#define SE_CRYPTO_IV_SEL(x) ((x) << SE_CRYPTO_IV_SEL_SHIFT) -#define SE_CRYPTO_CORE_SEL_SHIFT 8 -#define CORE_DECRYPT 0 -#define CORE_ENCRYPT 1 -#define SE_CRYPTO_CORE_SEL(x) ((x) << SE_CRYPTO_CORE_SEL_SHIFT) -#define SE_CRYPTO_CTR_VAL_SHIFT 11 -#define SE_CRYPTO_CTR_VAL(x) ((x) << SE_CRYPTO_CTR_VAL_SHIFT) -#define SE_CRYPTO_KEY_INDEX_SHIFT 24 -#define SE_CRYPTO_KEY_INDEX(x) ((x) << SE_CRYPTO_KEY_INDEX_SHIFT) -#define SE_CRYPTO_CTR_CNTN_SHIFT 11 -#define SE_CRYPTO_CTR_CNTN(x) ((x) << SE_CRYPTO_CTR_CNTN_SHIFT) +#define SE_CRYPTO_LAST_BLOCK 0x080 -#define SE_CRYPTO_CTR_REG_COUNT 4 -#define SE_CRYPTO_CTR_REG_OFFSET 0x308 - -#define SE_OPERATION_REG_OFFSET 0x008 -#define SE_OPERATION_SHIFT 0 -#define OP_ABORT 0 -#define OP_START 1 -#define OP_RESTART 2 -#define OP_CTX_SAVE 3 -#define OP_RESTART_IN 4 -#define SE_OPERATION(x) ((x) << SE_OPERATION_SHIFT) - -#define SE_CONTEXT_SAVE_CONFIG_REG_OFFSET 0x070 -#define SE_CONTEXT_SAVE_WORD_QUAD_SHIFT 0 -#define KEYS_0_3 0 -#define KEYS_4_7 1 -#define ORIG_IV 2 -#define UPD_IV 3 -#define SE_CONTEXT_SAVE_WORD_QUAD(x) ((x) << SE_CONTEXT_SAVE_WORD_QUAD_SHIFT) - -#define SE_CONTEXT_SAVE_KEY_INDEX_SHIFT 8 -#define SE_CONTEXT_SAVE_KEY_INDEX(x) ((x) << SE_CONTEXT_SAVE_KEY_INDEX_SHIFT) - -#define SE_CONTEXT_SAVE_STICKY_WORD_QUAD_SHIFT 24 -#define STICKY_0_3 0 -#define STICKY_4_7 1 -#define SE_CONTEXT_SAVE_STICKY_WORD_QUAD(x) \ - ((x) << SE_CONTEXT_SAVE_STICKY_WORD_QUAD_SHIFT) - -#define SE_CONTEXT_SAVE_SRC_SHIFT 29 -#define STICKY_BITS 0 -#define KEYTABLE 2 -#define MEM 4 -#define SRK 6 - -#define RSA_KEYTABLE 1 -#define AES_KEYTABLE 2 -#define SE_CONTEXT_SAVE_SRC(x) ((x) << SE_CONTEXT_SAVE_SRC_SHIFT) - -#define SE_CONTEXT_SAVE_RSA_KEY_INDEX_SHIFT 16 -#define SE_CONTEXT_SAVE_RSA_KEY_INDEX(x) \ - ((x) << SE_CONTEXT_SAVE_RSA_KEY_INDEX_SHIFT) - -#define SE_CONTEXT_RSA_WORD_QUAD_SHIFT 12 -#define SE_CONTEXT_RSA_WORD_QUAD(x) \ - ((x) << SE_CONTEXT_RSA_WORD_QUAD_SHIFT) - -#define SE_CTX_SAVE_AUTO 0x074 -#define CTX_SAVE_AUTO_ENABLE BIT(0) -#define CTX_SAVE_AUTO_LOCK BIT(8) -#define CTX_SAVE_AUTO_CURR_CNT_MASK (0x3FF << 16) - -#define SE_INT_ENABLE_REG_OFFSET 0x00c -#define SE_INT_STATUS_REG_OFFSET 0x010 -#define INT_DISABLE 0 -#define INT_ENABLE 1 -#define INT_UNSET 0 -#define INT_SET 1 -#define SE_INT_OP_DONE_SHIFT 4 -#define SE_INT_OP_DONE(x) ((x) << SE_INT_OP_DONE_SHIFT) -#define SE_INT_ERROR_SHIFT 16 -#define SE_INT_ERROR(x) ((x) << SE_INT_ERROR_SHIFT) - -#define SE_STATUS_0 0x800 -#define SE_STATUS_0_STATE_WAIT_IN 3 - -#define SE_ERR_STATUS_0 0x804 -#define SE_ERR_STATUS_0_SE_NS_ACCESS_CLEAR 0 - -#define SE_CRYPTO_KEYTABLE_DST_REG_OFFSET 0X330 -#define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT 0 -#define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD(x) \ - ((x) << SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT) - -#define SE_KEY_INDEX_SHIFT 8 -#define SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(x) ((x) << SE_KEY_INDEX_SHIFT) - -#define SE_IN_LL_ADDR_REG_OFFSET 0x018 -#define SE_OUT_LL_ADDR_REG_OFFSET 0x024 - -#define SE_KEYTABLE_DATA0_REG_OFFSET 0x320 -#define SE_KEYTABLE_REG_MAX_DATA 16 - -#define SE_BLOCK_COUNT_REG_OFFSET 0x318 - -#define SE_SPARE_0_REG_OFFSET 0x80c - -#define SE_SHA_CONFIG_REG_OFFSET 0x200 +#define SE_SHA_CONFIG_REG 0x200 #define SHA_CONTINUE 0 #define SHA_INIT_HASH 1 -#define SE_SHA_MSG_LENGTH_0_REG_OFFSET 0x204 -#define SE_SHA_MSG_LENGTH_1_REG_OFFSET 0x208 -#define SE_SHA_MSG_LENGTH_2_REG_OFFSET 0x20C -#define SE_SHA_MSG_LENGTH_3_REG_OFFSET 0x210 -#define SE_SHA_MSG_LEFT_0_REG_OFFSET 0x214 -#define SE_SHA_MSG_LEFT_1_REG_OFFSET 0x218 -#define SE_SHA_MSG_LEFT_2_REG_OFFSET 0x21C -#define SE_SHA_MSG_LEFT_3_REG_OFFSET 0x220 +#define SE_SHA_MSG_LENGTH_0_REG 0x204 +#define SE_SHA_MSG_LENGTH_1_REG 0x208 +#define SE_SHA_MSG_LENGTH_2_REG 0x20C +#define SE_SHA_MSG_LENGTH_3_REG 0x210 +#define SE_SHA_MSG_LEFT_0_REG 0x214 +#define SE_SHA_MSG_LEFT_1_REG 0x218 +#define SE_SHA_MSG_LEFT_2_REG 0x21C +#define SE_SHA_MSG_LEFT_3_REG 0x220 -#define SE_HASH_RESULT_REG_COUNT 16 -#define SE_HASH_RESULT_REG_OFFSET 0x030 -#define TEGRA_SE_KEY_256_SIZE 32 -#define TEGRA_SE_KEY_192_SIZE 24 -#define TEGRA_SE_KEY_128_SIZE 16 -#define TEGRA_SE_AES_BLOCK_SIZE 16 -#define TEGRA_SE_AES_MIN_KEY_SIZE 16 -#define TEGRA_SE_AES_MAX_KEY_SIZE 32 -#define TEGRA_SE_AES_IV_SIZE 16 -#define TEGRA_SE_SHA_512_SIZE 64 -#define TEGRA_SE_SHA_384_SIZE 48 -#define TEGRA_SE_SHA_256_SIZE 32 -#define TEGRA_SE_SHA_192_SIZE 24 -#define TEGRA_SE_RNG_IV_SIZE 16 -#define TEGRA_SE_RNG_DT_SIZE 16 -#define TEGRA_SE_RNG_KEY_SIZE 16 -#define TEGRA_SE_RNG_SEED_SIZE (TEGRA_SE_RNG_IV_SIZE + \ - TEGRA_SE_RNG_KEY_SIZE + \ - TEGRA_SE_RNG_DT_SIZE) +#define SE_CRYPTO_SECURITY_PERKEY_REG 0x280 +#define SE_KEY_LOCK_FLAG 0x80 +#define SE_CRYPTO_KEYTABLE_ACCESS_REG 0x284 +#define SE_CRYPTO_KEYTABLE_ACCESS_REG_COUNT 16 +#define SE_KEY_TBL_DIS_KEYREAD_FLAG BIT(0) +#define SE_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1) +#define SE_KEY_TBL_DIS_OIVREAD_FLAG BIT(2) +#define SE_KEY_TBL_DIS_OIVUPDATE_FLAG BIT(3) +#define SE_KEY_TBL_DIS_UIVREAD_FLAG BIT(4) +#define SE_KEY_TBL_DIS_UIVUPDATE_FLAG BIT(5) +#define SE_KEY_TBL_DIS_KEYUSE_FLAG BIT(6) +#define SE_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F -#define TEGRA_SE_AES_CMAC_DIGEST_SIZE 16 -#define TEGRA_SE_RSA512_DIGEST_SIZE 64 -#define TEGRA_SE_RSA1024_DIGEST_SIZE 128 -#define TEGRA_SE_RSA1536_DIGEST_SIZE 192 -#define TEGRA_SE_RSA2048_DIGEST_SIZE 256 +#define SE_CRYPTO_CONFIG_REG 0x304 +#define HASH_DISABLE 0 +#define HASH_ENABLE 1 +#define SE_CRYPTO_HASH(x) ((x) << 0) +#define XOR_BYPASS 0 +#define XOR_TOP 2 +#define XOR_BOTTOM 3 +#define SE_CRYPTO_XOR_POS(x) ((x) << 1) +#define INPUT_MEMORY 0 +#define INPUT_RANDOM 1 +#define INPUT_AESOUT 2 +#define INPUT_LNR_CTR 3 +#define SE_CRYPTO_INPUT_SEL(x) ((x) << 3) +#define VCTRAM_MEM 0 +#define VCTRAM_AESOUT 2 +#define VCTRAM_PREVMEM 3 +#define SE_CRYPTO_VCTRAM_SEL(x) ((x) << 5) +#define IV_ORIGINAL 0 +#define IV_UPDATED 1 +#define SE_CRYPTO_IV_SEL(x) ((x) << 7) +#define CORE_DECRYPT 0 +#define CORE_ENCRYPT 1 +#define SE_CRYPTO_CORE_SEL(x) ((x) << 8) +#define SE_CRYPTO_KEYSCH_BYPASS BIT(10) +#define SE_CRYPTO_CTR_CNTN(x) ((x) << 11) +#define SE_CRYPTO_KEY_INDEX(x) ((x) << 24) +#define MEMIF_AHB 0 +#define MEMIF_MCCIF 1 +#define SE_CRYPTO_MEMIF(x) ((x) << 31) -#define SE_KEY_TABLE_ACCESS_LOCK_OFFSET 0x280 -#define SE_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80 +#define SE_CRYPTO_LINEAR_CTR_REG 0x308 +#define SE_CRYPTO_LINEAR_CTR_REG_COUNT 4 -#define SE_KEY_TABLE_ACCESS_REG_OFFSET 0x284 -#define SE_KEY_TBL_DIS_KEYREAD_FLAG BIT(0) -#define SE_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1) -#define SE_KEY_TBL_DIS_OIVREAD_FLAG BIT(2) -#define SE_KEY_TBL_DIS_OIVUPDATE_FLAG BIT(3) -#define SE_KEY_TBL_DIS_UIVREAD_FLAG BIT(4) -#define SE_KEY_TBL_DIS_UIVUPDATE_FLAG BIT(5) -#define SE_KEY_TBL_DIS_KEYUSE_FLAG BIT(6) -#define SE_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F +#define SE_CRYPTO_BLOCK_COUNT_REG 0x318 -#define SE_KEY_READ_DISABLE_SHIFT 0 -#define SE_KEY_UPDATE_DISABLE_SHIFT 1 +#define SE_CRYPTO_KEYTABLE_ADDR_REG 0x31C +#define SE_KEYTABLE_PKT(x) ((x) << 0) +#define KEYS_0_3 0 +#define KEYS_4_7 1 +#define ORIGINAL_IV 2 +#define UPDATED_IV 3 +#define SE_KEYTABLE_QUAD(x) ((x) << 2) +#define SE_KEYTABLE_SLOT(x) ((x) << 4) -#define SE_CONTEXT_BUFER_SIZE 1072 -#define SE_CONTEXT_DRBG_BUFER_SIZE 2112 +#define SE_CRYPTO_KEYTABLE_DATA_REG 0x320 -#define SE_CONTEXT_SAVE_RANDOM_DATA_OFFSET 0 -#define SE_CONTEXT_SAVE_RANDOM_DATA_SIZE 16 -#define SE_CONTEXT_SAVE_STICKY_BITS_OFFSET \ - (SE_CONTEXT_SAVE_RANDOM_DATA_OFFSET + SE_CONTEXT_SAVE_RANDOM_DATA_SIZE) -#define SE_CONTEXT_SAVE_STICKY_BITS_SIZE 16 +#define SE_CRYPTO_KEYTABLE_DST_REG 0x330 +#define KEYS_0_3 0 +#define KEYS_4_7 1 +#define ORIGINAL_IV 2 +#define UPDATED_IV 3 +#define SE_KEYTABLE_DST_WORD_QUAD(x) ((x) << 0) +#define SE_KEYTABLE_DST_KEY_INDEX(x) ((x) << 8) -#define SE_CONTEXT_SAVE_KEYS_OFFSET (SE_CONTEXT_SAVE_STICKY_BITS_OFFSET + \ - SE_CONTEXT_SAVE_STICKY_BITS_SIZE) -#define SE11_CONTEXT_SAVE_KEYS_OFFSET (SE_CONTEXT_SAVE_STICKY_BITS_OFFSET + \ - SE_CONTEXT_SAVE_STICKY_BITS_SIZE + \ - SE_CONTEXT_SAVE_STICKY_BITS_SIZE) +#define SE_RNG_CONFIG_REG 0x340 +#define MODE_NORMAL 0 +#define MODE_FORCE_INSTANTION 1 +#define MODE_FORCE_RESEED 2 +#define SE_RNG_CONFIG_MODE(x) ((x) << 0) +#define SRC_NONE 0 +#define SRC_ENTROPY 1 +#define SRC_LFSR 2 +#define SE_RNG_CONFIG_SRC(x) ((x) << 2) -#define SE_CONTEXT_SAVE_KEY_LENGTH 512 -#define SE_CONTEXT_ORIGINAL_IV_OFFSET (SE_CONTEXT_SAVE_KEYS_OFFSET + \ - SE_CONTEXT_SAVE_KEY_LENGTH) -#define SE11_CONTEXT_ORIGINAL_IV_OFFSET (SE11_CONTEXT_SAVE_KEYS_OFFSET + \ - SE_CONTEXT_SAVE_KEY_LENGTH) +#define SE_RNG_SRC_CONFIG_REG 0x344 +#define RO_ENTR_LOCK_DISABLE 0 +#define RO_ENTR_LOCK_ENABLE 1 +#define SE_RNG_SRC_CONFIG_ENTR_SRC_LOCK(x) ((x) << 0) +#define RO_ENTR_DISABLE 0 +#define RO_ENTR_ENABLE 1 +#define SE_RNG_SRC_CONFIG_ENTR_SRC(x) ((x) << 1) +#define RO_HW_DIS_CYA_DISABLE 0 +#define RO_HW_DIS_CYA_ENABLE 1 +#define SE_RNG_SRC_CONFIG_HW_DIS_CYA(x) ((x) << 2) +#define SE_RNG_SRC_CONFIG_ENTR_SUBSMPL(x) ((x) << 4) +#define SE_RNG_SRC_CONFIG_ENTR_DATA_FLUSH BIT(8) -#define SE_CONTEXT_ORIGINAL_IV_LENGTH 256 +#define SE_RNG_RESEED_INTERVAL_REG 0x348 -#define SE_CONTEXT_UPDATED_IV_OFFSET (SE_CONTEXT_ORIGINAL_IV_OFFSET + \ - SE_CONTEXT_ORIGINAL_IV_LENGTH) -#define SE11_CONTEXT_UPDATED_IV_OFFSET (SE11_CONTEXT_ORIGINAL_IV_OFFSET + \ - SE_CONTEXT_ORIGINAL_IV_LENGTH) +#define SE_RSA_CONFIG 0x400 +#define RSA_KEY_SLOT_ONE 0 +#define RSA_KEY_SLOT_TW0 1 +#define RSA_KEY_SLOT(x) ((x) << 24) -#define SE_CONTEXT_UPDATED_IV_LENGTH 256 +#define SE_RSA_KEY_SIZE_REG 0x404 +#define RSA_KEY_WIDTH_512 0 +#define RSA_KEY_WIDTH_1024 1 +#define RSA_KEY_WIDTH_1536 2 +#define RSA_KEY_WIDTH_2048 3 -#define SE_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET (SE_CONTEXT_UPDATED_IV_OFFSET + \ - SE_CONTEXT_UPDATED_IV_LENGTH) -#define SE11_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET \ - (SE11_CONTEXT_UPDATED_IV_OFFSET + \ - SE_CONTEXT_UPDATED_IV_LENGTH) +#define SE_RSA_EXP_SIZE_REG 0x408 -#define SE_CONTEXT_SAVE_RSA_KEYS_OFFSET SE11_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET +#define SE_RSA_SECURITY_PERKEY_REG 0x40C +#define SE_RSA_KEY_LOCK_FLAG 0x80 +#define SE_RSA_KEYTABLE_ACCESS_REG 0x410 +#define SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG BIT(0) +#define SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1) +#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG BIT(2) +#define SE_RSA_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F +#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG) +#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_USE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG | SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) -#define SE_CONTEXT_SAVE_RSA_KEY_LENGTH 1024 +#define SE_RSA_KEYTABLE_ADDR_REG 0x420 +#define SE_RSA_KEYTABLE_PKT(x) ((x) << 0) +#define RSA_KEY_TYPE_EXP 0 +#define RSA_KEY_TYPE_MOD 1 +#define SE_RSA_KEYTABLE_TYPE(x) ((x) << 6) +#define RSA_KEY_NUM(x) ((x) << 7) +#define RSA_KEY_INPUT_MODE_REG 0 +#define RSA_KEY_INPUT_MODE_DMA 1 +#define SE_RSA_KEYTABLE_INPUT_MODE(x) ((x) << 8) +#define RSA_KEY_READ 0 +#define RSA_KEY_WRITE 1 +#define SE_RSA_KEY_OP(x) ((x) << 10) -#define SE_CONTEXT_SAVE_RSA_KNOWN_PATTERN_OFFSET \ - (SE_CONTEXT_SAVE_RSA_KEYS_OFFSET + SE_CONTEXT_SAVE_RSA_KEY_LENGTH) +#define SE_RSA_KEYTABLE_DATA_REG 0x424 -#define SE_CONTEXT_KNOWN_PATTERN_SIZE 16 +#define SE_RSA_OUTPUT_REG 0x428 +#define SE_RSA_OUTPUT_REG_COUNT 64 -#define TEGRA_SE_RSA_KEYSLOT_COUNT 2 +#define SE_STATUS_REG 0x800 +#define SE_STATUS_STATE_IDLE 0 +#define SE_STATUS_STATE_BUSY 1 +#define SE_STATUS_STATE_WAIT_OUT 2 +#define SE_STATUS_STATE_WAIT_IN 3 +#define SE_STATUS_STATE_MASK 3 -#define SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET 0x40C -#define SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80 +#define SE_ERR_STATUS_REG 0x804 +#define SE_ERR_STATUS_SE_NS_ACCESS BIT(0) +#define SE_ERR_STATUS_BUSY_REG_WR BIT(1) +#define SE_ERR_STATUS_DST BIT(2) +#define SE_ERR_STATUS_SRK_USAGE_LIMIT BIT(3) +#define SE_ERR_STATUS_TZRAM_NS_ACCESS BIT(24) +#define SE_ERR_STATUS_TZRAM_ADDRESS BIT(25) -#define SE_RSA_KEYTABLE_ACCESS_REG_OFFSET 0x410 -#define SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG BIT(0) -#define SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1) -#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG) -#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG BIT(2) -#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT BIT(2) -#define SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG 7 -#define SE_RSA_KEY_TBL_DIS_KEY_ALL_FLAG 0x7F +#define SE_MISC_REG 0x808 +#define SE_ENTROPY_NEXT_192BIT BIT(0) +#define SE_ENTROPY_VN_BYPASS BIT(1) +#define SE_CLK_OVR_ON BIT(2) -#define SE_RSA_KEYTABLE_ADDR 0x420 -#define SE_RSA_KEYTABLE_DATA 0x424 -#define SE_RSA_OUTPUT 0x428 +#define SE_SPARE_REG 0x80C +#define SE_ERRATA_FIX_DISABLE 0 +#define SE_ERRATA_FIX_ENABLE 1 +#define SE_ECO(x) ((x) << 0) -#define RSA_KEY_READ 0 -#define RSA_KEY_WRITE 1 -#define SE_RSA_KEY_OP_SHIFT 10 -#define SE_RSA_KEY_OP(x) ((x) << SE_RSA_KEY_OP_SHIFT) - -#define RSA_KEY_INPUT_MODE_REG 0 -#define RSA_KEY_INPUT_MODE_DMA 1 -#define RSA_KEY_INPUT_MODE_SHIFT 8 -#define RSA_KEY_INPUT_MODE(x) ((x) << RSA_KEY_INPUT_MODE_SHIFT) - -#define RSA_KEY_SLOT_ONE 0 -#define RSA_KEY_SLOT_TW0 1 -#define RSA_KEY_NUM_SHIFT 7 -#define RSA_KEY_NUM(x) ((x) << RSA_KEY_NUM_SHIFT) - -#define RSA_KEY_TYPE_EXP 0 -#define RSA_KEY_TYPE_MOD 1 -#define RSA_KEY_TYPE_SHIFT 6 -#define RSA_KEY_TYPE(x) ((x) << RSA_KEY_TYPE_SHIFT) - -#define SE_RSA_KEY_SIZE_REG_OFFSET 0x404 -#define SE_RSA_EXP_SIZE_REG_OFFSET 0x408 - -#define RSA_KEY_SLOT_SHIFT 24 -#define RSA_KEY_SLOT(x) ((x) << RSA_KEY_SLOT_SHIFT) -#define SE_RSA_CONFIG 0x400 - -#define RSA_KEY_PKT_WORD_ADDR_SHIFT 0 -#define RSA_KEY_PKT_WORD_ADDR(x) ((x) << RSA_KEY_PKT_WORD_ADDR_SHIFT) - -#define RSA_KEY_WORD_ADDR_SHIFT 0 -#define RSA_KEY_WORD_ADDR(x) ((x) << RSA_KEY_WORD_ADDR_SHIFT) - -#define SE_RSA_KEYTABLE_PKT_SHIFT 0 -#define SE_RSA_KEYTABLE_PKT(x) ((x) << SE_RSA_KEYTABLE_PKT_SHIFT) - -#endif /* _CRYPTO_TEGRA_SE_H */ +#endif diff --git a/bdk/sec/tsec.c b/bdk/sec/tsec.c index 3361144..adf5ac2 100644 --- a/bdk/sec/tsec.c +++ b/bdk/sec/tsec.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2019 CTCaer + * Copyright (c) 2018-2021 CTCaer * Copyright (c) 2018 balika011 * * This program is free software; you can redistribute it and/or modify it @@ -70,7 +70,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt) u32 *pkg11_magic_off; bpmp_mmu_disable(); - bpmp_clk_rate_set(BPMP_CLK_NORMAL); + bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL); // Enable clocks. clock_enable_host1x(); @@ -190,7 +190,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt) if (kb == KB_TSEC_FW_EMU_COMPAT) { u32 start = get_tmr_us(); - u32 k = se[SE_KEYTABLE_DATA0_REG_OFFSET / 4]; + u32 k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4]; u32 key[16] = {0}; u32 kidx = 0; @@ -198,9 +198,9 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt) { smmu_flush_all(); - if (k != se[SE_KEYTABLE_DATA0_REG_OFFSET / 4]) + if (k != se[SE_CRYPTO_KEYTABLE_DATA_REG / 4]) { - k = se[SE_KEYTABLE_DATA0_REG_OFFSET / 4]; + k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4]; key[kidx++] = k; } @@ -269,7 +269,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt) SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_MSB) = 0; SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_LSB) = 0; - memcpy(tsec_keys, &buf, 0x10); + memcpy(tsec_keys, &buf, SE_KEY_128_SIZE); } out_free:; @@ -284,7 +284,7 @@ out:; clock_disable_sor_safe(); clock_disable_tsec(); bpmp_mmu_enable(); - bpmp_clk_rate_set(BPMP_CLK_DEFAULT_BOOST); + bpmp_clk_rate_set(prev_fid); return res; } diff --git a/bdk/soc/bpmp.c b/bdk/soc/bpmp.c index 2e1819d..fc0e412 100644 --- a/bdk/soc/bpmp.c +++ b/bdk/soc/bpmp.c @@ -1,7 +1,7 @@ /* * BPMP-Lite Cache/MMU and Frequency driver for Tegra X1 * - * Copyright (c) 2019-2020 CTCaer + * Copyright (c) 2019-2021 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -212,43 +212,45 @@ const u8 pll_divn[] = { //95 // BPMP_CLK_DEV_BOOST: 608MHz 49% - 152MHz APB. }; -bpmp_freq_t bpmp_clock_set = BPMP_CLK_NORMAL; +bpmp_freq_t bpmp_fid_current = BPMP_CLK_NORMAL; void bpmp_clk_rate_get() { bool clk_src_is_pllp = ((CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) >> 4) & 7) == 3; if (clk_src_is_pllp) - bpmp_clock_set = BPMP_CLK_NORMAL; + bpmp_fid_current = BPMP_CLK_NORMAL; else { - bpmp_clock_set = BPMP_CLK_HIGH_BOOST; + bpmp_fid_current = BPMP_CLK_HIGH_BOOST; u8 pll_divn_curr = (CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) >> 10) & 0xFF; for (u32 i = 1; i < sizeof(pll_divn); i++) { if (pll_divn[i] == pll_divn_curr) { - bpmp_clock_set = i; + bpmp_fid_current = i; break; } } } } -void bpmp_clk_rate_set(bpmp_freq_t fid) +bpmp_freq_t bpmp_clk_rate_set(bpmp_freq_t fid) { + bpmp_freq_t prev_fid = bpmp_fid_current; + if (fid > (BPMP_CLK_MAX - 1)) fid = BPMP_CLK_MAX - 1; - if (bpmp_clock_set == fid) - return; + if (prev_fid == fid) + return prev_fid; if (fid) { - if (bpmp_clock_set) + if (prev_fid) { - // Restore to PLLP source during PLLC4 configuration. + // Restore to PLLP source during PLLC configuration. CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; // PLLP_OUT. msleep(1); // Wait a bit for clock source change. } @@ -269,7 +271,10 @@ void bpmp_clk_rate_set(bpmp_freq_t fid) // Disable PLLC to save power. clock_disable_pllc(); } - bpmp_clock_set = fid; + bpmp_fid_current = fid; + + // Return old fid in case of temporary swap. + return prev_fid; } // The following functions halt BPMP to reduce power while sleeping. diff --git a/bdk/soc/bpmp.h b/bdk/soc/bpmp.h index 81f000b..0f80150 100644 --- a/bdk/soc/bpmp.h +++ b/bdk/soc/bpmp.h @@ -1,7 +1,7 @@ /* * BPMP-Lite Cache/MMU and Frequency driver for Tegra X1 * - * Copyright (c) 2019-2020 CTCaer + * Copyright (c) 2019-2021 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -53,6 +53,7 @@ typedef enum BPMP_CLK_MAX } bpmp_freq_t; +#define BPMP_CLK_LOWER_BOOST BPMP_CLK_SUPER_BOOST #define BPMP_CLK_DEFAULT_BOOST BPMP_CLK_HYPER_BOOST void bpmp_mmu_maintenance(u32 op, bool force); @@ -60,7 +61,7 @@ void bpmp_mmu_set_entry(int idx, bpmp_mmu_entry_t *entry, bool apply); void bpmp_mmu_enable(); void bpmp_mmu_disable(); void bpmp_clk_rate_get(); -void bpmp_clk_rate_set(bpmp_freq_t fid); +bpmp_freq_t bpmp_clk_rate_set(bpmp_freq_t fid); void bpmp_usleep(u32 us); void bpmp_msleep(u32 ms); void bpmp_halt(); diff --git a/bdk/soc/ccplex.c b/bdk/soc/ccplex.c index a8d782d..894cb28 100644 --- a/bdk/soc/ccplex.c +++ b/bdk/soc/ccplex.c @@ -16,7 +16,6 @@ */ #include -#include #include #include #include @@ -29,27 +28,24 @@ void _ccplex_enable_power_t210() { - u8 tmp = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO); // Get current pinmuxing - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO, tmp & ~BIT(5)); // Disable GPIO5 pinmuxing. - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO5, MAX77620_CNFG_GPIO_DRV_PUSHPULL | MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH); + // Configure GPIO5 and enable output in order to power CPU pmic. + max77620_config_gpio(5, MAX77620_GPIO_OUTPUT_ENABLE); - // Enable cores power. + // Configure CPU pmic. // 1-3.x: MAX77621_NFSR_ENABLE. - i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL1_REG, - MAX77621_AD_ENABLE | MAX77621_NFSR_ENABLE | MAX77621_SNS_ENABLE | MAX77621_RAMP_12mV_PER_US); // 1.0.0-3.x: MAX77621_T_JUNCTION_120 | MAX77621_CKKADV_TRIP_DISABLE | MAX77621_INDUCTOR_NOMINAL. - i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL2_REG, - MAX77621_T_JUNCTION_120 | MAX77621_WDTMR_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US| MAX77621_INDUCTOR_NOMINAL); - i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_0_95V); - i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_DVS_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_0_95V); + max77621_config_default(REGULATOR_CPU0, MAX77621_CTRL_HOS_CFG); + + // Set voltage and enable cores power. + max7762x_regulator_set_voltage(REGULATOR_CPU0, 950000); + max7762x_regulator_enable(REGULATOR_CPU0, true); } void _ccplex_enable_power_t210b01() { - u8 pmic_cpu_addr = !(FUSE(FUSE_RESERVED_ODM28) & 1) ? MAX77812_PHASE31_CPU_I2C_ADDR : MAX77812_PHASE211_CPU_I2C_ADDR; - u8 tmp = i2c_recv_byte(I2C_5, pmic_cpu_addr, MAX77812_REG_EN_CTRL); - i2c_send_byte(I2C_5, pmic_cpu_addr, MAX77812_REG_EN_CTRL, tmp | MAX77812_EN_CTRL_EN_M4); - i2c_send_byte(I2C_5, pmic_cpu_addr, MAX77812_REG_M4_VOUT, MAX77812_M4_VOUT_0_80V); + // Set voltage and enable cores power. + max7762x_regulator_set_voltage(REGULATOR_CPU1, 800000); + max7762x_regulator_enable(REGULATOR_CPU1, true); } void ccplex_boot_cpu0(u32 entry) @@ -62,24 +58,31 @@ void ccplex_boot_cpu0(u32 entry) else _ccplex_enable_power_t210b01(); - if (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & 0x40000000)) // PLLX_ENABLE. + // Enable PLLX and set it to 300 MHz. + if (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & PLLX_BASE_ENABLE)) // PLLX_ENABLE. { CLOCK(CLK_RST_CONTROLLER_PLLX_MISC_3) &= 0xFFFFFFF7; // Disable IDDQ. usleep(2); - CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x80404E02; - CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x404E02; + + // Bypass dividers. + CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = PLLX_BASE_BYPASS | (4 << 20) | (78 << 8) | 2; // P div: 4 (5), N div: 78, M div: 2. + // Disable bypass + CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = (4 << 20) | (78 << 8) | 2; + // Set PLLX_LOCK_ENABLE. CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) = (CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) & 0xFFFBFFFF) | 0x40000; - CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x40404E02; + // Enable PLLX. + CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = PLLX_BASE_ENABLE | (4 << 20) | (78 << 8) | 2; } - while (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & 0x8000000)) + // Wait for PLL to stabilize. + while (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & PLLX_BASE_LOCK)) ; - // Configure MSELECT source and enable clock. + // Configure MSELECT source and enable clock to 102MHz. CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) & 0x1FFFFF00) | 6; - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) = (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) & ~BIT(CLK_V_MSELECT)) | BIT(CLK_V_MSELECT); + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_MSELECT); // Configure initial CPU clock frequency and enable clock. - CLOCK(CLK_RST_CONTROLLER_CCLK_BURST_POLICY) = 0x20008888; + CLOCK(CLK_RST_CONTROLLER_CCLK_BURST_POLICY) = 0x20008888; // PLLX_OUT0_LJ. CLOCK(CLK_RST_CONTROLLER_SUPER_CCLK_DIVIDER) = 0x80000000; CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_CPUG); @@ -88,12 +91,12 @@ void ccplex_boot_cpu0(u32 entry) // CAR2PMC_CPU_ACK_WIDTH should be set to 0. CLOCK(CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2) &= 0xFFFFF000; - // Enable CPU rail. - pmc_enable_partition(0, 1); + // Enable CPU main rail. + pmc_enable_partition(POWER_RAIL_CRAIL, ENABLE); // Enable cluster 0 non-CPU rail. - pmc_enable_partition(15, 1); - // Enable CE0 rail. - pmc_enable_partition(14, 1); + pmc_enable_partition(POWER_RAIL_C0NC, ENABLE); + // Enable CPU0 rail. + pmc_enable_partition(POWER_RAIL_CE0, ENABLE); // Request and wait for RAM repair. FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) = 1; @@ -113,7 +116,7 @@ void ccplex_boot_cpu0(u32 entry) // MC(MC_TZ_SECURITY_CTRL) = 1; // Clear MSELECT reset. - CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_V) &= ~BIT(CLK_V_MSELECT); + CLOCK(CLK_RST_CONTROLLER_RST_DEV_V_CLR) = BIT(CLK_V_MSELECT); // Clear NONCPU reset. CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR) = 0x20000000; // Clear CPU0 reset. diff --git a/bdk/soc/clock.c b/bdk/soc/clock.c index cf0007e..31bdb8f 100644 --- a/bdk/soc/clock.c +++ b/bdk/soc/clock.c @@ -21,6 +21,23 @@ #include #include +typedef struct _clock_osc_t +{ + u32 freq; + u16 min; + u16 max; +} clock_osc_t; + +static const clock_osc_t _clock_osc_cnt[] = { + { 12000, 706, 757 }, + { 13000, 766, 820 }, + { 16800, 991, 1059 }, + { 19200, 1133, 1210 }, + { 26000, 1535, 1638 }, + { 38400, 2268, 2418 }, + { 48000, 2836, 3023 } +}; + /* clock_t: reset, enable, source, index, clk_src, clk_div */ static const clock_t _clock_uart[] = { @@ -42,7 +59,7 @@ static const clock_t _clock_i2c[] = { }; static clock_t _clock_se = { - CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, CLK_V_SE, 0, 0 + CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, CLK_V_SE, 0, 0 // 408MHz. }; static clock_t _clock_tzram = { @@ -50,19 +67,19 @@ static clock_t _clock_tzram = { }; static clock_t _clock_host1x = { - CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_L_HOST1X, 4, 3 + CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_L_HOST1X, 4, 3 // 163.2MHz. }; static clock_t _clock_tsec = { - CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, CLK_U_TSEC, 0, 2 + CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, CLK_U_TSEC, 0, 2 // 204MHz. }; static clock_t _clock_sor_safe = { CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_NO_SOURCE, CLK_Y_SOR_SAFE, 0, 0 }; static clock_t _clock_sor0 = { - CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NO_SOURCE, CLK_X_SOR0, 0, 0 + CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NOT_USED, CLK_X_SOR0, 0, 0 }; static clock_t _clock_sor1 = { - CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_X_SOR1, 0, 2 + CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_X_SOR1, 0, 2 //204MHz. }; static clock_t _clock_kfuse = { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_KFUSE, 0, 0 @@ -72,11 +89,11 @@ static clock_t _clock_cl_dvfs = { CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_NO_SOURCE, CLK_W_DVFS, 0, 0 }; static clock_t _clock_coresight = { - CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, CLK_U_CSITE, 0, 4 + CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, CLK_U_CSITE, 0, 4 // 136MHz. }; static clock_t _clock_pwm = { - CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, CLK_L_PWM, 6, 4 // Fref: 6.4MHz. Stock PLLP / 54: 7.55MHz. + CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, CLK_L_PWM, 6, 4 // Fref: 6.4MHz. HOS: PLLP / 54 = 7.55MHz. }; static clock_t _clock_sdmmc_legacy_tm = { @@ -218,13 +235,13 @@ void clock_disable_sor1() void clock_enable_kfuse() { - u32 kfuse_clk_unmask = ~BIT(CLK_H_KFUSE); - CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) = (CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) & kfuse_clk_unmask) | BIT(CLK_H_KFUSE); - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) &= kfuse_clk_unmask; - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) = (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) & kfuse_clk_unmask) | BIT(CLK_H_KFUSE); - usleep(10); - CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) &= kfuse_clk_unmask; - usleep(20); + CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = BIT(CLK_H_KFUSE); + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_CLR) = BIT(CLK_H_KFUSE); + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_KFUSE); + usleep(10); // Wait 10s to prevent glitching. + + CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_KFUSE); + usleep(20); // Wait 20s fo kfuse hw to init. } void clock_disable_kfuse() @@ -721,3 +738,44 @@ void clock_sdmmc_disable(u32 id) _clock_sdmmc_is_reset(id); _clock_disable_pllc4(BIT(id)); } + +u32 clock_get_osc_freq() +{ + CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET) = OSC_FREQ_DET_TRIG | (2 - 1); // 2 periods of 32.76KHz window. + while (CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY) + ; + u32 cnt = (CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_CNT); + CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET) = 0; + + // Return frequency in KHz. + for (u32 i = 0; i < ARRAY_SIZE(_clock_osc_cnt); i++) + if (cnt >= _clock_osc_cnt[i].min && cnt <= _clock_osc_cnt[i].max) + return _clock_osc_cnt[i].freq; + + return 0; +} + +u32 clock_get_dev_freq(clock_pto_id_t id) +{ + u32 val = ((id & PTO_SRC_SEL_MASK) << PTO_SRC_SEL_SHIFT) | PTO_DIV_SEL_DIV1 | PTO_CLK_ENABLE | (16 - 1); // 16 periods of 32.76KHz window. + CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val; + usleep(2); + CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val | PTO_CNT_RST; + usleep(2); + CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val; + usleep(2); + CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val | PTO_CNT_EN; + usleep(502); + + while (CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS) & PTO_CLK_CNT_BUSY) + ; + + u32 cnt = CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS) & PTO_CLK_CNT; + + CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = 0; + + u32 freq = ((cnt << 8) | 0x3E) / 125; + + return freq; +} + diff --git a/bdk/soc/clock.h b/bdk/soc/clock.h index 2f6de41..67e9b4d 100644 --- a/bdk/soc/clock.h +++ b/bdk/soc/clock.h @@ -35,6 +35,10 @@ #define CLK_RST_CONTROLLER_CLK_SYSTEM_RATE 0x30 #define CLK_RST_CONTROLLER_MISC_CLK_ENB 0x48 #define CLK_RST_CONTROLLER_OSC_CTRL 0x50 +#define CLK_RST_CONTROLLER_OSC_FREQ_DET 0x58 +#define CLK_RST_CONTROLLER_OSC_FREQ_DET_STATUS 0x5C +#define CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL 0x60 +#define CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS 0x64 #define CLK_RST_CONTROLLER_PLLC_BASE 0x80 #define CLK_RST_CONTROLLER_PLLC_OUT 0x84 #define CLK_RST_CONTROLLER_PLLC_MISC 0x88 @@ -156,11 +160,18 @@ #define CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE 0x710 #define CLK_NO_SOURCE 0x0 +#define CLK_NOT_USED 0x0 /*! PLL control and status bits */ +#define PLLX_BASE_LOCK BIT(27) +#define PLLX_BASE_REF_DIS BIT(29) +#define PLLX_BASE_ENABLE BIT(30) +#define PLLX_BASE_BYPASS BIT(31) + #define PLLCX_BASE_LOCK BIT(27) #define PLLCX_BASE_REF_DIS BIT(29) #define PLLCX_BASE_ENABLE BIT(30) +#define PLLCX_BASE_BYPASS BIT(31) #define PLLA_OUT0_RSTN_CLR BIT(0) #define PLLA_OUT0_CLKEN BIT(1) @@ -178,6 +189,140 @@ #define UTMIPLL_LOCK BIT(31) +/*! PTO_CLK_CNT */ +#define PTO_REF_CLK_WIN_CFG_MASK 0xF +#define PTO_REF_CLK_WIN_CFG_16P 0xF +#define PTO_CNT_EN BIT(9) +#define PTO_CNT_RST BIT(10) +#define PTO_CLK_ENABLE BIT(13) +#define PTO_SRC_SEL_SHIFT 14 +#define PTO_SRC_SEL_MASK 0x1FF +#define PTO_DIV_SEL_MASK (3 << 23) +#define PTO_DIV_SEL_GATED (0 << 23) +#define PTO_DIV_SEL_DIV1 (1 << 23) +#define PTO_DIV_SEL_DIV2_RISING (2 << 23) +#define PTO_DIV_SEL_DIV2_FALLING (3 << 23) +#define PTO_DIV_SEL_CPU_EARLY (0 << 23) +#define PTO_DIV_SEL_CPU_LATE (1 << 23) + +#define PTO_CLK_CNT_BUSY BIT(31) +#define PTO_CLK_CNT 0xFFFFFF + +/*! OSC_FREQ_DET */ +#define OSC_REF_CLK_WIN_CFG_MASK 0xF +#define OSC_FREQ_DET_TRIG BIT(31) + +#define OSC_FREQ_DET_BUSY BIT(31) +#define OSC_FREQ_DET_CNT 0xFFFF + +/*! PLLs omitted as they need PTO enabled in MISC registers. Norm div is 2. */ +typedef enum _clock_pto_id_t +{ + CLK_PTO_PCLK_SYS = 0x06, + CLK_PTO_HCLK_SYS = 0x07, + + CLK_PTO_UTMIP_240 = 0x0C, + + CLK_PTO_CCLK_G = 0x12, + CLK_PTO_CCLK_G_DIV2 = 0x13, + + CLK_PTO_SPI1 = 0x17, + CLK_PTO_SPI2 = 0x18, + CLK_PTO_SPI3 = 0x19, + CLK_PTO_SPI4 = 0x1A, + CLK_PTO_MAUD = 0x1B, + CLK_PTO_SCLK = 0x1C, + + CLK_PTO_SDMMC1 = 0x20, + CLK_PTO_SDMMC2 = 0x21, + CLK_PTO_SDMMC3 = 0x22, + CLK_PTO_SDMMC4 = 0x23, + CLK_PTO_EMC = 0x24, + + CLK_PTO_MSELECT = 0x2F, + + CLK_PTO_VIC = 0x36, + + CLK_PTO_NVDEC = 0x39, + + CLK_PTO_NVENC = 0x3A, + CLK_PTO_NVJPG = 0x3B, + CLK_PTO_TSEC = 0x3C, + CLK_PTO_TSECB = 0x3D, + CLK_PTO_SE = 0x3E, + + CLK_PTO_DSIA_LP = 0x62, + + CLK_PTO_ISP = 0x64, + CLK_PTO_MC = 0x6A, + + CLK_PTO_ACTMON = 0x6B, + CLK_PTO_CSITE = 0x6C, + + CLK_PTO_HOST1X = 0x6F, + + CLK_PTO_SE_2 = 0x74, // Same as CLK_PTO_SE. + CLK_PTO_SOC_THERM = 0x75, + + CLK_PTO_TSEC_2 = 0x77, // Same as CLK_PTO_TSEC. + + CLK_PTO_ACLK = 0x7C, + CLK_PTO_QSPI = 0x7D, + + CLK_PTO_I2S1 = 0x80, + CLK_PTO_I2S2 = 0x81, + CLK_PTO_I2S3 = 0x82, + CLK_PTO_I2S4 = 0x83, + CLK_PTO_I2S5 = 0x84, + CLK_PTO_AHUB = 0x85, + CLK_PTO_APE = 0x86, + + CLK_PTO_DVFS_SOC = 0x88, + CLK_PTO_DVFS_REF = 0x89, + + CLK_PTO_SPDIF = 0x8F, + CLK_PTO_SPDIF_IN = 0x90, + CLK_PTO_UART_FST_MIPI_CAL = 0x91, + + CLK_PTO_PWM = 0x93, + CLK_PTO_I2C1 = 0x94, + CLK_PTO_I2C2 = 0x95, + CLK_PTO_I2C3 = 0x96, + CLK_PTO_I2C4 = 0x97, + CLK_PTO_I2C5 = 0x98, + CLK_PTO_I2C6 = 0x99, + CLK_PTO_I2C_SLOW = 0x9A, + CLK_PTO_UARTAPE = 0x9B, + + CLK_PTO_EXTPERIPH1 = 0x9D, + CLK_PTO_EXTPERIPH2 = 0x9E, + + CLK_PTO_ENTROPY = 0xA0, + CLK_PTO_UARTA = 0xA1, + CLK_PTO_UARTB = 0xA2, + CLK_PTO_UARTC = 0xA3, + CLK_PTO_UARTD = 0xA4, + CLK_PTO_OWR = 0xA5, + + CLK_PTO_HDA2CODEC_2X = 0xA7, + CLK_PTO_HDA = 0xA8, + + CLK_PTO_SDMMC_LEGACY_TM = 0xAB, + + CLK_PTO_SOR0 = 0xC0, + CLK_PTO_SOR1 = 0xC1, + + CLK_PTO_DISP2 = 0xC4, + CLK_PTO_DISP1 = 0xC5, + + CLK_PTO_XUSB_FALCON = 0x110, + + CLK_PTO_XUSB_FS = 0x136, + CLK_PTO_XUSB_SS_HOST_DEV = 0x137, + CLK_PTO_XUSB_CORE_HOST = 0x138, + CLK_PTO_XUSB_CORE_DEV = 0x139, +} clock_pto_id_t; + /* * CLOCK Peripherals: * L 0 - 31 @@ -216,7 +361,7 @@ enum CLK_L_DEV CLK_L_USBD = 22, CLK_L_ISP = 23, CLK_L_3D = 24, // HIDDEN. - //CLK_L_ = 25, + CLK_L_IDE = 25, // RESERVED. CLK_L_DISP2 = 26, CLK_L_DISP1 = 27, CLK_L_HOST1X = 28, @@ -244,11 +389,11 @@ enum CLK_H_DEV CLK_H_SPI3 = 14, CLK_H_I2C5 = 15, CLK_H_DSI = 16, - //CLK_H_ = 17, + CLK_H_TVO = 17, // RESERVED. CLK_H_HSI = 18, // HIDDEN. CLK_H_HDMI = 19, // HIDDEN. CLK_H_CSI = 20, - //CLK_H_ = 21, + CLK_H_TVDAC = 21, // RESERVED. CLK_H_I2C2 = 22, CLK_H_UARTC = 23, CLK_H_MIPI_CAL = 24, @@ -263,14 +408,14 @@ enum CLK_H_DEV enum CLK_U_DEV { - //CLK_U_ = 0, + CLK_U_SPEEDO = 0, // RESERVED. CLK_U_UARTD = 1, CLK_U_UARTE = 2, // HIDDEN. CLK_U_I2C3 = 3, CLK_U_SPI4 = 4, CLK_U_SDMMC3 = 5, CLK_U_PCIE = 6, - CLK_U_UNUSED = 7, // RESERVED + CLK_U_OWR = 7, // RESERVED. CLK_U_AFI = 8, CLK_U_CSITE = 9, CLK_U_PCIEXCLK = 10, // Only reset. @@ -444,9 +589,9 @@ enum CLK_Y_DEV /*! Generic clock descriptor. */ typedef struct _clock_t { - u32 reset; - u32 enable; - u32 source; + u16 reset; + u16 enable; + u16 source; u8 index; u8 clk_src; u8 clk_div; @@ -494,4 +639,7 @@ int clock_sdmmc_is_not_reset_and_enabled(u32 id); void clock_sdmmc_enable(u32 id, u32 val); void clock_sdmmc_disable(u32 id); +u32 clock_get_osc_freq(); +u32 clock_get_dev_freq(clock_pto_id_t id); + #endif diff --git a/bdk/soc/fuse.c b/bdk/soc/fuse.c index 62dba31..0a37a4b 100644 --- a/bdk/soc/fuse.c +++ b/bdk/soc/fuse.c @@ -2,7 +2,7 @@ * Copyright (c) 2018 naehrwert * Copyright (c) 2018 shuffle2 * Copyright (c) 2018 balika011 - * Copyright (c) 2019 CTCaer + * Copyright (c) 2019-2020 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -76,6 +76,35 @@ u32 fuse_read_odm_keygen_rev() return 0; } +u32 fuse_read_dramid(bool raw_id) +{ + u32 dramid = (fuse_read_odm(4) & 0xF8) >> 3; + + if (raw_id) + return dramid; + + if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210) + { + if (dramid > 6) + dramid = 0; + } + else + { + if (dramid > 27) + dramid = 8; + } + + return dramid; +} + +u32 fuse_read_hw_state() +{ + if ((fuse_read_odm(4) & 3) != 3) + return FUSE_NX_HW_STATE_PROD; + else + return FUSE_NX_HW_STATE_DEV; +} + u32 fuse_read_hw_type() { if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01) @@ -118,6 +147,7 @@ u32 fuse_read(u32 addr) FUSE(FUSE_ADDR) = addr; FUSE(FUSE_CTRL) = (FUSE(FUSE_ADDR) & ~FUSE_CMD_MASK) | FUSE_READ; fuse_wait_idle(); + return FUSE(FUSE_RDATA); } diff --git a/bdk/soc/fuse.h b/bdk/soc/fuse.h index d7d5c77..810efd6 100644 --- a/bdk/soc/fuse.h +++ b/bdk/soc/fuse.h @@ -2,6 +2,7 @@ * Copyright (c) 2018 naehrwert * Copyright (c) 2018 shuffle2 * Copyright (c) 2018 balika011 + * Copyright (c) 2019-2020 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -64,9 +65,10 @@ #define FUSE_OPT_X_COORDINATE 0x214 #define FUSE_OPT_Y_COORDINATE 0x218 #define FUSE_GPU_IDDQ_CALIB 0x228 -#define FUSE_RESERVED_ODM28 0x240 #define FUSE_USB_CALIB_EXT 0x350 +#define FUSE_RESERVED_ODM28_T210B01 0x240 + /*! Fuse commands. */ #define FUSE_READ 0x1 #define FUSE_WRITE 0x2 @@ -83,9 +85,17 @@ enum FUSE_NX_HW_TYPE_HOAG }; +enum +{ + FUSE_NX_HW_STATE_PROD, + FUSE_NX_HW_STATE_DEV +}; + void fuse_disable_program(); u32 fuse_read_odm(u32 idx); u32 fuse_read_odm_keygen_rev(); +u32 fuse_read_dramid(bool raw_id); +u32 fuse_read_hw_state(); u32 fuse_read_hw_type(); u8 fuse_count_burnt(u32 val); void fuse_wait_idle(); diff --git a/bdk/soc/hw_init.c b/bdk/soc/hw_init.c index dd79dc6..1da102f 100644 --- a/bdk/soc/hw_init.c +++ b/bdk/soc/hw_init.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2020 CTCaer + * Copyright (c) 2018-2021 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include #include @@ -42,6 +42,7 @@ #include #include #include +#include #include extern boot_cfg_t b_cfg; @@ -87,6 +88,7 @@ static void _config_oscillators() CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // Set HCLK div to 1 and PCLK div to 3. } +// The uart is skipped for Copper, Hoag and Calcio. Used in Icosa, Iowa and Aula. static void _config_gpios(bool nx_hoag) { // Clamp inputs when tristated. @@ -263,7 +265,7 @@ static void _config_se_brom() FUSE(FUSE_PRIVATE_KEY3) }; // Set SBK to slot 14. - se_aes_key_set(14, sbk, 0x10); + se_aes_key_set(14, sbk, SE_KEY_128_SIZE); // Lock SBK from being read. se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG); @@ -275,7 +277,7 @@ static void _config_se_brom() // 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; + SE(SE_INT_STATUS_REG) = 0x1F; // Clear all SE interrupts. // Clear the boot reason to avoid problems later PMC(APBDEV_PMC_SCRATCH200) = 0x0; @@ -285,17 +287,21 @@ static void _config_se_brom() static void _config_regulators(bool tegra_t210) { + // Set RTC/AO domain to POR voltage. + if (tegra_t210) + max7762x_regulator_set_voltage(REGULATOR_LDO4, 1000000); + // Disable low battery shutdown monitor. max77620_low_battery_monitor_config(false); // Disable SDMMC1 IO power. gpio_write(GPIO_PORT_E, GPIO_PIN_4, GPIO_LOW); - max77620_regulator_enable(REGULATOR_LDO2, 0); + max7762x_regulator_enable(REGULATOR_LDO2, false); 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, - BIT(6) | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off. + MAX77620_ONOFFCNFG1_RSVD | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off. if (tegra_t210) { @@ -313,28 +319,18 @@ static void _config_regulators(bool tegra_t210) (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); + max7762x_regulator_set_voltage(REGULATOR_SD0, 1125000); - // 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); + // Fix CPU/GPU after L4T warmboot. + max77620_config_gpio(5, MAX77620_GPIO_OUTPUT_DISABLE); + max77620_config_gpio(6, MAX77620_GPIO_OUTPUT_DISABLE); - 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); + // Set POR configuration. + max77621_config_default(REGULATOR_CPU0, MAX77621_CTRL_POR_CFG); + max77621_config_default(REGULATOR_GPU0, MAX77621_CTRL_POR_CFG); } else // Tegra X1+ set vdd_core voltage to 1.05V. - max77620_regulator_set_voltage(REGULATOR_SD0, 1050000); + max7762x_regulator_set_voltage(REGULATOR_SD0, 1050000); } void hw_init() @@ -373,7 +369,8 @@ void hw_init() #ifdef DEBUG_UART_PORT clock_enable_uart(DEBUG_UART_PORT); - uart_init(DEBUG_UART_PORT, 115200); + uart_init(DEBUG_UART_PORT, DEBUG_UART_BAUDRATE); + uart_invert(DEBUG_UART_PORT, DEBUG_UART_INVERT, UART_INVERT_TXD); #endif // Enable Dynamic Voltage and Frequency Scaling device clock. @@ -391,17 +388,20 @@ void hw_init() //! TODO: Why? Device is NFC MCU on Lite. if (nx_hoag) - max77620_regulator_set_volt_and_flags(REGULATOR_LDO8, 2800000, MAX77620_POWER_MODE_NORMAL); + { + max7762x_regulator_set_voltage(REGULATOR_LDO8, 2800000); + max7762x_regulator_enable(REGULATOR_LDO8, true); + } // Initialize I2C1 for various power related devices. i2c_init(I2C_1); - // Enable charger in case it's disabled. - bq24193_enable_charger(); - // Initialize various regulators based on Erista/Mariko platform. _config_regulators(tegra_t210); + // Enable charger in case it's disabled. + bq24193_enable_charger(); + _config_pmc_scratch(); // Missing from 4.x+ // Set BPMP/SCLK to PLLP_OUT (408MHz). @@ -421,19 +421,18 @@ void hw_init() bpmp_mmu_enable(); } -void hw_reinit_workaround(bool extra_reconfig, u32 magic) +void hw_reinit_workaround(bool coreboot, u32 bl_magic) { // Disable BPMP max clock. bpmp_clk_rate_set(BPMP_CLK_NORMAL); #ifdef NYX - // Deinit touchscreen, 5V regulators and Joy-Con. - touch_power_off(); + // Disable temperature sensor, touchscreen, 5V regulators and Joy-Con. + tmp451_end(); set_fan_duty(0); + touch_power_off(); jc_deinit(); - regulator_disable_5v(REGULATOR_5V_ALL); - clock_disable_uart(UART_B); - clock_disable_uart(UART_C); + regulator_5v_disable(REGULATOR_5V_ALL); #endif // Flush/disable MMU cache and set DRAM clock to 204MHz. @@ -445,10 +444,10 @@ void hw_reinit_workaround(bool extra_reconfig, u32 magic) CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= BIT(CLK_V_AHUB); CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= BIT(CLK_Y_APE); - if (extra_reconfig) + // Do coreboot mitigations. + if (coreboot) { msleep(10); - PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_SDMMC1_IO_EN; clock_disable_cl_dvfs(); @@ -457,13 +456,27 @@ void hw_reinit_workaround(bool extra_reconfig, u32 magic) gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO); gpio_config(GPIO_PORT_E, GPIO_PIN_6, GPIO_MODE_SPIO); gpio_config(GPIO_PORT_H, GPIO_PIN_6, GPIO_MODE_SPIO); + + // Reinstate SD controller power. + PMC(APBDEV_PMC_NO_IOPOWER) &= ~(PMC_NO_IOPOWER_SDMMC1_IO_EN); } - // Power off display. - display_end(); + // Seamless display or display power off. + switch (bl_magic) + { + case BL_MAGIC_CRBOOT_SLD:; + // Set pwm to 0%, switch to gpio mode and restore pwm duty. + u32 brightness = display_get_backlight_brightness(); + display_backlight_brightness(0, 1000); + gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_GPIO); + display_backlight_brightness(brightness, 0); + break; + default: + display_end(); + } // Enable clock to USBD and init SDMMC1 to avoid hangs with bad hw inits. - if (magic == 0xBAADF00D) + if (bl_magic == BL_MAGIC_BROKEN_HWI) { CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_USBD); sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, 0); diff --git a/bdk/soc/hw_init.h b/bdk/soc/hw_init.h index ff9ae4a..a1b2dfc 100644 --- a/bdk/soc/hw_init.h +++ b/bdk/soc/hw_init.h @@ -20,8 +20,11 @@ #include +#define BL_MAGIC_CRBOOT_SLD 0x30444C53 // SLD0, seamless display type 0. +#define BL_MAGIC_BROKEN_HWI 0xBAADF00D // Broken hwinit. + void hw_init(); -void hw_reinit_workaround(bool extra_reconfig, u32 magic); +void hw_reinit_workaround(bool coreboot, u32 magic); u32 hw_get_chip_id(); #endif diff --git a/bdk/soc/i2c.c b/bdk/soc/i2c.c index 099a182..0906adc 100644 --- a/bdk/soc/i2c.c +++ b/bdk/soc/i2c.c @@ -136,10 +136,10 @@ static int _i2c_send_single(u32 i2c_idx, u32 dev_addr, u8 *buf, u32 size) // Initiate transaction on normal mode. base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | NORMAL_MODE_GO; - u32 timeout = get_tmr_ms() + 400; // Actual for max 8 bytes at 100KHz is 0.74ms. + u32 timeout = get_tmr_us() + 200000; // Actual for max 8 bytes at 100KHz is 0.74ms. while (base[I2C_STATUS] & I2C_STATUS_BUSY) { - if (get_tmr_ms() > timeout) + if (get_tmr_us() > timeout) return 0; } @@ -168,10 +168,10 @@ static int _i2c_recv_single(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr) // Initiate transaction on normal mode. base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | NORMAL_MODE_GO; - u32 timeout = get_tmr_ms() + 400; // Actual for max 8 bytes at 100KHz is 0.74ms. + u32 timeout = get_tmr_us() + 200000; // Actual for max 8 bytes at 100KHz is 0.74ms. while (base[I2C_STATUS] & I2C_STATUS_BUSY) { - if (get_tmr_ms() > timeout) + if (get_tmr_us() > timeout) return 0; } diff --git a/bdk/soc/irq.c b/bdk/soc/irq.c index 4fb39ca..e2f925c 100644 --- a/bdk/soc/irq.c +++ b/bdk/soc/irq.c @@ -133,6 +133,10 @@ static irq_status_t _irq_handle_source(u32 irq) } } + // Do not re-enable if not handled. + if (status == IRQ_NONE) + return status; + if (irqs[idx].flags & IRQ_FLAG_ONE_OFF) irq_free(irq); else @@ -148,7 +152,9 @@ void irq_handler() if (!irq_init_done) { + _irq_disable_source(irq); _irq_ack_source(irq); + return; } @@ -156,9 +162,10 @@ void irq_handler() int err = _irq_handle_source(irq); - //TODO: disable if unhandhled. if (err == IRQ_NONE) - gfx_printf("Unhandled IRQ: %d\n", irq); + { + DPRINTF("Unhandled IRQ got disabled: %d!\n", irq); + } } static void _irq_init() @@ -170,6 +177,9 @@ static void _irq_init() void irq_end() { + if (!irq_init_done) + return; + _irq_free_all(); irq_disable_cpu_irq_exceptions(); irq_init_done = false; diff --git a/bdk/soc/pmc.c b/bdk/soc/pmc.c index 62caa22..aa86cb7 100644 --- a/bdk/soc/pmc.c +++ b/bdk/soc/pmc.c @@ -14,11 +14,69 @@ * along with this program. If not, see . */ +#include #include #include #include -int pmc_enable_partition(u32 part, int enable) +void pmc_scratch_lock(pmc_sec_lock_t lock_mask) +{ + // Lock Private key disable, Fuse write enable, MC carveout, Warmboot PA id and Warmboot address. + if (lock_mask & PMC_SEC_LOCK_MISC) + { + PMC(APBDEV_PMC_SEC_DISABLE) |= 0x700FF0; // RW lock: 0-3. + PMC(APBDEV_PMC_SEC_DISABLE2) |= 0xFC000000; // RW lock: 21-23. + PMC(APBDEV_PMC_SEC_DISABLE3) |= 0x3F0FFF00; // RW lock: 28-33, 36-38. + PMC(APBDEV_PMC_SEC_DISABLE6) |= 0xC000000; // RW lock: 85. + PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xFF00FF00; // RW lock: 108-111, 116-119. + + // SE2 context. + if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01) + { + PMC(APBDEV_PMC_SEC_DISABLE9) |= 0x3FF; // RW lock: 120-124. (0xB38) + PMC(APBDEV_PMC_SEC_DISABLE10) = 0xFFFFFFFF; // RW lock: 135-150. + } + } + + if (lock_mask & PMC_SEC_LOCK_LP0_PARAMS) + { + PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x3FCFFFF; // RW lock: 8-15, 17-20. + PMC(APBDEV_PMC_SEC_DISABLE4) |= 0x3F3FFFFF; // RW lock: 40-50, 52-54. + PMC(APBDEV_PMC_SEC_DISABLE5) = 0xFFFFFFFF; // RW lock: 56-71. + PMC(APBDEV_PMC_SEC_DISABLE6) |= 0xF3FFC00F; // RW lock: 72-73, 79-84, 86-87. + PMC(APBDEV_PMC_SEC_DISABLE7) |= 0x3FFFFF; // RW lock: 88-98. + PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xFF; // RW lock: 104-107. + } + + if (lock_mask & PMC_SEC_LOCK_RST_VECTOR) + PMC(APBDEV_PMC_SEC_DISABLE3) |= 0xF00000; // RW lock: 34-35. + + if (lock_mask & PMC_SEC_LOCK_CARVEOUTS) + { + PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x30000; // RW lock: 16. + PMC(APBDEV_PMC_SEC_DISABLE3) |= 0xC0000000; // RW lock: 39. + PMC(APBDEV_PMC_SEC_DISABLE4) |= 0xC0C00000; // RW lock: 51, 55. + PMC(APBDEV_PMC_SEC_DISABLE6) |= 0x3FF0; // RW lock: 74-78. + PMC(APBDEV_PMC_SEC_DISABLE7) |= 0xFFC00000; // RW lock: 99-103. + } + + if (lock_mask & PMC_SEC_LOCK_TZ_CMAC_W) + PMC(APBDEV_PMC_SEC_DISABLE8) |= 0x550000; // W lock: 112-115. + + if (lock_mask & PMC_SEC_LOCK_TZ_CMAC_R) + PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xAA0000; // R lock: 112-115. + + if (lock_mask & PMC_SEC_LOCK_TZ_KEK_W) + PMC(APBDEV_PMC_SEC_DISABLE3) |= 0x55; // W lock: 24-27. + + if (lock_mask & PMC_SEC_LOCK_TZ_KEK_R) + PMC(APBDEV_PMC_SEC_DISABLE3) |= 0xAA; // R lock: 24-27. + + if (lock_mask & PMC_SEC_LOCK_SE_SRK) + PMC(APBDEV_PMC_SEC_DISABLE) |= 0xFF000; // RW lock: 4-7 +} + +int pmc_enable_partition(pmc_power_rail_t part, u32 enable) { u32 part_mask = BIT(part); u32 desired_state = enable << part; diff --git a/bdk/soc/pmc.h b/bdk/soc/pmc.h index c27d937..42bd869 100644 --- a/bdk/soc/pmc.h +++ b/bdk/soc/pmc.h @@ -91,6 +91,8 @@ #define APBDEV_PMC_SEC_DISABLE6 0x5B8 #define APBDEV_PMC_SEC_DISABLE7 0x5BC #define APBDEV_PMC_SEC_DISABLE8 0x5C0 +#define APBDEV_PMC_SEC_DISABLE9 0x5C4 +#define APBDEV_PMC_SEC_DISABLE10 0x5C8 #define APBDEV_PMC_SCRATCH188 0x810 #define APBDEV_PMC_SCRATCH190 0x818 #define APBDEV_PMC_SCRATCH200 0x840 @@ -98,6 +100,54 @@ #define APBDEV_PMC_TZRAM_SEC_DISABLE 0xBEC #define APBDEV_PMC_TZRAM_NON_SEC_DISABLE 0xBF0 -int pmc_enable_partition(u32 part, int enable); +typedef enum _pmc_sec_lock_t +{ + PMC_SEC_LOCK_MISC = BIT(0), + PMC_SEC_LOCK_LP0_PARAMS = BIT(1), + PMC_SEC_LOCK_RST_VECTOR = BIT(2), + PMC_SEC_LOCK_CARVEOUTS = BIT(3), + PMC_SEC_LOCK_TZ_CMAC_W = BIT(4), + PMC_SEC_LOCK_TZ_CMAC_R = BIT(5), + PMC_SEC_LOCK_TZ_KEK_W = BIT(6), + PMC_SEC_LOCK_TZ_KEK_R = BIT(7), + PMC_SEC_LOCK_SE_SRK = BIT(8), +} pmc_sec_lock_t; + +typedef enum _pmc_power_rail_t +{ + POWER_RAIL_CRAIL = 0, + POWER_RAIL_3D0 = 1, + POWER_RAIL_VENC = 2, + POWER_RAIL_PCIE = 3, + POWER_RAIL_VDEC = 4, + POWER_RAIL_L2C = 5, + POWER_RAIL_MPE = 6, + POWER_RAIL_HEG = 7, + POWER_RAIL_SATA = 8, + POWER_RAIL_CE1 = 9, + POWER_RAIL_CE2 = 10, + POWER_RAIL_CE3 = 11, + POWER_RAIL_CELP = 12, + POWER_RAIL_3D1 = 13, + POWER_RAIL_CE0 = 14, + POWER_RAIL_C0NC = 15, + POWER_RAIL_C1NC = 16, + POWER_RAIL_SOR = 17, + POWER_RAIL_DIS = 18, + POWER_RAIL_DISB = 19, + POWER_RAIL_XUSBA = 20, + POWER_RAIL_XUSBB = 21, + POWER_RAIL_XUSBC = 22, + POWER_RAIL_VIC = 23, + POWER_RAIL_IRAM = 24, + POWER_RAIL_NVDEC = 25, + POWER_RAIL_NVJPG = 26, + POWER_RAIL_AUD = 27, + POWER_RAIL_DFD = 28, + POWER_RAIL_VE2 = 29 +} pmc_power_rail_t; + +void pmc_scratch_lock(pmc_sec_lock_t lock_mask); +int pmc_enable_partition(pmc_power_rail_t part, u32 enable); #endif diff --git a/bdk/soc/uart.c b/bdk/soc/uart.c index 75e18b8..582bca1 100644 --- a/bdk/soc/uart.c +++ b/bdk/soc/uart.c @@ -122,7 +122,12 @@ u32 uart_get_IIR(u32 idx) { uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]); - return uart->UART_IIR_FCR; + u32 iir = uart->UART_IIR_FCR & UART_IIR_INT_MASK; + + if (iir & UART_IIR_NO_INT) + return 0; + else + return ((iir >> 1) + 1); // Return encoded interrupt. } void uart_set_IIR(u32 idx) diff --git a/bdk/soc/uart.h b/bdk/soc/uart.h index 809192a..6a4c073 100644 --- a/bdk/soc/uart.h +++ b/bdk/soc/uart.h @@ -54,6 +54,17 @@ #define UART_IIR_FCR_RX_CLR 0x2 #define UART_IIR_FCR_EN_FIFO 0x1 +#define UART_IIR_NO_INT BIT(0) +#define UART_IIR_INT_MASK 0xF +/* Custom returned interrupt results. Actual interrupts are -1 */ +#define UART_IIR_NOI 0 // No interrupt. +#define UART_IIR_MSI 1 // Modem status interrupt. +#define UART_IIR_THRI 2 // Transmitter holding register empty. +#define UART_IIR_RDI 3 // Receiver data interrupt. +#define UART_IIR_ERROR 4 // Overrun Error, Parity Error, Framing Error, Break. +#define UART_IIR_REDI 5 // Receiver end of data interrupt. +#define UART_IIR_RDTI 7 // Receiver data timeout interrupt. + #define UART_MCR_RTS 0x2 #define UART_MCR_DTR 0x1 diff --git a/bdk/storage/mmc.h b/bdk/storage/mmc.h index efa9e10..fc6c2f8 100644 --- a/bdk/storage/mmc.h +++ b/bdk/storage/mmc.h @@ -84,6 +84,11 @@ #define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */ #define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */ +#define MMC_VENDOR_60_CMD 60 /* Vendor Defined */ +#define MMC_VENDOR_61_CMD 61 /* Vendor Defined */ +#define MMC_VENDOR_62_CMD 62 /* Vendor Defined */ +#define MMC_VENDOR_63_CMD 63 /* Vendor Defined */ + /* class 11 */ #define MMC_QUE_TASK_PARAMS 44 /* ac [20:16] task id R1 */ #define MMC_QUE_TASK_ADDR 45 /* ac [31:0] data addr R1 */ @@ -142,7 +147,10 @@ c : clear by read #define R1_SWITCH_ERROR (1 << 7) /* sx, c */ #define R1_EXCEPTION_EVENT (1 << 6) /* sr, a */ #define R1_APP_CMD (1 << 5) /* sr, c */ +#define R1_SKIP_STATE_CHECK (1 << 4) /* Custom state to skip expected state check */ +#define R1_AKE_SEQ_ERROR (1 << 3) +/* R1_CURRENT_STATE 12:9 */ #define R1_STATE_IDLE 0 #define R1_STATE_READY 1 #define R1_STATE_IDENT 2 @@ -179,7 +187,10 @@ c : clear by read /* * OCR bits are mostly in host.h */ -#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */ +#define MMC_CARD_VDD_18 (1 << 7) /* Card VDD voltage 1.8 */ +#define MMC_CARD_VDD_27_34 (0x7F << 15) /* Card VDD voltage 2.7 ~ 3.4 */ +#define MMC_CARD_CCS (1 << 30) /* Card Capacity status bit */ +#define MMC_CARD_BUSY (1 << 31) /* Card Power up status bit */ /* * Card Command Classes (CCC) @@ -241,6 +252,7 @@ c : clear by read #define EXT_CSD_GP_SIZE_MULT 143 /* R/W */ #define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */ #define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */ +#define EXT_CSD_MAX_ENH_SIZE_MULT 157 /* RO, 3 bytes */ #define EXT_CSD_PARTITION_SUPPORT 160 /* RO */ #define EXT_CSD_HPI_MGMT 161 /* R/W */ #define EXT_CSD_RST_N_FUNCTION 162 /* R/W */ diff --git a/bdk/storage/nx_sd.h b/bdk/storage/nx_sd.h index bc4c2d4..e2b703f 100644 --- a/bdk/storage/nx_sd.h +++ b/bdk/storage/nx_sd.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2019 CTCaer + * Copyright (c) 2018-2021 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -45,12 +45,15 @@ extern FATFS sd_fs; void sd_error_count_increment(u8 type); u16 *sd_get_error_count(); bool sd_get_card_removed(); +bool sd_get_card_initialized(); +bool sd_get_card_mounted(); u32 sd_get_mode(); int sd_init_retry(bool power_cycle); bool sd_initialize(bool power_cycle); bool sd_mount(); void sd_unmount(); void sd_end(); +bool sd_is_gpt(); void *sd_file_read(const char *path, u32 *fsize); int sd_save_to_file(void *buf, u32 size, const char *filename); diff --git a/bdk/storage/ramdisk.c b/bdk/storage/ramdisk.c index e7b7c01..315075d 100644 --- a/bdk/storage/ramdisk.c +++ b/bdk/storage/ramdisk.c @@ -1,7 +1,7 @@ /* * Ramdisk driver for Tegra X1 * - * Copyright (c) 2019 CTCaer + * Copyright (c) 2019-2021 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -19,23 +19,40 @@ #include #include "ramdisk.h" +#include #include #include #include -int ram_disk_init(FATFS *ram_fs) +static u32 disk_size = 0; + +int ram_disk_init(FATFS *ram_fs, u32 ramdisk_size) { - int res; - u8 *buf = malloc(0x400000); + int res = 0; + disk_size = ramdisk_size; - f_mount(NULL, "ram:", 1); // Unmount ramdisk. + // If ramdisk is not raw, format it. + if (ram_fs) + { + u8 *buf = malloc(0x400000); - res = f_mkfs("ram:", FM_EXFAT, RAMDISK_CLUSTER_SZ, buf, 0x400000); // Format as exFAT w/ 32KB cluster. - if (!res) - res = f_mount(ram_fs, "ram:", 1); // Mount ramdisk. + // Set ramdisk size. + ramdisk_size >>= 9; + disk_set_info(DRIVE_RAM, SET_SECTOR_COUNT, &ramdisk_size); - free(buf); + // Unmount ramdisk. + f_mount(NULL, "ram:", 1); + + // Format as exFAT w/ 32KB cluster with no MBR. + res = f_mkfs("ram:", FM_EXFAT | FM_SFD, RAMDISK_CLUSTER_SZ, buf, 0x400000); + + // Mount ramdisk. + if (!res) + res = f_mount(ram_fs, "ram:", 1); + + free(buf); + } return res; } @@ -45,7 +62,7 @@ int ram_disk_read(u32 sector, u32 sector_count, void *buf) u32 sector_off = RAM_DISK_ADDR + (sector << 9); u32 bytes_count = sector_count << 9; - if ((sector_off - RAM_DISK_ADDR) > RAM_DISK_SZ) + if ((sector_off - RAM_DISK_ADDR) > disk_size) return 1; memcpy(buf, (void *)sector_off, bytes_count); @@ -58,7 +75,7 @@ int ram_disk_write(u32 sector, u32 sector_count, const void *buf) u32 sector_off = RAM_DISK_ADDR + (sector << 9); u32 bytes_count = sector_count << 9; - if ((sector_off - RAM_DISK_ADDR) > RAM_DISK_SZ) + if ((sector_off - RAM_DISK_ADDR) > disk_size) return 1; memcpy((void *)sector_off, buf, bytes_count); diff --git a/bdk/storage/ramdisk.h b/bdk/storage/ramdisk.h index ef43bb5..e625235 100644 --- a/bdk/storage/ramdisk.h +++ b/bdk/storage/ramdisk.h @@ -1,7 +1,7 @@ /* * Ramdisk driver for Tegra X1 * - * Copyright (c) 2019 CTCaer + * Copyright (c) 2019-2021 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -23,7 +23,7 @@ #define RAMDISK_CLUSTER_SZ 32768 -int ram_disk_init(FATFS *ram_fs); +int ram_disk_init(FATFS *ram_fs, u32 ramdisk_size); int ram_disk_read(u32 sector, u32 sector_count, void *buf); int ram_disk_write(u32 sector, u32 sector_count, const void *buf); diff --git a/bdk/storage/sd.h b/bdk/storage/sd.h index a780ec8..22d3359 100644 --- a/bdk/storage/sd.h +++ b/bdk/storage/sd.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2005-2007 Pierre Ossman, All Rights Reserved. - * Copyright (c) 2018 CTCaer + * Copyright (c) 2018-2021 CTCaer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,58 +14,79 @@ /* SD commands type argument response */ /* class 0 */ /* This is basically the same command as for MMC with some quirks. */ -#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */ -#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */ -#define SD_SWITCH_VOLTAGE 11 /* ac R1 */ - +#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */ +#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */ +#define SD_SWITCH_VOLTAGE 11 /* ac R1 */ /* class 10 */ -#define SD_SWITCH 6 /* adtc [31:0] See below R1 */ - +#define SD_SWITCH 6 /* adtc [31:0] See below R1 */ /* class 5 */ -#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */ -#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */ +#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */ +#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */ /* Application commands */ -#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */ -#define SD_APP_SD_STATUS 13 /* adtc R1 */ -#define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */ -#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */ -#define SD_APP_SET_CLR_CARD_DETECT 42 -#define SD_APP_SEND_SCR 51 /* adtc R1 */ +#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */ +#define SD_APP_SD_STATUS 13 /* adtc R1 */ +#define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */ +#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */ +#define SD_APP_SET_CLR_CARD_DETECT 42 /* adtc R1 */ +#define SD_APP_SEND_SCR 51 /* adtc R1 */ + +/* Application secure commands */ +#define SD_APP_SECURE_READ_MULTI_BLOCK 18 /* adtc R1 */ +#define SD_APP_SECURE_WRITE_MULTI_BLOCK 25 /* adtc R1 */ +#define SD_APP_SECURE_WRITE_MKB 26 /* adtc R1 */ +#define SD_APP_SECURE_ERASE 38 /* adtc R1b */ +#define SD_APP_GET_MKB 43 /* adtc [31:0] See below R1 */ +#define SD_APP_GET_MID 44 /* adtc R1 */ +#define SD_APP_SET_CER_RN1 45 /* adtc R1 */ +#define SD_APP_GET_CER_RN2 46 /* adtc R1 */ +#define SD_APP_SET_CER_RES2 47 /* adtc R1 */ +#define SD_APP_GET_CER_RES1 48 /* adtc R1 */ +#define SD_APP_CHANGE_SECURE_AREA 49 /* adtc R1b */ /* OCR bit definitions */ +#define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */ +#define SD_VHD_27_36 (1 << 8) /* VDD voltage 2.7 ~ 3.6 */ +#define SD_OCR_VDD_27_34 (0x7F << 15) /* VDD voltage 2.7 ~ 3.4 */ +#define SD_OCR_VDD_32_33 (1 << 20) /* VDD voltage 3.2 ~ 3.3 */ #define SD_OCR_S18R (1 << 24) /* 1.8V switching request */ #define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */ #define SD_OCR_XPC (1 << 28) /* SDXC power control */ #define SD_OCR_CCS (1 << 30) /* Card Capacity Status */ -#define SD_OCR_VDD_27_34 (0x7F << 15) /* VDD voltage 2.7 ~ 3.4 */ -#define SD_OCR_VDD_32_33 (1 << 20) /* VDD voltage 3.2 ~ 3.3 */ -#define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */ +#define SD_OCR_BUSY (1 << 31) /* Card Power up Status */ /* -* SD_SWITCH argument format: -* -* [31] Check (0) or switch (1) -* [30:24] Reserved (0) -* [23:20] Function group 6 -* [19:16] Function group 5 -* [15:12] Function group 4 -* [11:8] Function group 3 -* [7:4] Function group 2 -* [3:0] Function group 1 -*/ + * SD_SWITCH argument format: + * + * [31] Check (0) or switch (1) + * [30:24] Reserved (0) + * [23:20] Function group 6 + * [19:16] Function group 5 + * [15:12] Function group 4 + * [11:8] Function group 3 + * [7:4] Function group 2 + * [3:0] Function group 1 + */ /* -* SD_SEND_IF_COND argument format: -* -* [31:12] Reserved (0) -* [11:8] Host Voltage Supply Flags -* [7:0] Check Pattern (0xAA) -*/ + * SD_SEND_IF_COND argument format: + * + * [31:12] Reserved (0) + * [11:8] Host Voltage Supply Flags + * [7:0] Check Pattern (0xAA) + */ /* -* SCR field definitions -*/ + * SD_APP_GET_MKB argument format: + * + * [31:24] Number of blocks to read (512 block size) + * [23:16] MKB ID + * [15:0] Block offset + */ + +/* + * SCR field definitions + */ #define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */ #define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */ #define SCR_SPEC_VER_2 2 /* Implements system specification 2.00-3.0X */ @@ -73,14 +94,14 @@ #define SD_SCR_BUS_WIDTH_4 (1<<2) /* -* SD bus widths -*/ + * SD bus widths + */ #define SD_BUS_WIDTH_1 0 #define SD_BUS_WIDTH_4 2 /* -* SD bus speeds -*/ + * SD bus speeds + */ #define UHS_SDR12_BUS_SPEED 0 #define HIGH_SPEED_BUS_SPEED 1 #define UHS_SDR25_BUS_SPEED 1 @@ -110,19 +131,19 @@ #define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800) /* -* SD_SWITCH mode -*/ + * SD_SWITCH mode + */ #define SD_SWITCH_CHECK 0 #define SD_SWITCH_SET 1 /* -* SD_SWITCH function groups -*/ + * SD_SWITCH function groups + */ #define SD_SWITCH_GRP_ACCESS 0 /* -* SD_SWITCH access modes -*/ + * SD_SWITCH access modes + */ #define SD_SWITCH_ACCESS_DEF 0 #define SD_SWITCH_ACCESS_HS 1 diff --git a/bdk/storage/sdmmc.c b/bdk/storage/sdmmc.c index 43f837d..54b19de 100644 --- a/bdk/storage/sdmmc.c +++ b/bdk/storage/sdmmc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2020 CTCaer + * Copyright (c) 2018-2021 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -42,10 +42,10 @@ static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size) } /* -* Common functions for SD and MMC. -*/ + * Common functions for SD and MMC. + */ -static int _sdmmc_storage_check_result(u32 res) +static int _sdmmc_storage_check_card_status(u32 res) { //Error mask: //TODO: R1_SWITCH_ERROR can be skipped for certain card types. @@ -66,15 +66,15 @@ static int _sdmmc_storage_execute_cmd_type1_ex(sdmmc_storage_t *storage, u32 *re { sdmmc_cmd_t cmdbuf; sdmmc_init_cmd(&cmdbuf, cmd, arg, SDMMC_RSP_TYPE_1, check_busy); - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0)) + if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL)) return 0; sdmmc_get_rsp(storage->sdmmc, resp, 4, SDMMC_RSP_TYPE_1); if (mask) *resp &= ~mask; - if (_sdmmc_storage_check_result(*resp)) - if (expected_state == 0x10 || R1_CURRENT_STATE(*resp) == expected_state) + if (_sdmmc_storage_check_card_status(*resp)) + if (expected_state == R1_SKIP_STATE_CHECK || R1_CURRENT_STATE(*resp) == expected_state) return 1; return 0; @@ -88,37 +88,37 @@ static int _sdmmc_storage_execute_cmd_type1(sdmmc_storage_t *storage, u32 cmd, u static int _sdmmc_storage_go_idle_state(sdmmc_storage_t *storage) { - sdmmc_cmd_t cmd; - sdmmc_init_cmd(&cmd, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0); + sdmmc_cmd_t cmdbuf; + sdmmc_init_cmd(&cmdbuf, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0); - return sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0); + return sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL); } -static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage, void *buf) +static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage) { - sdmmc_cmd_t cmd; - sdmmc_init_cmd(&cmd, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0); - if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0)) + sdmmc_cmd_t cmdbuf; + sdmmc_init_cmd(&cmdbuf, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0); + if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL)) return 0; - sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2); + sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_cid, 16, SDMMC_RSP_TYPE_2); return 1; } static int _sdmmc_storage_select_card(sdmmc_storage_t *storage) { - return _sdmmc_storage_execute_cmd_type1(storage, MMC_SELECT_CARD, storage->rca << 16, 1, 0x10); + return _sdmmc_storage_execute_cmd_type1(storage, MMC_SELECT_CARD, storage->rca << 16, 1, R1_SKIP_STATE_CHECK); } -static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage, void *buf) +static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage) { sdmmc_cmd_t cmdbuf; sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0); - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0)) + if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL)) return 0; - sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2); + sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_csd, 16, SDMMC_RSP_TYPE_2); return 1; } @@ -145,6 +145,10 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out sdmmc_cmd_t cmdbuf; sdmmc_req_t reqbuf; + // If SDSC convert block address to byte address. + if (!storage->has_sector_access) + sector <<= 9; + sdmmc_init_cmd(&cmdbuf, is_write ? MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK, sector, SDMMC_RSP_TYPE_1, 0); reqbuf.buf = buf; @@ -152,7 +156,7 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out reqbuf.blksize = 512; reqbuf.is_write = is_write; reqbuf.is_multi_block = 1; - reqbuf.is_auto_cmd12 = 1; + reqbuf.is_auto_stop_trn = 1; if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, blkcnt_out)) { @@ -288,25 +292,25 @@ int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, v static int _mmc_storage_get_op_cond_inner(sdmmc_storage_t *storage, u32 *pout, u32 power) { - sdmmc_cmd_t cmd; + sdmmc_cmd_t cmdbuf; u32 arg = 0; switch (power) { case SDMMC_POWER_1_8: - arg = SD_OCR_CCS | SD_OCR_VDD_18; + arg = MMC_CARD_CCS | MMC_CARD_VDD_18; break; case SDMMC_POWER_3_3: - arg = SD_OCR_CCS | SD_OCR_VDD_27_34; + arg = MMC_CARD_CCS | MMC_CARD_VDD_27_34; break; default: return 0; } - sdmmc_init_cmd(&cmd, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0); - if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0)) + sdmmc_init_cmd(&cmdbuf, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0); + if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL)) return 0; return sdmmc_get_rsp(storage->sdmmc, pout, 4, SDMMC_RSP_TYPE_3); @@ -316,15 +320,17 @@ static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power) { u32 timeout = get_tmr_ms() + 1500; - while (1) + while (true) { u32 cond = 0; if (!_mmc_storage_get_op_cond_inner(storage, &cond, power)) break; + // Check if power up is done. if (cond & MMC_CARD_BUSY) { - if (cond & SD_OCR_CCS) + // Check if card is high capacity. + if (cond & MMC_CARD_CCS) storage->has_sector_access = 1; return 1; @@ -340,7 +346,7 @@ static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power) static int _mmc_storage_set_relative_addr(sdmmc_storage_t *storage) { - return _sdmmc_storage_execute_cmd_type1(storage, MMC_SET_RELATIVE_ADDR, storage->rca << 16, 0, 0x10); + return _sdmmc_storage_execute_cmd_type1(storage, MMC_SET_RELATIVE_ADDR, storage->rca << 16, 0, R1_SKIP_STATE_CHECK); } static void _mmc_storage_parse_cid(sdmmc_storage_t *storage) @@ -362,7 +368,6 @@ static void _mmc_storage_parse_cid(sdmmc_storage_t *storage) case 3: /* MMC v3.1 - v3.3 */ case 4: /* MMC v4 */ storage->cid.manfid = unstuff_bits(raw_cid, 120, 8); - storage->cid.card_bga = unstuff_bits(raw_cid, 112, 2); storage->cid.oemid = unstuff_bits(raw_cid, 104, 8); storage->cid.prv = unstuff_bits(raw_cid, 48, 8); storage->cid.serial = unstuff_bits(raw_cid, 16, 32); @@ -390,13 +395,14 @@ static void _mmc_storage_parse_cid(sdmmc_storage_t *storage) static void _mmc_storage_parse_csd(sdmmc_storage_t *storage) { - u32 *raw_csd = (u32 *)&(storage->raw_csd); + u32 *raw_csd = (u32 *)storage->raw_csd; storage->csd.mmca_vsn = unstuff_bits(raw_csd, 122, 4); storage->csd.structure = unstuff_bits(raw_csd, 126, 2); storage->csd.cmdclass = unstuff_bits(raw_csd, 84, 12); storage->csd.read_blkbits = unstuff_bits(raw_csd, 80, 4); storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2); + storage->sec_cnt = storage->csd.capacity; } static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf) @@ -407,16 +413,26 @@ static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf) storage->ext_csd.dev_version = *(u16 *)&buf[EXT_CSD_DEVICE_VERSION]; storage->ext_csd.boot_mult = buf[EXT_CSD_BOOT_MULT]; storage->ext_csd.rpmb_mult = buf[EXT_CSD_RPMB_MULT]; - storage->ext_csd.sectors = *(u32 *)&buf[EXT_CSD_SEC_CNT]; - storage->ext_csd.bkops = buf[EXT_CSD_BKOPS_SUPPORT]; - storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN]; - storage->ext_csd.bkops_status = buf[EXT_CSD_BKOPS_STATUS]; + //storage->ext_csd.bkops = buf[EXT_CSD_BKOPS_SUPPORT]; + //storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN]; + //storage->ext_csd.bkops_status = buf[EXT_CSD_BKOPS_STATUS]; storage->ext_csd.pre_eol_info = buf[EXT_CSD_PRE_EOL_INFO]; storage->ext_csd.dev_life_est_a = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A]; storage->ext_csd.dev_life_est_b = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B]; - storage->sec_cnt = *(u32 *)&buf[EXT_CSD_SEC_CNT]; + storage->ext_csd.cache_size = + buf[EXT_CSD_CACHE_SIZE] | + (buf[EXT_CSD_CACHE_SIZE + 1] << 8) | + (buf[EXT_CSD_CACHE_SIZE + 2] << 16) | + (buf[EXT_CSD_CACHE_SIZE + 3] << 24); + storage->ext_csd.max_enh_mult = + (buf[EXT_CSD_MAX_ENH_SIZE_MULT] | + (buf[EXT_CSD_MAX_ENH_SIZE_MULT + 1] << 8) | + (buf[EXT_CSD_MAX_ENH_SIZE_MULT + 2] << 16)) * + buf[EXT_CSD_HC_WP_GRP_SIZE] * buf[EXT_CSD_HC_ERASE_GRP_SIZE]; + + storage->sec_cnt = *(u32 *)&buf[EXT_CSD_SEC_CNT]; } static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf) @@ -430,21 +446,21 @@ static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf) reqbuf.num_sectors = 1; reqbuf.is_write = 0; reqbuf.is_multi_block = 0; - reqbuf.is_auto_cmd12 = 0; + reqbuf.is_auto_stop_trn = 0; - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, 0)) + if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL)) return 0; u32 tmp = 0; sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); _mmc_storage_parse_ext_csd(storage, buf); - return _sdmmc_storage_check_result(tmp); + return _sdmmc_storage_check_card_status(tmp); } static int _mmc_storage_switch(sdmmc_storage_t *storage, u32 arg) { - return _sdmmc_storage_execute_cmd_type1(storage, MMC_SWITCH, arg, 1, 0x10); + return _sdmmc_storage_execute_cmd_type1(storage, MMC_SWITCH, arg, 1, R1_SKIP_STATE_CHECK); } static int _mmc_storage_switch_buswidth(sdmmc_storage_t *storage, u32 bus_width) @@ -559,19 +575,21 @@ out: return 1; } +/* static int _mmc_storage_enable_bkops(sdmmc_storage_t *storage) { - if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_BKOPS_LEVEL_2))) + if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_AUTO_BKOPS_MASK))) return 0; return _sdmmc_storage_check_status(storage); } +*/ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type) { memset(storage, 0, sizeof(sdmmc_storage_t)); storage->sdmmc = sdmmc; - storage->rca = 2; //TODO: this could be a config item. + storage->rca = 2; // Set default device address. This could be a config item. if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_MMC_ID, SDMMC_POWER_SAVE_DISABLE)) return 0; @@ -587,7 +605,7 @@ DPRINTF("[MMC] went to idle state\n"); return 0; DPRINTF("[MMC] got op cond\n"); - if (!_sdmmc_storage_get_cid(storage, storage->raw_cid)) + if (!_sdmmc_storage_get_cid(storage)) return 0; DPRINTF("[MMC] got cid\n"); @@ -595,7 +613,7 @@ DPRINTF("[MMC] got cid\n"); return 0; DPRINTF("[MMC] set relative addr\n"); - if (!_sdmmc_storage_get_csd(storage, storage->raw_csd)) + if (!_sdmmc_storage_get_csd(storage)) return 0; DPRINTF("[MMC] got csd\n"); _mmc_storage_parse_csd(storage); @@ -612,13 +630,9 @@ DPRINTF("[MMC] card selected\n"); return 0; DPRINTF("[MMC] set blocklen to 512\n"); - u32 *csd = (u32 *)storage->raw_csd; - //Check system specification version, only version 4.0 and later support below features. - if (unstuff_bits(csd, 122, 4) < CSD_SPEC_VER_4) - { - storage->sec_cnt = (1 + unstuff_bits(csd, 62, 12)) << (unstuff_bits(csd, 47, 3) + 2); + // Check system specification version, only version 4.0 and later support below features. + if (storage->csd.mmca_vsn < CSD_SPEC_VER_4) return 1; - } if (!_mmc_storage_switch_buswidth(storage, bus_width)) return 0; @@ -628,21 +642,20 @@ DPRINTF("[MMC] switched buswidth\n"); return 0; DPRINTF("[MMC] got ext_csd\n"); - _mmc_storage_parse_cid(storage); //This needs to be after csd and ext_csd + _mmc_storage_parse_cid(storage); // This needs to be after csd and ext_csd. //gfx_hexdump(0, ext_csd, 512); - /* When auto BKOPS is enabled the mmc device should be powered all the time until we disable this and check status. - Disable it for now until BKOPS disable added to power down sequence at sdmmc_storage_end(). - Additionally this works only when we put the device in idle mode which we don't after enabling it. */ - if (0 && storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_BKOPS_LEVEL_2)) +/* + if (storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_AUTO_BKOPS_MASK)) { _mmc_storage_enable_bkops(storage); DPRINTF("[MMC] BKOPS enabled\n"); } +*/ if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type)) return 0; -DPRINTF("[MMC] succesfully switched to HS mode\n"); +DPRINTF("[MMC] successfully switched to HS mode\n"); sdmmc_card_clock_powersave(storage->sdmmc, SDMMC_POWER_SAVE_ENABLE); @@ -665,16 +678,16 @@ int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition) } /* -* SD specific functions. -*/ + * SD specific functions. + */ -static int _sd_storage_execute_app_cmd(sdmmc_storage_t *storage, u32 expected_state, u32 mask, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out) +static int _sd_storage_execute_app_cmd(sdmmc_storage_t *storage, u32 expected_state, u32 mask, sdmmc_cmd_t *cmdbuf, sdmmc_req_t *req, u32 *blkcnt_out) { u32 tmp; if (!_sdmmc_storage_execute_cmd_type1_ex(storage, &tmp, MMC_APP_CMD, storage->rca << 16, 0, expected_state, mask)) return 0; - return sdmmc_execute_cmd(storage->sdmmc, cmd, req, blkcnt_out); + return sdmmc_execute_cmd(storage->sdmmc, cmdbuf, req, blkcnt_out); } static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp, u32 cmd, u32 arg, u32 check_busy, u32 expected_state) @@ -685,60 +698,70 @@ static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp return _sdmmc_storage_execute_cmd_type1_ex(storage, resp, cmd, arg, check_busy, expected_state, 0); } -static int _sd_storage_send_if_cond(sdmmc_storage_t *storage) +static int _sd_storage_send_if_cond(sdmmc_storage_t *storage, bool *is_sdsc) { sdmmc_cmd_t cmdbuf; - sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, 0x1AA, SDMMC_RSP_TYPE_5, 0); - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0)) - return 1; // The SD Card is version 1.X + u16 vhd_pattern = SD_VHD_27_36 | 0xAA; + sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, vhd_pattern, SDMMC_RSP_TYPE_5, 0); + if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL)) + { + *is_sdsc = 1; // The SD Card is version 1.X + return 1; + } + // For Card version >= 2.0, parse results. u32 resp = 0; - if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5)) - return 2; + sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5); - return (resp & 0xFF) == 0xAA ? 0 : 2; + // Check if VHD was accepted and pattern was properly returned. + if ((resp & 0xFFF) == vhd_pattern) + return 1; + + return 0; } -static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int is_version_1, int bus_low_voltage_support) +static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, bool is_sdsc, int bus_uhs_support) { sdmmc_cmd_t cmdbuf; // Support for Current > 150mA - u32 arg = (~is_version_1 & 1) ? SD_OCR_XPC : 0; + u32 arg = !is_sdsc ? SD_OCR_XPC : 0; // Support for handling block-addressed SDHC cards - arg |= (~is_version_1 & 1) ? SD_OCR_CCS : 0; + arg |= !is_sdsc ? SD_OCR_CCS : 0; // Support for 1.8V - arg |= (bus_low_voltage_support & ~is_version_1 & 1) ? SD_OCR_S18R : 0; + arg |= (bus_uhs_support && !is_sdsc) ? SD_OCR_S18R : 0; // This is needed for most cards. Do not set bit7 even if 1.8V is supported. arg |= SD_OCR_VDD_32_33; sdmmc_init_cmd(&cmdbuf, SD_APP_OP_COND, arg, SDMMC_RSP_TYPE_3, 0); - if (!_sd_storage_execute_app_cmd(storage, 0x10, is_version_1 ? 0x400000 : 0, &cmdbuf, 0, 0)) + if (!_sd_storage_execute_app_cmd(storage, R1_SKIP_STATE_CHECK, is_sdsc ? R1_ILLEGAL_COMMAND : 0, &cmdbuf, NULL, NULL)) return 0; return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3); } -static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, int bus_low_voltage_support) +static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, bool is_sdsc, int bus_uhs_support) { u32 timeout = get_tmr_ms() + 1500; - while (1) + while (true) { u32 cond = 0; - if (!_sd_storage_get_op_cond_once(storage, &cond, is_version_1, bus_low_voltage_support)) + if (!_sd_storage_get_op_cond_once(storage, &cond, is_sdsc, bus_uhs_support)) break; - if (cond & MMC_CARD_BUSY) - { -DPRINTF("[SD] cond: %08X, lv: %d\n", cond, bus_low_voltage_support); + // Check if power up is done. + if (cond & SD_OCR_BUSY) + { +DPRINTF("[SD] op cond: %08X, lv: %d\n", cond, bus_uhs_support); + + // Check if card is high capacity. if (cond & SD_OCR_CCS) storage->has_sector_access = 1; // Check if card supports 1.8V signaling. - if (cond & SD_ROCR_S18A && bus_low_voltage_support) + if (cond & SD_ROCR_S18A && bus_uhs_support) { - //The low voltage regulator configuration is valid for SDMMC1 only. - if (storage->sdmmc->id == SDMMC_1 && - _sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY)) + // Switch to 1.8V signaling. + if (_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY)) { if (!sdmmc_enable_low_voltage(storage->sdmmc)) return 0; @@ -769,9 +792,9 @@ static int _sd_storage_get_rca(sdmmc_storage_t *storage) u32 timeout = get_tmr_ms() + 1500; - while (1) + while (true) { - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0)) + if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL)) break; u32 resp = 0; @@ -802,8 +825,9 @@ static void _sd_storage_parse_scr(sdmmc_storage_t *storage) storage->scr.sda_vsn = unstuff_bits(resp, 56, 4); storage->scr.bus_widths = unstuff_bits(resp, 48, 4); + + /* If v2.0 is supported, check if Physical Layer Spec v3.0 is supported */ if (storage->scr.sda_vsn == SCR_SPEC_VER_2) - /* Check if Physical Layer Spec v3.0 is supported */ storage->scr.sda_spec3 = unstuff_bits(resp, 47, 1); if (storage->scr.sda_spec3) storage->scr.cmds = unstuff_bits(resp, 32, 2); @@ -820,9 +844,9 @@ int _sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf) reqbuf.num_sectors = 1; reqbuf.is_write = 0; reqbuf.is_multi_block = 0; - reqbuf.is_auto_cmd12 = 0; + reqbuf.is_auto_stop_trn = 0; - if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, 0)) + if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, NULL)) return 0; u32 tmp = 0; @@ -838,7 +862,7 @@ int _sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf) _sd_storage_parse_scr(storage); //gfx_hexdump(0, storage->raw_scr, 8); - return _sdmmc_storage_check_result(tmp); + return _sdmmc_storage_check_card_status(tmp); } int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf) @@ -852,14 +876,14 @@ int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf) reqbuf.num_sectors = 1; reqbuf.is_write = 0; reqbuf.is_multi_block = 0; - reqbuf.is_auto_cmd12 = 0; + reqbuf.is_auto_stop_trn = 0; - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, 0)) + if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL)) return 0; u32 tmp = 0; sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); - return _sdmmc_storage_check_result(tmp); + return _sdmmc_storage_check_card_status(tmp); } int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group, u32 arg) @@ -876,14 +900,14 @@ int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group, reqbuf.num_sectors = 1; reqbuf.is_write = 0; reqbuf.is_multi_block = 0; - reqbuf.is_auto_cmd12 = 0; + reqbuf.is_auto_stop_trn = 0; - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, 0)) + if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL)) return 0; u32 tmp = 0; sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); - return _sdmmc_storage_check_result(tmp); + return _sdmmc_storage_check_card_status(tmp); } void _sd_storage_set_current_limit(sdmmc_storage_t *storage, u16 current_limit, u8 *buf) @@ -1057,41 +1081,64 @@ int _sd_storage_enable_hs_high_volt(sdmmc_storage_t *storage, u8 *buf) return sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_HS25); } +u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage) +{ + u32 au_size = storage->ssr.uhs_au_size; + + if (!au_size) + au_size = storage->ssr.au_size; + + if (au_size <= 10) + { + u32 shift = au_size; + au_size = shift ? 8 : 0; + au_size <<= shift; + } + else + { + switch (au_size) + { + case 11: + au_size = 12288; + break; + case 12: + au_size = 16384; + break; + case 13: + au_size = 24576; + break; + case 14: + au_size = 32768; + break; + case 15: + au_size = 65536; + break; + } + } + + return au_size; +} + static void _sd_storage_parse_ssr(sdmmc_storage_t *storage) { - // unstuff_bits supports only 4 u32 so break into 2 x 16byte groups + // unstuff_bits supports only 4 u32 so break into 2 x u32x4 groups. u32 raw_ssr1[4]; u32 raw_ssr2[4]; - raw_ssr1[3] = *(u32 *)&storage->raw_ssr[12]; - raw_ssr1[2] = *(u32 *)&storage->raw_ssr[8]; - raw_ssr1[1] = *(u32 *)&storage->raw_ssr[4]; - raw_ssr1[0] = *(u32 *)&storage->raw_ssr[0]; - - raw_ssr2[3] = *(u32 *)&storage->raw_ssr[28]; - raw_ssr2[2] = *(u32 *)&storage->raw_ssr[24]; - raw_ssr2[1] = *(u32 *)&storage->raw_ssr[20]; - raw_ssr2[0] = *(u32 *)&storage->raw_ssr[16]; + memcpy(raw_ssr1, &storage->raw_ssr[0], 16); + memcpy(raw_ssr2, &storage->raw_ssr[16], 16); storage->ssr.bus_width = (unstuff_bits(raw_ssr1, 510 - 384, 2) & SD_BUS_WIDTH_4) ? 4 : 1; storage->ssr.protected_size = unstuff_bits(raw_ssr1, 448 - 384, 32); - switch(unstuff_bits(raw_ssr1, 440 - 384, 8)) + u32 speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8); + switch(speed_class) { case 0: - storage->ssr.speed_class = 0; - break; - case 1: - storage->ssr.speed_class = 2; - break; - case 2: - storage->ssr.speed_class = 4; - break; - case 3: - storage->ssr.speed_class = 6; + storage->ssr.speed_class = speed_class << 1; break; case 4: @@ -1099,16 +1146,18 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage) break; default: - storage->ssr.speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8); + storage->ssr.speed_class = speed_class; break; } - storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4); + storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4); storage->ssr.video_class = unstuff_bits(raw_ssr1, 384 - 384, 8); + storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4); - storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4); + storage->ssr.au_size = unstuff_bits(raw_ssr1, 428 - 384, 4); + storage->ssr.uhs_au_size = unstuff_bits(raw_ssr1, 392 - 384, 4); } -static int _sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf) +int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf) { sdmmc_cmd_t cmdbuf; sdmmc_init_cmd(&cmdbuf, SD_APP_SD_STATUS, 0, SDMMC_RSP_TYPE_1, 0); @@ -1119,49 +1168,51 @@ static int _sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf) reqbuf.num_sectors = 1; reqbuf.is_write = 0; reqbuf.is_multi_block = 0; - reqbuf.is_auto_cmd12 = 0; + reqbuf.is_auto_stop_trn = 0; if (!(storage->csd.cmdclass & CCC_APP_SPEC)) { -DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n"); +DPRINTF("[SD] ssr: Not supported\n"); return 0; } - if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, 0)) + if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, NULL)) return 0; u32 tmp = 0; sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); - //Prepare buffer for unstuff_bits - for (int i = 0; i < 64; i+=4) + + // Convert buffer to LE. + for (int i = 0; i < 64; i += 4) { storage->raw_ssr[i + 3] = buf[i]; storage->raw_ssr[i + 2] = buf[i + 1]; storage->raw_ssr[i + 1] = buf[i + 2]; storage->raw_ssr[i] = buf[i + 3]; } + _sd_storage_parse_ssr(storage); //gfx_hexdump(0, storage->raw_ssr, 64); - return _sdmmc_storage_check_result(tmp); + return _sdmmc_storage_check_card_status(tmp); } static void _sd_storage_parse_cid(sdmmc_storage_t *storage) { u32 *raw_cid = (u32 *)&(storage->raw_cid); - storage->cid.manfid = unstuff_bits(raw_cid, 120, 8); - storage->cid.oemid = unstuff_bits(raw_cid, 104, 16); - storage->cid.prod_name[0] = unstuff_bits(raw_cid, 96, 8); - storage->cid.prod_name[1] = unstuff_bits(raw_cid, 88, 8); - storage->cid.prod_name[2] = unstuff_bits(raw_cid, 80, 8); - storage->cid.prod_name[3] = unstuff_bits(raw_cid, 72, 8); - storage->cid.prod_name[4] = unstuff_bits(raw_cid, 64, 8); - storage->cid.hwrev = unstuff_bits(raw_cid, 60, 4); - storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4); - storage->cid.serial = unstuff_bits(raw_cid, 24, 32); - storage->cid.month = unstuff_bits(raw_cid, 8, 4); - storage->cid.year = unstuff_bits(raw_cid, 12, 8) + 2000; + storage->cid.manfid = unstuff_bits(raw_cid, 120, 8); + storage->cid.oemid = unstuff_bits(raw_cid, 104, 16); + storage->cid.prod_name[0] = unstuff_bits(raw_cid, 96, 8); + storage->cid.prod_name[1] = unstuff_bits(raw_cid, 88, 8); + storage->cid.prod_name[2] = unstuff_bits(raw_cid, 80, 8); + storage->cid.prod_name[3] = unstuff_bits(raw_cid, 72, 8); + storage->cid.prod_name[4] = unstuff_bits(raw_cid, 64, 8); + storage->cid.hwrev = unstuff_bits(raw_cid, 60, 4); + storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4); + storage->cid.serial = unstuff_bits(raw_cid, 24, 32); + storage->cid.year = unstuff_bits(raw_cid, 12, 8) + 2000; + storage->cid.month = unstuff_bits(raw_cid, 8, 4); } static void _sd_storage_parse_csd(sdmmc_storage_t *storage) @@ -1176,6 +1227,7 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage) { case 0: storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2); + storage->csd.capacity <<= unstuff_bits(raw_csd, 80, 4) - 9; // Convert native block size to LBA 512B. break; case 1: @@ -1183,10 +1235,16 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage) storage->csd.capacity = storage->csd.c_size << 10; storage->csd.read_blkbits = 9; break; + + default: +DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure); + break; } + + storage->sec_cnt = storage->csd.capacity; } -static bool _sdmmc_storage_get_low_voltage_support(u32 bus_width, u32 type) +static bool _sdmmc_storage_get_bus_uhs_support(u32 bus_width, u32 type) { switch (type) { @@ -1213,8 +1271,10 @@ void sdmmc_storage_init_wait_sd() int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type) { - int is_version_1 = 0; - u8 *buf = (u8 *)SDMMC_UPPER_BUFFER; + u32 tmp = 0; + int is_sdsc = 0; + u8 *buf = (u8 *)SDMMC_UPPER_BUFFER; + bool bus_uhs_support = _sdmmc_storage_get_bus_uhs_support(bus_width, type); DPRINTF("[SD] init: bus: %d, type: %d\n", bus_width, type); @@ -1234,18 +1294,15 @@ DPRINTF("[SD] after init\n"); return 0; DPRINTF("[SD] went to idle state\n"); - is_version_1 = _sd_storage_send_if_cond(storage); - if (is_version_1 == 2) + if (!_sd_storage_send_if_cond(storage, &is_sdsc)) return 0; DPRINTF("[SD] after send if cond\n"); - bool bus_low_voltage_support = _sdmmc_storage_get_low_voltage_support(bus_width, type); - - if (!_sd_storage_get_op_cond(storage, is_version_1, bus_low_voltage_support)) + if (!_sd_storage_get_op_cond(storage, is_sdsc, bus_uhs_support)) return 0; DPRINTF("[SD] got op cond\n"); - if (!_sdmmc_storage_get_cid(storage, storage->raw_cid)) + if (!_sdmmc_storage_get_cid(storage)) return 0; DPRINTF("[SD] got cid\n"); _sd_storage_parse_cid(storage); @@ -1254,30 +1311,16 @@ DPRINTF("[SD] got cid\n"); return 0; DPRINTF("[SD] got rca (= %04X)\n", storage->rca); - if (!_sdmmc_storage_get_csd(storage, storage->raw_csd)) + if (!_sdmmc_storage_get_csd(storage)) return 0; DPRINTF("[SD] got csd\n"); - - //Parse CSD. _sd_storage_parse_csd(storage); - switch (storage->csd.structure) - { - case 0: - storage->sec_cnt = storage->csd.capacity; - break; - case 1: - storage->sec_cnt = storage->csd.c_size << 10; - break; - default: -DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure); - break; - } if (!storage->is_low_voltage) { if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_DS12)) return 0; -DPRINTF("[SD] after setup clock\n"); +DPRINTF("[SD] after setup default clock\n"); } if (!_sdmmc_storage_select_card(storage)) @@ -1288,19 +1331,17 @@ DPRINTF("[SD] card selected\n"); return 0; DPRINTF("[SD] set blocklen to 512\n"); - u32 tmp = 0; + // Disconnect Card Detect resistor from DAT3. if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_CLR_CARD_DETECT, 0, 0, R1_STATE_TRAN)) return 0; DPRINTF("[SD] cleared card detect\n"); if (!_sd_storage_get_scr(storage, buf)) return 0; - - //gfx_hexdump(0, storage->raw_scr, 8); DPRINTF("[SD] got scr\n"); - // Check if card supports a wider bus and if it's not SD Version 1.X - if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & 4) && (storage->scr.sda_vsn & 0xF)) + // If card supports a wider bus and if it's not SD Version 1.0 switch bus width. + if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & BIT(SD_BUS_WIDTH_4)) && storage->scr.sda_vsn) { if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_BUS_WIDTH, SD_BUS_WIDTH_4, 0, R1_STATE_TRAN)) return 0; @@ -1310,6 +1351,7 @@ DPRINTF("[SD] switched to wide bus width\n"); } else { + bus_width = SDMMC_BUS_WIDTH_1; DPRINTF("[SD] SD does not support wide bus width\n"); } @@ -1321,7 +1363,7 @@ DPRINTF("[SD] enabled UHS\n"); sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE); } - else if (type != SDHCI_TIMING_SD_DS12 && (storage->scr.sda_vsn & 0xF) != 0) + else if (type != SDHCI_TIMING_SD_DS12 && storage->scr.sda_vsn) // Not default speed and not SD Version 1.0. { if (!_sd_storage_enable_hs_high_volt(storage, buf)) return 0; @@ -1340,7 +1382,7 @@ DPRINTF("[SD] enabled HS\n"); } // Parse additional card info from sd status. - if (_sd_storage_get_ssr(storage, buf)) + if (sd_storage_get_ssr(storage, buf)) { DPRINTF("[SD] got sd status\n"); } @@ -1351,14 +1393,14 @@ DPRINTF("[SD] got sd status\n"); } /* -* Gamecard specific functions. -*/ + * Gamecard specific functions. + */ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf) { u32 resp; sdmmc_cmd_t cmdbuf; - sdmmc_init_cmd(&cmdbuf, 60, 0, SDMMC_RSP_TYPE_1, 1); + sdmmc_init_cmd(&cmdbuf, MMC_VENDOR_60_CMD, 0, SDMMC_RSP_TYPE_1, 1); sdmmc_req_t reqbuf; reqbuf.buf = buf; @@ -1366,9 +1408,9 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf) reqbuf.num_sectors = 1; reqbuf.is_write = 1; reqbuf.is_multi_block = 0; - reqbuf.is_auto_cmd12 = 0; + reqbuf.is_auto_stop_trn = 0; - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, 0)) + if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL)) { sdmmc_stop_transmission(storage->sdmmc, &resp); return 0; @@ -1376,7 +1418,7 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf) if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_1)) return 0; - if (!_sdmmc_storage_check_result(resp)) + if (!_sdmmc_storage_check_card_status(resp)) return 0; return _sdmmc_storage_check_status(storage); } diff --git a/bdk/storage/sdmmc.h b/bdk/storage/sdmmc.h index 68d70f0..2b59f7d 100644 --- a/bdk/storage/sdmmc.h +++ b/bdk/storage/sdmmc.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2020 CTCaer + * Copyright (c) 2018-2021 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -30,18 +30,18 @@ typedef enum _sdmmc_type EMMC_GPP = 0, EMMC_BOOT0 = 1, - EMMC_BOOT1 = 2 + EMMC_BOOT1 = 2, + EMMC_RPMB = 3 } sdmmc_type; typedef struct _mmc_cid { u32 manfid; u8 prod_name[8]; - u8 card_bga; - u8 prv; u32 serial; u16 oemid; u16 year; + u8 prv; u8 hwrev; u8 fwrev; u8 month; @@ -65,19 +65,20 @@ typedef struct _mmc_csd typedef struct _mmc_ext_csd { - u32 sectors; - int bkops; /* background support bit */ - int bkops_en; /* manual bkops enable bit */ + //u8 bkops; /* background support bit */ + //u8 bkops_en; /* manual bkops enable bit */ + //u8 bkops_status; /* 246 */ u8 rev; u8 ext_struct; /* 194 */ u8 card_type; /* 196 */ - u8 bkops_status; /* 246 */ u8 pre_eol_info; u8 dev_life_est_a; u8 dev_life_est_b; u8 boot_mult; u8 rpmb_mult; u16 dev_version; + u32 cache_size; + u32 max_enh_mult; } mmc_ext_csd_t; typedef struct _sd_scr @@ -90,11 +91,13 @@ typedef struct _sd_scr typedef struct _sd_ssr { - u8 bus_width; - u8 speed_class; - u8 uhs_grade; - u8 video_class; - u8 app_class; + u8 bus_width; + u8 speed_class; + u8 uhs_grade; + u8 video_class; + u8 app_class; + u8 au_size; + u8 uhs_au_size; u32 protected_size; } sd_ssr_t; @@ -107,6 +110,7 @@ typedef struct _sdmmc_storage_t u32 sec_cnt; int is_low_voltage; u32 partition; + int initialized; u8 raw_cid[0x10]; u8 raw_csd[0x10]; u8 raw_scr[8]; @@ -116,16 +120,18 @@ typedef struct _sdmmc_storage_t mmc_ext_csd_t ext_csd; sd_scr_t scr; sd_ssr_t ssr; - int initialized; } sdmmc_storage_t; -int sdmmc_storage_end(sdmmc_storage_t *storage); -int sdmmc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf); -int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf); -int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type); -int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition); +int sdmmc_storage_end(sdmmc_storage_t *storage); +int sdmmc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf); +int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf); +int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type); +int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition); void sdmmc_storage_init_wait_sd(); -int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type); -int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc); +int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type); +int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc); + +int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf); +u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage); #endif diff --git a/bdk/storage/sdmmc_driver.c b/bdk/storage/sdmmc_driver.c index 3eaded0..5ceb2e7 100644 --- a/bdk/storage/sdmmc_driver.c +++ b/bdk/storage/sdmmc_driver.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2020 CTCaer + * Copyright (c) 2018-2021 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -501,7 +501,7 @@ int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type) break; case SDMMC_RSP_TYPE_2: - if (size < 0x10) + if (size < 16) return 0; rsp[0] = sdmmc->rsp[0]; rsp[1] = sdmmc->rsp[1]; @@ -934,12 +934,20 @@ static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req) *blkcnt_out = blkcnt; u32 trnmode = SDHCI_TRNS_DMA; + + // Set mulitblock request. if (req->is_multi_block) trnmode = SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_DMA; + + // Set request direction. if (!req->is_write) trnmode |= SDHCI_TRNS_READ; - if (req->is_auto_cmd12) - trnmode = (trnmode & ~(SDHCI_TRNS_AUTO_CMD12 | SDHCI_TRNS_AUTO_CMD23)) | SDHCI_TRNS_AUTO_CMD12; + + // Automatic send of stop transmission or set block count cmd. + if (req->is_auto_stop_trn) + trnmode |= SDHCI_TRNS_AUTO_CMD12; + //else if (req->is_auto_set_blkcnt) + // trnmode |= SDHCI_TRNS_AUTO_CMD23; sdmmc->regs->trnmod = trnmode; @@ -1052,7 +1060,7 @@ DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result, if (!result) { #ifdef ERROR_EXTRA_PRINTING - EPRINTFARGS("SDMMC: DMA Update failed (%08X)!", result); + EPRINTF("SDMMC: DMA Update failed!"); #endif } } @@ -1070,7 +1078,7 @@ DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result, if (blkcnt_out) *blkcnt_out = blkcnt; - if (req->is_auto_cmd12) + if (req->is_auto_stop_trn) sdmmc->rsp3 = sdmmc->regs->rspreg3; } @@ -1200,8 +1208,8 @@ static int _sdmmc_config_sdmmc1(bool t210b01) usleep(10000); // Enable SD card IO power. - max77620_regulator_set_voltage(REGULATOR_LDO2, 3300000); - max77620_regulator_enable(REGULATOR_LDO2, 1); + max7762x_regulator_set_voltage(REGULATOR_LDO2, 3300000); + max7762x_regulator_enable(REGULATOR_LDO2, true); usleep(1000); // Set pad slew codes to get good quality clock. @@ -1332,18 +1340,6 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int p void sdmmc1_disable_power() { - // Ensure regulator is into default voltage. - if (PMC(APBDEV_PMC_PWR_DET_VAL) & PMC_PWR_DET_SDMMC1_IO_EN) - { - // Switch to 1.8V and wait for regulator to stabilize. - max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000); - usleep(150); - - // Inform IO pads that we switched to 1.8V. - PMC(APBDEV_PMC_PWR_DET_VAL) &= ~(PMC_PWR_DET_SDMMC1_IO_EN); - (void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write. - } - // T210B01 WAR: Clear pull down from CLK pad. PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) &= ~PINMUX_PULL_MASK; @@ -1351,7 +1347,7 @@ void sdmmc1_disable_power() _sdmmc_config_sdmmc1_pads(true); // Disable SD card IO power regulator. - max77620_regulator_enable(REGULATOR_LDO2, 0); + max7762x_regulator_enable(REGULATOR_LDO2, false); usleep(4000); // Disable SD card IO power pin. @@ -1383,12 +1379,12 @@ void sdmmc_end(sdmmc_t *sdmmc) _sdmmc_sd_clock_disable(sdmmc); // Disable SDMMC power. _sdmmc_set_io_power(sdmmc, SDMMC_POWER_OFF); + _sdmmc_commit_changes(sdmmc); // Disable SD card power. if (sdmmc->id == SDMMC_1) sdmmc1_disable_power(); - _sdmmc_commit_changes(sdmmc); clock_sdmmc_disable(sdmmc->id); sdmmc->clock_stopped = 1; } @@ -1440,7 +1436,7 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc) _sdmmc_commit_changes(sdmmc); // Switch to 1.8V and wait for regulator to stabilize. Assume max possible wait needed. - max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000); + max7762x_regulator_set_voltage(REGULATOR_LDO2, 1800000); usleep(150); // Inform IO pads that we switched to 1.8V. diff --git a/bdk/storage/sdmmc_driver.h b/bdk/storage/sdmmc_driver.h index fb2b1b3..696ce4d 100644 --- a/bdk/storage/sdmmc_driver.h +++ b/bdk/storage/sdmmc_driver.h @@ -242,7 +242,7 @@ typedef struct _sdmmc_req_t u32 num_sectors; int is_write; int is_multi_block; - int is_auto_cmd12; + int is_auto_stop_trn; } sdmmc_req_t; int sdmmc_get_io_power(sdmmc_t *sdmmc); diff --git a/bdk/thermal/fan.c b/bdk/thermal/fan.c index f39b082..14379e3 100644 --- a/bdk/thermal/fan.c +++ b/bdk/thermal/fan.c @@ -26,7 +26,7 @@ void set_fan_duty(u32 duty) { static bool fan_init = false; - static u16 curr_duty = -1; + static u16 curr_duty = -1; if (curr_duty == duty) return; @@ -56,7 +56,7 @@ void set_fan_duty(u32 duty) if (inv_duty == 236) { PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (0x100 << 16); // Bit 24 is absolute 0%. - regulator_disable_5v(REGULATOR_5V_FAN); + regulator_5v_disable(REGULATOR_5V_FAN); // Disable fan. PINMUX_AUX(PINMUX_AUX_LCD_GPIO2) = @@ -65,7 +65,7 @@ void set_fan_duty(u32 duty) else // Set PWM duty. { // Fan power supply. - regulator_enable_5v(REGULATOR_5V_FAN); + regulator_5v_enable(REGULATOR_5V_FAN); PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (inv_duty << 16); // Enable fan. @@ -79,15 +79,14 @@ void get_fan_speed(u32 *duty, u32 *rpm) { if (rpm) { - u32 irq_count = 1; + u32 irq_count = 0; bool should_read = true; - bool irq_val = 0; - // Poll irqs for 2 seconds. - int timer = get_tmr_us() + 1000000; - while (timer - get_tmr_us()) + // Poll irqs for 2 seconds. (5 seconds for accurate count). + int timer = get_tmr_us() + 2000000; + while ((timer - get_tmr_us()) > 0) { - irq_val = gpio_read(GPIO_PORT_S, GPIO_PIN_7); + bool irq_val = gpio_read(GPIO_PORT_S, GPIO_PIN_7); if (irq_val && should_read) { irq_count++; @@ -97,8 +96,11 @@ void get_fan_speed(u32 *duty, u32 *rpm) should_read = true; } + // Halve the irq count. + irq_count /= 2; + // Calculate rpm based on triggered interrupts. - *rpm = 60000000 / ((1000000 * 2) / irq_count); + *rpm = irq_count * (60 / 2); } if (duty) diff --git a/bdk/thermal/tmp451.c b/bdk/thermal/tmp451.c index fb9f9fa..65f2fd2 100644 --- a/bdk/thermal/tmp451.c +++ b/bdk/thermal/tmp451.c @@ -1,7 +1,7 @@ /* * SOC/PCB Temperature driver for Nintendo Switch's TI TMP451 * - * Copyright (c) 2018 CTCaer + * Copyright (c) 2018-2020 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -16,7 +16,9 @@ * along with this program. If not, see . */ +#include #include +#include #include u16 tmp451_get_soc_temp(bool intenger) @@ -56,6 +58,20 @@ void tmp451_init() // Disable ALARM and Range to 0 - 127 oC. i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CONFIG_REG, 0x80); + // Set remote sensor offsets based on SoC. + if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210) + { + // Set offset to 0 oC for Erista. + i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFH_REG, 0); + i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFL_REG, 0); + } + else + { + // Set offset to -12.5 oC for Mariko. + i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFH_REG, 0xF3); // - 13 oC. + i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFL_REG, 0x80); // + 0.5 oC. + } + // Set conversion rate to 32/s and make a read to update the reg. i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CNV_RATE_REG, 9); tmp451_get_soc_temp(false); @@ -63,3 +79,9 @@ void tmp451_init() // Set rate to every 4 seconds. i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CNV_RATE_REG, 2); } + +void tmp451_end() +{ + // Place into shutdown mode to conserve power. + i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CONFIG_REG, 0xC0); +} diff --git a/bdk/thermal/tmp451.h b/bdk/thermal/tmp451.h index 9549ffa..6258fbd 100644 --- a/bdk/thermal/tmp451.h +++ b/bdk/thermal/tmp451.h @@ -32,11 +32,15 @@ #define TMP451_SOC_TMP_DEC_REG 0x10 #define TMP451_PCB_TMP_DEC_REG 0x15 +#define TMP451_SOC_TMP_OFH_REG 0x11 +#define TMP451_SOC_TMP_OFL_REG 0x12 + // If input is false, the return value is packed. MSByte is the integer in oC // and the LSByte is the decimal point truncated to 2 decimal places. // Otherwise it's an integer oC. u16 tmp451_get_soc_temp(bool integer); u16 tmp451_get_pcb_temp(bool integer); void tmp451_init(); +void tmp451_end(); #endif /* __TMP451_H_ */ diff --git a/bdk/usb/usb_gadget_hid.c b/bdk/usb/usb_gadget_hid.c index 3437b40..b7c2e24 100644 --- a/bdk/usb/usb_gadget_hid.c +++ b/bdk/usb/usb_gadget_hid.c @@ -309,7 +309,7 @@ static bool _fts_touch_read(touchpad_report_t *rpt) static u8 _hid_transfer_start(usb_ctxt_t *usbs, u32 len) { - u8 status = usb_ops.usb_device_ep1_in_write((u8 *)USB_EP_BULK_IN_BUF_ADDR, len, NULL, USB_XFER_SYNCED); + u8 status = usb_ops.usb_device_ep1_in_write((u8 *)USB_EP_BULK_IN_BUF_ADDR, len, NULL, USB_XFER_SYNCED_CMD); if (status == USB_ERROR_XFER_ERROR) { usbs->set_text(usbs->label, "#FFDD00 Error:# EP IN transfer!"); diff --git a/bdk/usb/usb_gadget_ums.c b/bdk/usb/usb_gadget_ums.c index 97deeb5..10bd56a 100644 --- a/bdk/usb/usb_gadget_ums.c +++ b/bdk/usb/usb_gadget_ums.c @@ -58,7 +58,7 @@ #define UMS_SCSI_TRANSFER_512K (0x80000 >> UMS_DISK_LBA_SHIFT) -#define UMS_EP_OUT_MAX_XFER (USB_EP_BULK_OUT_MAX_XFER >> UMS_DISK_LBA_SHIFT) +#define UMS_EP_OUT_MAX_XFER (USB_EP_BULK_OUT_MAX_XFER) // Length of a SCSI Command Data Block. #define SCSI_MAX_CMD_SZ 16 @@ -121,6 +121,15 @@ enum ums_state { UMS_STATE_TERMINATED }; +enum ums_result { + UMS_RES_OK = 0, + UMS_RES_IO_ERROR = -5, + UMS_RES_TIMEOUT = -3, + UMS_RES_PROT_FATAL = -4, + UMS_RES_INVALID_ARG = -22 +}; + + enum data_direction { DATA_DIR_UNKNOWN = 0, DATA_DIR_FROM_HOST, @@ -194,7 +203,7 @@ typedef struct _bulk_ctxt_t { typedef struct _usbd_gadget_ums_t { bulk_ctxt_t bulk_ctxt; - int cmnd_size; + u32 cmnd_size; u8 cmnd[SCSI_MAX_CMD_SZ]; u32 lun_idx; // lun index @@ -283,21 +292,21 @@ static int ums_wedge_bulk_in_endpoint(usbd_gadget_ums_t *ums) { /* usbd_set_ep_wedge(bulk_ctxt->bulk_in); */ - return 0; + return UMS_RES_OK; } static int ums_set_stall(u32 ep) { usb_ops.usbd_set_ep_stall(ep, USB_EP_CFG_STALL); - return 0; + return UMS_RES_OK; } static int ums_clear_stall(u32 ep) { usb_ops.usbd_set_ep_stall(ep, USB_EP_CFG_CLEAR); - return 0; + return UMS_RES_OK; } static void ums_flush_endpoint(u32 ep) @@ -306,13 +315,13 @@ static void ums_flush_endpoint(u32 ep) usb_ops.usbd_flush_endpoint(ep); } -static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32 ep, bool sync) +static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32 ep, u32 sync_timeout) { if (ep == bulk_ctxt->bulk_in) { bulk_ctxt->bulk_in_status = usb_ops.usb_device_ep1_in_write( bulk_ctxt->bulk_in_buf, bulk_ctxt->bulk_in_length, - &bulk_ctxt->bulk_in_length_actual, sync); + &bulk_ctxt->bulk_in_length_actual, sync_timeout); if (bulk_ctxt->bulk_in_status == USB_ERROR_XFER_ERROR) { @@ -322,14 +331,14 @@ static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, else if (bulk_ctxt->bulk_in_status == USB2_ERROR_XFER_NOT_ALIGNED) ums->set_text(ums->label, "#FFDD00 Error:# EP IN Buffer not aligned!"); - if (sync) + if (sync_timeout) bulk_ctxt->bulk_in_buf_state = BUF_STATE_EMPTY; } else { bulk_ctxt->bulk_out_status = usb_ops.usb_device_ep1_out_read( bulk_ctxt->bulk_out_buf, bulk_ctxt->bulk_out_length, - &bulk_ctxt->bulk_out_length_actual, sync); + &bulk_ctxt->bulk_out_length_actual, sync_timeout); if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR) { @@ -339,7 +348,7 @@ static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, else if (bulk_ctxt->bulk_out_status == USB2_ERROR_XFER_NOT_ALIGNED) ums->set_text(ums->label, "#FFDD00 Error:# EP OUT Buffer not aligned!"); - if (sync) + if (sync_timeout) bulk_ctxt->bulk_out_buf_state = BUF_STATE_FULL; } } @@ -377,7 +386,7 @@ static void _ums_transfer_finish(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, else { bulk_ctxt->bulk_out_status = usb_ops.usb_device_ep1_out_reading_finish( - &bulk_ctxt->bulk_out_length_actual, 1000000); + &bulk_ctxt->bulk_out_length_actual); if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR) { @@ -446,20 +455,20 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } } if (lba_offset >= ums->lun.num_sectors) { ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } // Check that request data size is not 0. u32 amount_left = ums->data_size_from_cmnd >> UMS_DISK_LBA_SHIFT; if (!amount_left) - return -5; // I/O error. /* No default reply */ + return UMS_RES_IO_ERROR; // No default reply. // Limit IO transfers based on request for faster concurrent reads. u32 max_io_transfer = (amount_left >= UMS_SCSI_TRANSFER_512K) ? @@ -520,7 +529,7 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) sdmmc_buf += amount << UMS_DISK_LBA_SHIFT; } - return -5; // I/O error no default reply here. /* No default reply */ + return UMS_RES_IO_ERROR; // No default reply. } /* @@ -541,7 +550,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums->lun.sense_data = SS_WRITE_PROTECTED; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } if (ums->cmnd[0] == SC_WRITE_6) @@ -555,7 +564,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } } @@ -564,7 +573,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } /* Carry out the file writes */ @@ -574,22 +583,20 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) while (amount_left_to_write > 0) { - /* Queue a request for more data from the host */ - if (amount_left_to_req) + if (amount_left_to_req > 0) { // Limit write to max supported read from EP OUT. - amount = MIN(amount_left_to_req, UMS_EP_OUT_MAX_XFER << UMS_DISK_LBA_SHIFT); + amount = MIN(amount_left_to_req, UMS_EP_OUT_MAX_XFER); - if (usb_lba_offset >= ums->lun.num_sectors) //////////Check if it works with concurrency + if (usb_lba_offset >= ums->lun.num_sectors) { ums->set_text(ums->label, "#FFDD00 Error:# Write - Past last sector!"); - amount_left_to_req = 0; ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; ums->lun.sense_data_info = usb_lba_offset; ums->lun.info_valid = 1; - continue; + break; } // Get the next buffer. @@ -612,7 +619,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) ums->lun.sense_data = SS_COMMUNICATION_FAILURE; ums->lun.sense_data_info = lba_offset; ums->lun.info_valid = 1; - sprintf(txt_buf, "#FFDD00 Error:# Write - Comm failure %d!", bulk_ctxt->bulk_out_status); + s_printf(txt_buf, "#FFDD00 Error:# Write - Comm failure %d!", bulk_ctxt->bulk_out_status); ums->set_text(ums->label, txt_buf); break; } @@ -668,7 +675,7 @@ DPRINTF("file write %X @ %X\n", amount, lba_offset); } } - return -5; // I/O error. /* No default reply */ + return UMS_RES_IO_ERROR; // No default reply. } static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) @@ -679,7 +686,7 @@ static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } // We allow DPO but we don't implement it. Check that nothing else is enabled. @@ -687,12 +694,12 @@ static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } u32 verification_length = get_array_be_to_le16(&ums->cmnd[7]); if (verification_length == 0) - return -5; // I/O error. /* No default reply */ + return UMS_RES_IO_ERROR; // No default reply. u32 amount; while (verification_length > 0) @@ -724,7 +731,7 @@ DPRINTF("File read %X @ %X\n", amount, lba_offset); lba_offset += amount; verification_length -= amount; } - return 0; + return UMS_RES_OK; } static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) @@ -742,7 +749,7 @@ static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) buf[3] = 20; // Additional length. buf += 4; - sprintf((char *)buf, "%04X%s", + s_printf((char *)buf, "%04X%s", ums->lun.storage->cid.serial, ums->lun.type == MMC_SD ? " SD " : " eMMC "); switch (ums->lun.partition) @@ -751,13 +758,13 @@ static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) strcpy((char *)buf + strlen((char *)buf), "RAW"); break; case EMMC_GPP + 1: - sprintf((char *)buf + strlen((char *)buf), "GPP"); + s_printf((char *)buf + strlen((char *)buf), "GPP"); break; case EMMC_BOOT0 + 1: - sprintf((char *)buf + strlen((char *)buf), "BOOT0"); + s_printf((char *)buf + strlen((char *)buf), "BOOT0"); break; case EMMC_BOOT1 + 1: - sprintf((char *)buf + strlen((char *)buf), "BOOT1"); + s_printf((char *)buf + strlen((char *)buf), "BOOT1"); break; } @@ -784,18 +791,18 @@ static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) switch (ums->lun.partition) { case 0: - sprintf((char *)buf, "%s", "SD RAW"); + s_printf((char *)buf, "%s", "SD RAW"); break; case EMMC_GPP + 1: - sprintf((char *)buf, "%s%s", + s_printf((char *)buf, "%s%s", ums->lun.type == MMC_SD ? "SD " : "eMMC ", "GPP"); break; case EMMC_BOOT0 + 1: - sprintf((char *)buf, "%s%s", + s_printf((char *)buf, "%s%s", ums->lun.type == MMC_SD ? "SD " : "eMMC ", "BOOT0"); break; case EMMC_BOOT1 + 1: - sprintf((char *)buf, "%s%s", + s_printf((char *)buf, "%s%s", ums->lun.type == MMC_SD ? "SD " : "eMMC ", "BOOT1"); break; } @@ -843,7 +850,7 @@ static int _scsi_read_capacity(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } put_array_le_to_be32(ums->lun.num_sectors - 1, &buf[0]); // Max logical block. @@ -866,14 +873,14 @@ static int _scsi_log_sense(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums->lun.sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } if (pc != 1) // Current cumulative values. { ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } memset(buf, 0, 8); @@ -915,7 +922,7 @@ static int _scsi_log_sense(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } put_array_le_to_be16(len - 4, &buf0[2]); @@ -938,14 +945,14 @@ static int _scsi_mode_sense(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } if (pc == 3) { ums->lun.sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } /* Write the mode parameter header. Fixed values are: default @@ -995,7 +1002,7 @@ static int _scsi_mode_sense(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } /* Store the mode data length */ @@ -1015,14 +1022,14 @@ static int _scsi_start_stop(usbd_gadget_ums_t *ums) { ums->lun.sense_data = SS_INVALID_COMMAND; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } else if ((ums->cmnd[1] & ~0x01) != 0 || // Mask away Immed. (ums->cmnd[4] & ~0x03) != 0) // Mask LoEj, Start. { ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; - return -22; + return UMS_RES_INVALID_ARG; } loej = ums->cmnd[4] & 0x02; @@ -1035,10 +1042,10 @@ static int _scsi_start_stop(usbd_gadget_ums_t *ums) { ums->lun.sense_data = SS_MEDIUM_NOT_PRESENT; - return -22; + return UMS_RES_INVALID_ARG; } - return 0; + return UMS_RES_OK; } // Check if we are allowed to unload the media. @@ -1047,16 +1054,16 @@ static int _scsi_start_stop(usbd_gadget_ums_t *ums) ums->set_text(ums->label, "#C7EA46 Status:# Unload attempt prevented"); ums->lun.sense_data = SS_MEDIUM_REMOVAL_PREVENTED; - return -22; + return UMS_RES_INVALID_ARG; } if (!loej) - return 0; + return UMS_RES_OK; // Unmount means we exit UMS because of ejection. ums->lun.unmounted = 1; - return 0; + return UMS_RES_OK; } static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums) @@ -1067,7 +1074,7 @@ static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums) { ums->lun.sense_data = SS_INVALID_COMMAND; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } prevent = ums->cmnd[4] & 0x01; @@ -1075,7 +1082,7 @@ static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums) { ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } // Notify for possible unmounting? @@ -1085,7 +1092,7 @@ static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums) ums->lun.prevent_medium_removal = prevent; - return 0; + return UMS_RES_OK; } static int _scsi_read_format_capacities(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) @@ -1105,7 +1112,7 @@ static int _scsi_read_format_capacities(usbd_gadget_ums_t *ums, bulk_ctxt_t *bul // Check whether the command is properly formed and whether its data size // and direction agree with the values we already have. -static int _ums_check_scsi_cmd(usbd_gadget_ums_t *ums, int cmnd_size, +static int _ums_check_scsi_cmd(usbd_gadget_ums_t *ums, u32 cmnd_size, enum data_direction data_dir, u32 mask, int needs_medium) { //const char dirletter[4] = {'u', 'o', 'i', 'n'}; @@ -1132,7 +1139,7 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n", { ums->phase_error = 1; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } // Cmd length verification. @@ -1146,7 +1153,7 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n", { ums->phase_error = 1; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } } @@ -1167,7 +1174,7 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n", ums->lun.sense_data = ums->lun.unit_attention_data; ums->lun.unit_attention_data = SS_NO_SENSE; - return -22; + return UMS_RES_INVALID_ARG; } // Check that only command bytes listed in the mask are set. @@ -1178,7 +1185,7 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n", { ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } } @@ -1187,16 +1194,16 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n", { ums->lun.sense_data = SS_MEDIUM_NOT_PRESENT; - return -22; + return UMS_RES_INVALID_ARG; } - return 0; + return UMS_RES_OK; } static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { u32 len; - int reply = -22; // Invalid argument. + int reply = UMS_RES_INVALID_ARG; ums->phase_error = 0; ums->short_packet_received = 0; @@ -1227,7 +1234,7 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { // We don't support MODE SELECT. ums->lun.sense_data = SS_INVALID_COMMAND; - reply = -22; + reply = UMS_RES_INVALID_ARG; } break; @@ -1238,7 +1245,7 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { // We don't support MODE SELECT. ums->lun.sense_data = SS_INVALID_COMMAND; - reply = -22; + reply = UMS_RES_INVALID_ARG; } break; @@ -1367,12 +1374,12 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) if (reply == 0) { ums->lun.sense_data = SS_INVALID_COMMAND; - reply = -22; // Invalid argument. + reply = UMS_RES_INVALID_ARG; } break; } - if (reply == -22) // Invalid argument. + if (reply == UMS_RES_INVALID_ARG) reply = 0; // Error reply length. // Set up reply buffer for finish_reply(). Otherwise it's already set. @@ -1384,7 +1391,7 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) ums->residue -= reply; } - return 0; + return UMS_RES_OK; } static int pad_with_zeros(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) @@ -1398,12 +1405,12 @@ static int pad_with_zeros(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) u32 nsend = MIN(ums->usb_amount_left, USB_EP_BUFFER_MAX_SIZE); memset(bulk_ctxt->bulk_in_buf + current_len_to_keep, 0, nsend - current_len_to_keep); bulk_ctxt->bulk_in_length = nsend; - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_DATA); ums->usb_amount_left -= nsend; current_len_to_keep = 0; } - return 0; + return UMS_RES_OK; } static int throw_away_data(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) @@ -1416,10 +1423,10 @@ static int throw_away_data(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) u32 amount = MIN(ums->usb_amount_left, USB_EP_BUFFER_MAX_SIZE); bulk_ctxt->bulk_out_length = amount; - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_DATA); ums->usb_amount_left -= amount; - return 0; + return UMS_RES_OK; } // Throw away the data in a filled buffer. @@ -1431,15 +1438,15 @@ static int throw_away_data(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) bulk_ctxt->bulk_out_status != USB_RES_OK) { raise_exception(ums, UMS_STATE_ABORT_BULK_OUT); - return -4; // Interrupted system call + return UMS_RES_PROT_FATAL; } } - return 0; + return UMS_RES_OK; } static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { - int rc = 0; + int rc = UMS_RES_OK; switch (ums->data_dir) { case DATA_DIR_NONE: @@ -1463,7 +1470,7 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) // If there's no residue, simply send the last buffer. if (!ums->residue) { - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_DATA); /* For Bulk-only, if we're allowed to stall then send the * short packet and halt the bulk-in endpoint. If we can't @@ -1471,7 +1478,7 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) } else if (ums->can_stall) { - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_DATA); rc = ums_set_stall(bulk_ctxt->bulk_in); ums->set_text(ums->label, "#FFDD00 Error:# Residue. Stalled EP IN!"); } @@ -1491,7 +1498,7 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) if (ums->short_packet_received) // Did the host stop sending unexpectedly early? { raise_exception(ums, UMS_STATE_ABORT_BULK_OUT); - rc = -4; // Interrupted system call + rc = UMS_RES_PROT_FATAL; } else // We can't stall. Read in the excess data and throw it away. rc = throw_away_data(ums, bulk_ctxt); @@ -1574,7 +1581,7 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) } if (bulk_ctxt->bulk_out_status || bulk_ctxt->bulk_out_ignore) - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } /* Is the CBW valid? */ @@ -1594,12 +1601,12 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) // until the next reset. ums_wedge_bulk_in_endpoint(ums); bulk_ctxt->bulk_out_ignore = 1; - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } /* Is the CBW meaningful? */ if (cbw->Lun >= UMS_MAX_LUN || cbw->Flags & ~USB_BULK_IN_FLAG || - cbw->Length <= 0 || cbw->Length > SCSI_MAX_CMD_SZ) + cbw->Length == 0 || cbw->Length > SCSI_MAX_CMD_SZ) { gfx_printf("USB: non-meaningful CBW: lun = %X, flags = 0x%X, cmdlen %X\n", cbw->Lun, cbw->Flags, cbw->Length); @@ -1613,7 +1620,7 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) ums->set_text(ums->label, "#FFDD00 Error:# CBW unknown - Stalled both EP!"); } - return -22; // Invalid argument. + return UMS_RES_INVALID_ARG; } /* Save the command for later */ @@ -1636,12 +1643,12 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) if (!ums->lun.unmounted) ums->timeouts = 0; - return 0; + return UMS_RES_OK; } static int get_next_command(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { - int rc = 0; + int rc = UMS_RES_OK; /* Wait for the next buffer to become available */ // while (bulk_ctxt->bulk_out_buf_state != BUF_STATE_EMPTY) @@ -1652,7 +1659,7 @@ static int get_next_command(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) bulk_ctxt->bulk_out_length = USB_BULK_CB_WRAP_LEN; /* Queue a request to read a Bulk-only CBW */ - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_CMD); /* We will drain the buffer in software, which means we * can reuse it for the next filling. No need to advance @@ -1698,7 +1705,7 @@ static void send_status(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) csw->Status = status; bulk_ctxt->bulk_in_length = USB_BULK_CS_WRAP_LEN; - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_CMD); } static void handle_exception(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) @@ -1765,16 +1772,16 @@ static inline void _system_maintainance(usbd_gadget_ums_t *ums) u32 time = get_tmr_ms(); - if (timer_dram < time) - { - minerva_periodic_training(); - timer_dram = get_tmr_ms() + 100; - } - else if (timer_status_bar < time) + if (timer_status_bar < time) { ums->system_maintenance(true); timer_status_bar = get_tmr_ms() + 30000; } + else if (timer_dram < time) + { + minerva_periodic_training(); + timer_dram = get_tmr_ms() + EMC_PERIODIC_TRAIN_MS; + } } int usb_device_gadget_ums(usb_ctxt_t *usbs) @@ -1828,6 +1835,7 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs) // Initialize sdmmc. if (usbs->type == MMC_SD) { + sd_end(); sd_mount(); sd_unmount(); ums.lun.sdmmc = &sd_sdmmc; @@ -1898,7 +1906,10 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs) send_status(&ums, &ums.bulk_ctxt); } while (ums.state != UMS_STATE_TERMINATED); - ums.set_text(ums.label, "#C7EA46 Status:# Disk ejected"); + if (ums.lun.prevent_medium_removal) + ums.set_text(ums.label, "#FFDD00 Error:# Disk unsafely ejected"); + else + ums.set_text(ums.label, "#C7EA46 Status:# Disk ejected"); goto exit; error: diff --git a/bdk/usb/usb_t210.h b/bdk/usb/usb_t210.h index 4d67c69..e677a5f 100644 --- a/bdk/usb/usb_t210.h +++ b/bdk/usb/usb_t210.h @@ -198,6 +198,7 @@ typedef struct _t210_usb2d_t #define XUSB_DEV_XHCI_ST 0x34 #define XHCI_ST_RC BIT(0) #define XHCI_ST_IP BIT(4) +#define XUSB_DEV_XHCI_RT_IMOD 0x38 #define XUSB_DEV_XHCI_PORTSC 0x3C #define XHCI_PORTSC_PR BIT(4) #define XHCI_PORTSC_PLS_MASK (0xF << 5) diff --git a/bdk/usb/usbd.c b/bdk/usb/usbd.c index 8cf37c3..95d1ed5 100644 --- a/bdk/usb/usbd.c +++ b/bdk/usb/usbd.c @@ -724,7 +724,7 @@ static usb_ep_status_t _usbd_get_ep_status(usb_ep_t endpoint) return USB_EP_STATUS_IDLE; } -static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, bool sync) +static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, u32 sync_timeout) { if (!buf) len = 0; @@ -797,12 +797,12 @@ static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, bool sync) int res = USB_RES_OK; usb_ep_status_t ep_status; - if (sync) + if (sync_timeout) { ep_status = _usbd_get_ep_status(endpoint); if (ep_status == USB_EP_STATUS_ACTIVE) { - u32 retries = 1000000; // Timeout 2s. + u32 retries = sync_timeout; while (retries) { ep_status = _usbd_get_ep_status(endpoint); @@ -834,7 +834,7 @@ out: static int _usbd_ep_ack(usb_ep_t ep) { - return _usbd_ep_operation(ep, NULL, 0, true); + return _usbd_ep_operation(ep, NULL, 0, USB_XFER_SYNCED_ENUM); } static void _usbd_set_ep0_stall() @@ -1275,7 +1275,7 @@ static int _usbd_handle_ep0_control_transfer() if (_wLength < size) size = _wLength; - res = _usbd_ep_operation(USB_EP_CTRL_IN, usb_ep0_ctrl_buf, size, true); + res = _usbd_ep_operation(USB_EP_CTRL_IN, usb_ep0_ctrl_buf, size, USB_XFER_SYNCED_ENUM); if (!res) res = _usbd_ep_ack(USB_EP_CTRL_OUT); } @@ -1402,7 +1402,7 @@ static usb_ep_status_t _usbd_get_ep1_status(usb_dir_t dir) return _usbd_get_ep_status(ep); } -int usb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, bool sync) +int usb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, u32 sync_timeout) { if ((u32)buf % USB_EP_BUFFER_ALIGN) return USB2_ERROR_XFER_NOT_ALIGNED; @@ -1410,9 +1410,9 @@ int usb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, bool sync) if (len > USB_EP_BUFFER_MAX_SIZE) len = USB_EP_BUFFER_MAX_SIZE; - int res = _usbd_ep_operation(USB_EP_BULK_OUT, buf, len, sync); + int res = _usbd_ep_operation(USB_EP_BULK_OUT, buf, len, sync_timeout); - if (sync && bytes_read) + if (sync_timeout && bytes_read) *bytes_read = res ? 0 : len; return res; @@ -1435,7 +1435,7 @@ int usb_device_ep1_out_read_big(u8 *buf, u32 len, u32 *bytes_read) { u32 len_ep = MIN(len, USB_EP_BUFFER_MAX_SIZE); - res = usb_device_ep1_out_read(buf_curr, len_ep, &bytes, USB_XFER_SYNCED); + res = usb_device_ep1_out_read(buf_curr, len_ep, &bytes, USB_XFER_SYNCED_DATA); if (res) return res; @@ -1455,7 +1455,7 @@ static int _usbd_get_ep1_out_bytes_read() return (usbdaemon->ep_bytes_requested[USB_EP_BULK_OUT] - (usbdaemon->qhs[USB_EP_BULK_OUT].token >> 16)); } -int usb_device_ep1_out_reading_finish(u32 *pending_bytes, int tries) +int usb_device_ep1_out_reading_finish(u32 *pending_bytes) { usb_ep_status_t ep_status; do @@ -1480,7 +1480,7 @@ int usb_device_ep1_out_reading_finish(u32 *pending_bytes, int tries) return USB_ERROR_XFER_ERROR; } -int usb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, bool sync) +int usb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, u32 sync_timeout) { if ((u32)buf % USB_EP_BUFFER_ALIGN) return USB2_ERROR_XFER_NOT_ALIGNED; @@ -1488,9 +1488,9 @@ int usb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, bool sync) if (len > USB_EP_BUFFER_MAX_SIZE) len = USB_EP_BUFFER_MAX_SIZE; - int res = _usbd_ep_operation(USB_EP_BULK_IN, buf, len, sync); + int res = _usbd_ep_operation(USB_EP_BULK_IN, buf, len, sync_timeout); - if (sync && bytes_written) + if (sync_timeout && bytes_written) *bytes_written = res ? 0 : len; return res; diff --git a/bdk/usb/usbd.h b/bdk/usb/usbd.h index 6ba2a5a..a0e4a63 100644 --- a/bdk/usb/usbd.h +++ b/bdk/usb/usbd.h @@ -30,8 +30,12 @@ #define USB_EP_BUFFER_MAX_SIZE (USB_EP_BUFFER_4_TD) #define USB_EP_BUFFER_ALIGN (USB_TD_BUFFER_PAGE_SIZE) -#define USB_XFER_START false -#define USB_XFER_SYNCED true +#define USB_XFER_START 0 +#define USB_XFER_SYNCED_ENUM 1000000 +#define USB_XFER_SYNCED_CMD 1000000 +#define USB_XFER_SYNCED_DATA 2000000 +#define USB_XFER_SYNCED_CLASS 5000000 +#define USB_XFER_SYNCED -1 typedef enum _usb_hid_type { @@ -169,10 +173,10 @@ typedef struct _usb_ops_t int (*usb_device_class_send_max_lun)(u8); int (*usb_device_class_send_hid_report)(); - int (*usb_device_ep1_out_read)(u8 *, u32, u32 *, bool); + int (*usb_device_ep1_out_read)(u8 *, u32, u32 *, u32); int (*usb_device_ep1_out_read_big)(u8 *, u32, u32 *); - int (*usb_device_ep1_out_reading_finish)(u32 *, int); - int (*usb_device_ep1_in_write)(u8 *, u32, u32 *, bool); + int (*usb_device_ep1_out_reading_finish)(u32 *); + int (*usb_device_ep1_in_write)(u8 *, u32, u32 *, u32); int (*usb_device_ep1_in_writing_finish)(u32 *); bool (*usb_device_get_suspended)(); bool (*usb_device_get_port_in_sleep)(); diff --git a/bdk/usb/xusbd.c b/bdk/usb/xusbd.c index e33ca44..4beefcd 100644 --- a/bdk/usb/xusbd.c +++ b/bdk/usb/xusbd.c @@ -881,7 +881,7 @@ int xusb_device_init() _xusbd_init_device_clocks(); // Enable AHB redirect for access to IRAM for Event/EP ring buffers. - mc_enable_ahb_redirect(); // can be skipped if IRAM is not used///////////////// + mc_enable_ahb_redirect(); // Can be skipped if IRAM is not used. // Enable XUSB device IPFS. XUSB_DEV_DEV(XUSB_DEV_CONFIGURATION) |= DEV_CONFIGURATION_EN_FPCI; @@ -895,14 +895,11 @@ int xusb_device_init() XUSB_DEV_DEV(XUSB_DEV_INTR_MASK) |= DEV_INTR_MASK_IP_INT_MASK; // AHB USB performance cfg. - //TODO: Doesn't help.. -/* AHB_GIZMO(AHB_GIZMO_AHB_MEM) |= AHB_MEM_DONT_SPLIT_AHB_WR | AHB_MEM_ENB_FAST_REARBITRATE; AHB_GIZMO(AHB_GIZMO_USB3) |= AHB_GIZMO_IMMEDIATE; AHB_GIZMO(AHB_ARBITRATION_PRIORITY_CTRL) = PRIORITY_CTRL_WEIGHT(7) | PRIORITY_SELECT_USB3; AHB_GIZMO(AHB_AHB_MEM_PREFETCH_CFG1) = MEM_PREFETCH_ENABLE | MEM_PREFETCH_USB3_MST_ID | MEM_PREFETCH_ADDR_BNDRY(12) | 0x1000; // Addr boundary 64KB, Inactivity 4096 cycles. -*/ // Initialize context. usbd_xotg = &usbd_xotg_controller_ctxt; @@ -1771,6 +1768,13 @@ int xusb_device_enumerate(usb_gadget_type gadget) usbd_xotg->gadget = gadget; + /* + * Set interrupt moderation to 0us. + * This is important because default value creates a 4.62ms latency. + * Effectively hurting transfers by having 15% to 96% performance loss. + */ + XUSB_DEV_XHCI(XUSB_DEV_XHCI_RT_IMOD) = 0; + // Disable Wake events. XUSB_PADCTL(XUSB_PADCTL_ELPG_PROGRAM_0) = 0; XUSB_PADCTL(XUSB_PADCTL_ELPG_PROGRAM_1) = 0; @@ -1803,7 +1807,7 @@ int xusb_device_enumerate(usb_gadget_type gadget) u32 timer = get_tmr_ms() + 90000; while (true) { - int res = _xusb_ep_operation(1000000); // 2s timeout. + int res = _xusb_ep_operation(USB_XFER_SYNCED_ENUM); // 2s timeout. if (res && res != USB_ERROR_TIMEOUT) return res; @@ -1826,7 +1830,7 @@ void xusb_end(bool reset_ep, bool only_controller) CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB_PADCTL); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = BIT(CLK_W_XUSB); CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB); - mc_disable_ahb_redirect();/////////////////// + mc_disable_ahb_redirect(); // Can be skipped if IRAM is not used. } int xusb_handle_ep0_ctrl_setup() @@ -1844,7 +1848,7 @@ int xusb_handle_ep0_ctrl_setup() return USB_RES_OK; } -int xusb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, bool sync) +int xusb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, u32 sync_tries) { if (len > USB_EP_BUFFER_MAX_SIZE) len = USB_EP_BUFFER_MAX_SIZE; @@ -1855,10 +1859,10 @@ int xusb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, bool sync) _xusb_issue_normal_trb(buf, len, USB_DIR_OUT); usbd_xotg->tx_count[USB_DIR_OUT]++; - if (sync) + if (sync_tries) { while (!res && usbd_xotg->tx_count[USB_DIR_OUT]) - res = _xusb_ep_operation(1000000); // 2s timeout. + res = _xusb_ep_operation(sync_tries); if (bytes_read) *bytes_read = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_OUT]; @@ -1882,7 +1886,7 @@ int xusb_device_ep1_out_read_big(u8 *buf, u32 len, u32 *bytes_read) { u32 len_ep = MIN(len, USB_EP_BUFFER_MAX_SIZE); - int res = xusb_device_ep1_out_read(buf_curr, len_ep, &bytes, USB_XFER_SYNCED); + int res = xusb_device_ep1_out_read(buf_curr, len_ep, &bytes, USB_XFER_SYNCED_DATA); if (res) return res; @@ -1894,11 +1898,11 @@ int xusb_device_ep1_out_read_big(u8 *buf, u32 len, u32 *bytes_read) return USB_RES_OK; } -int xusb_device_ep1_out_reading_finish(u32 *pending_bytes, int tries) +int xusb_device_ep1_out_reading_finish(u32 *pending_bytes) { int res = USB_RES_OK; while (!res && usbd_xotg->tx_count[USB_DIR_OUT]) - res = _xusb_ep_operation(tries); + res = _xusb_ep_operation(USB_XFER_SYNCED); // Infinite retries. if (pending_bytes) *pending_bytes = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_OUT]; @@ -1908,7 +1912,7 @@ int xusb_device_ep1_out_reading_finish(u32 *pending_bytes, int tries) return res; } -int xusb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, bool sync) +int xusb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, u32 sync_tries) { if (len > USB_EP_BUFFER_MAX_SIZE) len = USB_EP_BUFFER_MAX_SIZE; @@ -1921,10 +1925,10 @@ int xusb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, bool sync) _xusb_issue_normal_trb(buf, len, USB_DIR_IN); usbd_xotg->tx_count[USB_DIR_IN]++; - if (sync) + if (sync_tries) { while (!res && usbd_xotg->tx_count[USB_DIR_IN]) - res = _xusb_ep_operation(1000000); // 2s timeout. + res = _xusb_ep_operation(sync_tries); if (bytes_written) *bytes_written = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_IN]; @@ -1947,7 +1951,7 @@ int xusb_device_ep1_in_writing_finish(u32 *pending_bytes) { int res = USB_RES_OK; while (!res && usbd_xotg->tx_count[USB_DIR_IN]) - res = _xusb_ep_operation(1000000); // 2s timeout. + res = _xusb_ep_operation(USB_XFER_SYNCED); // Infinite retries. if (pending_bytes) *pending_bytes = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_IN]; @@ -1973,7 +1977,7 @@ bool xusb_device_class_send_max_lun(u8 max_lun) // Wait for request and transfer start. while (usbd_xotg->device_state != XUSB_LUN_CONFIGURED) { - _xusb_ep_operation(500000); + _xusb_ep_operation(USB_XFER_SYNCED_CLASS); if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN)) return true; } @@ -1991,7 +1995,7 @@ bool xusb_device_class_send_hid_report() // Wait for request and transfer start. while (usbd_xotg->device_state != XUSB_HID_CONFIGURED) { - _xusb_ep_operation(500000); + _xusb_ep_operation(USB_XFER_SYNCED_CLASS); if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN)) return true; } diff --git a/bdk/utils/btn.c b/bdk/utils/btn.c index 9ffe275..cc36573 100644 --- a/bdk/utils/btn.c +++ b/bdk/utils/btn.c @@ -29,7 +29,7 @@ u8 btn_read() res |= BTN_VOL_DOWN; if (!gpio_read(GPIO_PORT_X, GPIO_PIN_6)) res |= BTN_VOL_UP; - if (i2c_recv_byte(4, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFSTAT) & 0x4) + if (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFSTAT) & MAX77620_ONOFFSTAT_EN0) res |= BTN_POWER; return res; } diff --git a/bdk/utils/dirlist.c b/bdk/utils/dirlist.c index 5732683..3b09d1d 100644 --- a/bdk/utils/dirlist.c +++ b/bdk/utils/dirlist.c @@ -21,16 +21,16 @@ #include #include +#define MAX_ENTRIES 64 + char *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs) { - u8 max_entries = 61; - int res = 0; u32 i = 0, j = 0, k = 0; DIR dir; FILINFO fno; - char *dir_entries = (char *)calloc(max_entries, 256); + char *dir_entries = (char *)calloc(MAX_ENTRIES, 256); char *temp = (char *)calloc(1, 256); if (!pattern && !f_opendir(&dir, directory)) @@ -49,7 +49,7 @@ char *dirlist(const char *directory, const char *pattern, bool includeHiddenFile { strcpy(dir_entries + (k * 256), fno.fname); k++; - if (k > (max_entries - 1)) + if (k > (MAX_ENTRIES - 1)) break; } } @@ -64,7 +64,7 @@ char *dirlist(const char *directory, const char *pattern, bool includeHiddenFile { strcpy(dir_entries + (k * 256), fno.fname); k++; - if (k > (max_entries - 1)) + if (k > (MAX_ENTRIES - 1)) break; } res = f_findnext(&dir, &fno); diff --git a/bdk/utils/ini.c b/bdk/utils/ini.c index 538435e..5088f51 100644 --- a/bdk/utils/ini.c +++ b/bdk/utils/ini.c @@ -66,14 +66,14 @@ ini_sec_t *_ini_create_section(link_t *dst, ini_sec_t *csec, char *name, u8 type int ini_parse(link_t *dst, char *ini_path, bool is_dir) { + FIL fp; u32 lblen; u32 pathlen = strlen(ini_path); u32 k = 0; - char lbuf[512]; - char *filelist = NULL; - FIL fp; ini_sec_t *csec = NULL; + char *lbuf = NULL; + char *filelist = NULL; char *filename = (char *)malloc(256); strcpy(filename, ini_path); @@ -114,6 +114,8 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir) return 0; } + lbuf = malloc(512); + do { // Fetch one line. @@ -168,6 +170,7 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir) } } while (is_dir); + free(lbuf); free(filename); free(filelist); diff --git a/bdk/utils/sprintf.c b/bdk/utils/sprintf.c index c27043c..8fa2dec 100644 --- a/bdk/utils/sprintf.c +++ b/bdk/utils/sprintf.c @@ -56,7 +56,7 @@ static u32 _putn(char *buffer, u32 v, int base, char fill, int fcnt) { return _puts(buffer, p); } -u32 sprintf(char *buffer, const char *fmt, ...) { +u32 s_printf(char *buffer, const char *fmt, ...) { va_list ap; int fill, fcnt; u32 count = 0; diff --git a/bdk/utils/sprintf.h b/bdk/utils/sprintf.h index 6094044..35a8218 100644 --- a/bdk/utils/sprintf.h +++ b/bdk/utils/sprintf.h @@ -19,6 +19,6 @@ #include "types.h" -u32 sprintf(char *buffer, const char *fmt, ...); +u32 s_printf(char *buffer, const char *fmt, ...); #endif diff --git a/bdk/utils/types.h b/bdk/utils/types.h index 0300425..9e8e716 100644 --- a/bdk/utils/types.h +++ b/bdk/utils/types.h @@ -22,7 +22,7 @@ #define ALWAYS_INLINE inline __attribute__((always_inline)) #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) -#define ALIGN_DOWN(x, a) (((x) - ((a) - 1)) & ~((a) - 1)) +#define ALIGN_DOWN(x, a) ((x) & ~((a) - 1)) #define BIT(n) (1U << (n)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b)) @@ -74,6 +74,9 @@ typedef int bool; #define true 1 #define false 0 +#define DISABLE 0 +#define ENABLE 1 + #define BOOT_CFG_AUTOBOOT_EN BIT(0) #define BOOT_CFG_FROM_LAUNCH BIT(1) #define BOOT_CFG_FROM_ID BIT(2) diff --git a/bdk/utils/util.c b/bdk/utils/util.c index e5cd868..f267236 100644 --- a/bdk/utils/util.c +++ b/bdk/utils/util.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert -* Copyright (c) 2018 CTCaer +* Copyright (c) 2018-2020 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -44,7 +44,7 @@ u32 get_tmr_ms() u32 get_tmr_us() { - return TMR(TIMERUS_CNTR_1US); //TIMERUS_CNTR_1US + return TMR(TIMERUS_CNTR_1US); } void msleep(u32 ms) @@ -132,53 +132,58 @@ void panic(u32 val) usleep(1); } -void reboot_normal() +void power_set_state(power_state_t state) { + u8 reg; + + // Unmount and power down sd card. sd_end(); - hw_reinit_workaround(false, 0); - panic(0x21); // Bypass fuse programming in package1. -} - -void reboot_rcm() -{ - sd_end(); - hw_reinit_workaround(false, 0); - - PMC(APBDEV_PMC_SCRATCH0) = PMC_SCRATCH0_MODE_RCM; - PMC(APBDEV_PMC_CNTRL) |= PMC_CNTRL_MAIN_RST; - - while (true) - bpmp_halt(); -} - -void reboot_full() -{ - sd_end(); - hw_reinit_workaround(false, 0); - - // Enable soft reset wake event. - u8 reg = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2); - reg |= MAX77620_ONOFFCNFG2_SFT_RST_WK; - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2, reg); - - // Do a soft reset. - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_SFT_RST); - - while (true) - bpmp_halt(); -} - -void power_off() -{ - sd_end(); + // De-initialize and power down various hardware. hw_reinit_workaround(false, 0); // Stop the alarm, in case we injected and powered off too fast. max77620_rtc_stop_alarm(); - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF); + // Set power state. + switch (state) + { + case REBOOT_RCM: + PMC(APBDEV_PMC_SCRATCH0) = PMC_SCRATCH0_MODE_RCM; // Enable RCM path. + PMC(APBDEV_PMC_CNTRL) |= PMC_CNTRL_MAIN_RST; // PMC reset. + break; + + case REBOOT_BYPASS_FUSES: + panic(0x21); // Bypass fuse programming in package1. + break; + + case POWER_OFF: + // Initiate power down sequence and do not generate a reset (regulators retain state). + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF); + break; + + case POWER_OFF_RESET: + case POWER_OFF_REBOOT: + default: + // Enable/Disable soft reset wake event. + reg = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2); + if (state == POWER_OFF_RESET) // Do not wake up after power off. + reg &= ~(MAX77620_ONOFFCNFG2_SFT_RST_WK | MAX77620_ONOFFCNFG2_WK_ALARM1 | MAX77620_ONOFFCNFG2_WK_ALARM2); + else // POWER_OFF_REBOOT. Wake up after power off. + reg |= MAX77620_ONOFFCNFG2_SFT_RST_WK; + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2, reg); + + // Initiate power down sequence and generate a reset (regulators' state resets). + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_SFT_RST); + break; + } while (true) bpmp_halt(); } + +void power_set_state_ex(void *param) +{ + power_state_t *state = (power_state_t *)param; + power_set_state(*state); +} diff --git a/bdk/utils/util.h b/bdk/utils/util.h index 20df76f..3503e1e 100644 --- a/bdk/utils/util.h +++ b/bdk/utils/util.h @@ -21,6 +21,16 @@ #include #include +typedef enum +{ + REBOOT_RCM, // PMC reset. Enter RCM mode. + REBOOT_BYPASS_FUSES, // PMC reset via watchdog. Enter Normal mode. Bypass fuse programming in package1. + + POWER_OFF, // Power off PMIC. Do not reset regulators. + POWER_OFF_RESET, // Power off PMIC. Reset regulators. + POWER_OFF_REBOOT, // Power off PMIC. Reset regulators. Power on. +} power_state_t; + typedef enum { NYX_CFG_BIS = BIT(5), @@ -41,6 +51,8 @@ typedef enum #define byte_swap_32(num) ((((num) >> 24) & 0xff) | (((num) << 8) & 0xff0000) | \ (((num) >> 8 )& 0xff00) | (((num) << 24) & 0xff000000)) +#define byte_swap_16(num) ((((num) >> 8) & 0xff) | (((num) << 8) & 0xff00)) + typedef struct _cfg_op_t { u32 off; @@ -49,6 +61,10 @@ typedef struct _cfg_op_t typedef struct _nyx_info_t { + u32 magic; + u32 sd_init; + u32 sd_errors[3]; + u8 rsvd[0x1000]; u32 disp_id; u32 errors; } nyx_info_t; @@ -65,17 +81,18 @@ typedef struct _nyx_storage_t emc_table_t mtc_table[10]; } nyx_storage_t; +void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops); +u32 crc32_calc(u32 crc, const u8 *buf, u32 len); + u32 get_tmr_us(); u32 get_tmr_ms(); u32 get_tmr_s(); void usleep(u32 us); void msleep(u32 ms); + void panic(u32 val); -void reboot_normal(); -void reboot_rcm(); -void reboot_full(); -void power_off(); -void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops); -u32 crc32_calc(u32 crc, const u8 *buf, u32 len); +void power_set_state(power_state_t state); +void power_set_state_ex(void *param); + #endif diff --git a/source/config.c b/source/config.c index 254095e..55bd64e 100644 --- a/source/config.c +++ b/source/config.c @@ -49,6 +49,7 @@ void set_default_configuration() h_cfg.sept_run = EMC(EMC_SCRATCH0) & EMC_SEPT_RUN; h_cfg.aes_slots_new = false; h_cfg.rcm_patched = fuse_check_patched_rcm(); + h_cfg.sbk_set = FUSE(FUSE_PRIVATE_KEY0) == 0xFFFFFFFF; h_cfg.emummc_force_disable = false; h_cfg.t210b01 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01; diff --git a/source/config.h b/source/config.h index 894cdf9..9a69d19 100644 --- a/source/config.h +++ b/source/config.h @@ -38,6 +38,7 @@ typedef struct _hekate_config bool aes_slots_new; bool emummc_force_disable; bool rcm_patched; + bool sbk_set; u32 errors; hos_eks_mbr_t *eks; } hekate_config; diff --git a/source/gfx/gfx.c b/source/gfx/gfx.c index 70a7292..db57ec1 100644 --- a/source/gfx/gfx.c +++ b/source/gfx/gfx.c @@ -1,7 +1,7 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2020 CTCaer - * Copyright (c) 2019-2020 shchmue + * Copyright (c) 2018-2021 CTCaer + * Copyright (c) 2019-2021 shchmue * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -24,6 +24,8 @@ gfx_ctxt_t gfx_ctxt; gfx_con_t gfx_con; +static bool gfx_con_init_done = false; + static const u8 _gfx_font[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Char 032 ( ) 0x00, 0x30, 0x30, 0x18, 0x18, 0x00, 0x0C, 0x00, // Char 033 (!) @@ -158,6 +160,8 @@ void gfx_con_init() gfx_con.fillbg = 1; gfx_con.bgcol = 0xFF1B1B1B; gfx_con.mute = 0; + + gfx_con_init_done = true; } void gfx_con_setcol(u32 fgcol, int fillbg, u32 bgcol) @@ -274,7 +278,7 @@ void gfx_putc(char c) void gfx_puts(const char *s) { - if (!s || gfx_con.mute) + if (!s || !gfx_con_init_done || gfx_con.mute) return; for (; *s; s++) @@ -330,7 +334,7 @@ void gfx_put_big_sep() void gfx_printf(const char *fmt, ...) { - if (gfx_con.mute) + if (!gfx_con_init_done || gfx_con.mute) return; va_list ap; @@ -404,11 +408,13 @@ void gfx_printf(const char *fmt, ...) va_end(ap); } -void gfx_hexdump(u32 base, const u8 *buf, u32 len) +void gfx_hexdump(u32 base, const void *buf, u32 len) { - if (gfx_con.mute) + if (!gfx_con_init_done || gfx_con.mute) return; + u8 *buff = (u8 *)buf; + u8 prevFontSize = gfx_con.fntsz; gfx_con.fntsz = 8; for(u32 i = 0; i < len; i++) @@ -420,7 +426,7 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len) gfx_puts("| "); for(u32 j = 0; j < 0x10; j++) { - u8 c = buf[i - 0x10 + j]; + u8 c = buff[i - 0x10 + j]; if(c >= 32 && c <= 126) gfx_putc(c); else @@ -430,7 +436,7 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len) } gfx_printf("%08x: ", base + i); } - gfx_printf("%02x ", buf[i]); + gfx_printf("%02x ", buff[i]); if (i == len - 1) { int ln = len % 0x10 != 0; @@ -444,7 +450,7 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len) gfx_puts("| "); for(u32 j = 0; j < (ln ? k : k + 1); j++) { - u8 c = buf[i - k + j]; + u8 c = buff[i - k + j]; if(c >= 32 && c <= 126) gfx_putc(c); else @@ -457,12 +463,15 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len) gfx_con.fntsz = prevFontSize; } -void gfx_hexdiff(u32 base, const u8 *buf1, const u8 *buf2, u32 len) +void gfx_hexdiff(u32 base, const void *buf1, const void *buf2, u32 len) { - if (gfx_con.mute) + if (!gfx_con_init_done || gfx_con.mute) return; - if (memcmp(buf1, buf2, len) == 0) + u8 *buff1 = (u8 *)buf1; + u8 *buff2 = (u8 *)buf2; + + if (memcmp(buff1, buff2, len) == 0) { gfx_printf("Diff: No differences found.\n"); return; @@ -473,14 +482,14 @@ void gfx_hexdiff(u32 base, const u8 *buf1, const u8 *buf2, u32 len) for(u32 i = 0; i < len; i+=0x10) { u32 bytes_left = len - i < 0x10 ? len - i : 0x10; - if (memcmp(buf1 + i, buf2 + i, bytes_left) == 0) + if (memcmp(buff1 + i, buff2 + i, bytes_left) == 0) continue; gfx_printf("Diff 1: %08x: ", base + i); for (u32 j = 0; j < bytes_left; j++) { - if (buf1[i+j] != buf2[i+j]) + if (buff1[i+j] != buff2[i+j]) gfx_con.fgcol = COLOR_ORANGE; - gfx_printf("%02x ", buf1[i+j]); + gfx_printf("%02x ", buff1[i+j]); gfx_con.fgcol = 0xFFCCCCCC; } gfx_puts("| "); @@ -488,9 +497,9 @@ void gfx_hexdiff(u32 base, const u8 *buf1, const u8 *buf2, u32 len) gfx_printf("Diff 2: %08x: ", base + i); for (u32 j = 0; j < bytes_left; j++) { - if (buf1[i+j] != buf2[i+j]) + if (buff1[i+j] != buff2[i+j]) gfx_con.fgcol = COLOR_ORANGE; - gfx_printf("%02x ", buf2[i+j]); + gfx_printf("%02x ", buff2[i+j]); gfx_con.fgcol = 0xFFCCCCCC; } gfx_puts("| "); diff --git a/source/gfx/gfx.h b/source/gfx/gfx.h index 582cbbb..0f1c27b 100644 --- a/source/gfx/gfx.h +++ b/source/gfx/gfx.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2020 CTCaer + * Copyright (c) 2018-2021 CTCaer + * Copyright (c) 2019-2021 shchmue * Copyright (c) 2018 M4xw * * This program is free software; you can redistribute it and/or modify it @@ -63,8 +64,8 @@ void gfx_con_setpos(u32 x, u32 y); void gfx_putc(char c); void gfx_puts(const char *s); void gfx_printf(const char *fmt, ...); -void gfx_hexdump(u32 base, const u8 *buf, u32 len); -void gfx_hexdiff(u32 base, const u8 *buf1, const u8 *buf2, u32 len); +void gfx_hexdump(u32 base, const void *buf, u32 len); +void gfx_hexdiff(u32 base, const void *buf1, const void *buf2, u32 len); void gfx_set_pixel(u32 x, u32 y, u32 color); void gfx_line(int x0, int y0, int x1, int y1, u32 color); diff --git a/source/gfx/tui.c b/source/gfx/tui.c index 79be716..173178a 100644 --- a/source/gfx/tui.c +++ b/source/gfx/tui.c @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -#include +#include #include "tui.h" #include "../config.h" #include @@ -77,7 +77,7 @@ void tui_pbar(int x, int y, u32 val, u32 fgcol, u32 bgcol) x += 7 * gfx_con.fntsz; - for (int i = 0; i < (gfx_con.fntsz >> 3) * 6; i++) + for (u32 i = 0; i < (gfx_con.fntsz >> 3) * 6; i++) { gfx_line(x, y + i + 1, x + 3 * val, y + i + 1, fgcol); gfx_line(x + 3 * val, y + i + 1, x + 3 * 100, y + i + 1, bgcol); diff --git a/source/hos/fss.c b/source/hos/fss.c index 09896f9..1521d82 100644 --- a/source/hos/fss.c +++ b/source/hos/fss.c @@ -139,7 +139,7 @@ int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt) if (mariko_not_supported) { - EPRINTF("Mariko not supported on < 0.17.0!"); + EPRINTF("\nMariko not supported on < 0.17.0!"); goto fail; } diff --git a/source/hos/hos.h b/source/hos/hos.h index b5900c6..2b89bb3 100644 --- a/source/hos/hos.h +++ b/source/hos/hos.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2020 CTCaer + * Copyright (c) 2018-2021 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -20,6 +20,7 @@ #include "pkg1.h" #include "pkg2.h" +#include #include #include #include @@ -50,20 +51,21 @@ typedef struct _exo_ctxt_t bool fs_is_510; bool no_user_exceptions; bool user_pmu; + bool *usb3_force; bool *cal0_blank; bool *cal0_allow_writes_sys; } exo_ctxt_t; typedef struct _hos_eks_keys_t { - u8 mkk[0x10]; - u8 fdk[0x10]; + u8 mkk[SE_KEY_128_SIZE]; + u8 fdk[SE_KEY_128_SIZE]; } hos_eks_keys_t; typedef struct _hos_eks_bis_keys_t { - u8 crypt[0x10]; - u8 tweak[0x10]; + u8 crypt[SE_KEY_128_SIZE]; + u8 tweak[SE_KEY_128_SIZE]; } hos_eks_bis_keys_t; typedef struct _hos_eks_mbr_t @@ -73,8 +75,8 @@ typedef struct _hos_eks_mbr_t u8 enabled_bis; u8 rsvd[2]; u32 lot0; - u8 dkg[0x10]; - u8 dkk[0x10]; + u8 dkg[SE_KEY_128_SIZE]; + u8 dkk[SE_KEY_128_SIZE]; hos_eks_keys_t keys[5]; hos_eks_bis_keys_t bis_keys[3]; } hos_eks_mbr_t; @@ -106,14 +108,16 @@ typedef struct _launch_ctxt_t link_t kip1_list; char* kip1_patches; - u32 fss0_hosver; bool svcperm; bool debugmode; bool stock; - bool atmosphere; - bool fss0_experimental; bool emummc_forced; + char *fss0_main_path; + u32 fss0_hosver; + bool fss0_experimental; + bool atmosphere; + exo_ctxt_t exo_ctx; ini_sec_t *cfg; @@ -129,6 +133,6 @@ void hos_eks_get(); void hos_eks_save(u32 kb); void hos_eks_clear(u32 kb); int hos_launch(ini_sec_t *cfg); -int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt); +int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt); #endif diff --git a/source/hos/pkg1.c b/source/hos/pkg1.c index 9cf549c..4800aff 100644 --- a/source/hos/pkg1.c +++ b/source/hos/pkg1.c @@ -1,7 +1,7 @@ /* * Copyright (c) 2018 naehrwert * Copyright (c) 2018 st4rk - * Copyright (c) 2018-2019 CTCaer + * Copyright (c) 2018-2021 CTCaer * Copyright (c) 2018 balika011 * * This program is free software; you can redistribute it and/or modify it @@ -46,7 +46,7 @@ static const pkg1_id_t _pkg1_ids[] = { const pkg1_id_t *pkg1_identify(u8 *pkg1) { - for (u32 i = 0; _pkg1_ids[i].id; i++) + for (u32 i = 0; i < ARRAY_SIZE(_pkg1_ids); i++) if (!memcmp(pkg1 + 0x10, _pkg1_ids[i].id, 8)) return &_pkg1_ids[i]; return NULL; diff --git a/source/hos/sept.c b/source/hos/sept.c index 94b86f6..873b7ab 100644 --- a/source/hos/sept.c +++ b/source/hos/sept.c @@ -21,7 +21,7 @@ #include "sept.h" #include "../config.h" #include -#include +#include #include #include #include diff --git a/source/keys/keys.c b/source/keys/keys.c index cfd3952..e634f57 100644 --- a/source/keys/keys.c +++ b/source/keys/keys.c @@ -17,7 +17,7 @@ #include "keys.h" #include "../config.h" -#include +#include #include #include "../gfx/tui.h" #include "../hos/pkg1.h" @@ -93,8 +93,8 @@ static ALWAYS_INLINE u32 _get_tsec_fw_size(tsec_key_data_t *key_data) { return key_data->blob0_size + sizeof(tsec_key_data_t) + key_data->blob1_size + key_data->blob2_size + key_data->blob3_size + key_data->blob4_size; } -static u8 *_read_pkg1(sdmmc_t *sdmmc, const pkg1_id_t **pkg1_id) { - if (emummc_storage_init_mmc(&emmc_storage, sdmmc)) { +static u8 *_read_pkg1(const pkg1_id_t **pkg1_id) { + if (emummc_storage_init_mmc()) { EPRINTF("Unable to init MMC."); return NULL; } @@ -102,11 +102,11 @@ static u8 *_read_pkg1(sdmmc_t *sdmmc, const pkg1_id_t **pkg1_id) { // Read package1. u8 *pkg1 = (u8 *)malloc(PKG1_MAX_SIZE); - if (!emummc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0)) { + if (!emummc_storage_set_mmc_partition(EMMC_BOOT0)) { EPRINTF("Unable to set partition."); return NULL; } - if (!emummc_storage_read(&emmc_storage, PKG1_OFFSET / NX_EMMC_BLOCKSIZE, PKG1_MAX_SIZE / NX_EMMC_BLOCKSIZE, pkg1)) { + if (!emummc_storage_read(PKG1_OFFSET / NX_EMMC_BLOCKSIZE, PKG1_MAX_SIZE / NX_EMMC_BLOCKSIZE, pkg1)) { EPRINTF("Unable to read pkg1."); return NULL; } @@ -283,7 +283,7 @@ static void _derive_master_keys_from_keyblobs(key_derivation_ctx_t *keys) { se_aes_key_set(8, keys->tsec_keys, sizeof(keys->tsec_keys) / 2); - if (!emummc_storage_read(&emmc_storage, KEYBLOB_OFFSET / NX_EMMC_BLOCKSIZE, KB_FIRMWARE_VERSION_600 + 1, keyblob_block)) { + if (!emummc_storage_read(KEYBLOB_OFFSET / NX_EMMC_BLOCKSIZE, KB_FIRMWARE_VERSION_600 + 1, keyblob_block)) { EPRINTF("Unable to read keyblobs."); } @@ -577,7 +577,7 @@ static bool _derive_titlekeys(key_derivation_ctx_t *keys, titlekey_buffer_t *tit rsa_keypair_t rsa_keypair = {0}; - if (!emummc_storage_read(&emmc_storage, NX_EMMC_CALIBRATION_OFFSET / NX_EMMC_BLOCKSIZE, NX_EMMC_CALIBRATION_SIZE / NX_EMMC_BLOCKSIZE, titlekey_buffer->read_buffer)) { + if (!emummc_storage_read(NX_EMMC_CALIBRATION_OFFSET / NX_EMMC_BLOCKSIZE, NX_EMMC_CALIBRATION_SIZE / NX_EMMC_BLOCKSIZE, titlekey_buffer->read_buffer)) { EPRINTF("Unable to read PRODINFO."); return false; } @@ -643,7 +643,7 @@ static bool _derive_emmc_keys(key_derivation_ctx_t *keys, titlekey_buffer_t *tit se_aes_key_set(4, keys->bis_key[2] + 0x00, AES_128_KEY_SIZE); se_aes_key_set(5, keys->bis_key[2] + 0x10, AES_128_KEY_SIZE); - if (!emummc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP)) { + if (!emummc_storage_set_mmc_partition(EMMC_GPP)) { EPRINTF("Unable to set partition."); return false; } @@ -690,7 +690,7 @@ static void _save_mariko_partial_keys(char *text_buffer) { for (u32 ks = 12; ks < 16; ks++) { // First, encrypt zeros with complete key se_aes_crypt_block_ecb(ks, 1, &data[3 * AES_128_KEY_SIZE], zeros); - pos += sprintf(&text_buffer[pos], "%d\n", ks); + pos += s_printf(&text_buffer[pos], "%d\n", ks); // We only need to overwrite 3 of the dwords of the key for (u32 i = 0; i < 3; i++) { @@ -701,8 +701,8 @@ static void _save_mariko_partial_keys(char *text_buffer) { } for (u32 i = 0; i < 4; i++) { for (u32 j = 0; j < AES_128_KEY_SIZE; j++) - pos += sprintf(&text_buffer[pos], "%02x", data[i * AES_128_KEY_SIZE + j]); - pos += sprintf(&text_buffer[pos], "\n"); + pos += s_printf(&text_buffer[pos], "%02x", data[i * AES_128_KEY_SIZE + j]); + pos += s_printf(&text_buffer[pos], "\n"); } } free(data); @@ -788,7 +788,7 @@ static void _save_keys_to_sd(key_derivation_ctx_t *keys, titlekey_buffer_t *titl f_mkdir("sd:/switch"); char keyfile_path[30] = "sd:/switch/prod.keys"; if (fuse_read_odm(4) & 3) - sprintf(&keyfile_path[11], "dev.keys"); + s_printf(&keyfile_path[11], "dev.keys"); FILINFO fno; if (!sd_save_to_file(text_buffer, strlen(text_buffer), keyfile_path) && !f_stat(keyfile_path, &fno)) { @@ -811,13 +811,13 @@ static void _save_keys_to_sd(key_derivation_ctx_t *keys, titlekey_buffer_t *titl for (u32 i = 0; i < _titlekey_count; i++) { for (u32 j = 0; j < AES_128_KEY_SIZE; j++) - sprintf(&titlekey_text[i].rights_id[j * 2], "%02x", titlekey_buffer->rights_ids[i][j]); - sprintf(titlekey_text[i].equals, " = "); + s_printf(&titlekey_text[i].rights_id[j * 2], "%02x", titlekey_buffer->rights_ids[i][j]); + s_printf(titlekey_text[i].equals, " = "); for (u32 j = 0; j < AES_128_KEY_SIZE; j++) - sprintf(&titlekey_text[i].titlekey[j * 2], "%02x", titlekey_buffer->titlekeys[i][j]); - sprintf(titlekey_text[i].newline, "\n"); + s_printf(&titlekey_text[i].titlekey[j * 2], "%02x", titlekey_buffer->titlekeys[i][j]); + s_printf(titlekey_text[i].newline, "\n"); } - sprintf(&keyfile_path[11], "title.keys"); + s_printf(&keyfile_path[11], "title.keys"); if (!sd_save_to_file(text_buffer, strlen(text_buffer), keyfile_path) && !f_stat(keyfile_path, &fno)) { gfx_printf("%kWrote %d bytes to %s\n", colors[(color_idx++) % 6], (u32)fno.fsize, keyfile_path); } else @@ -828,10 +828,9 @@ static void _save_keys_to_sd(key_derivation_ctx_t *keys, titlekey_buffer_t *titl static void _derive_keys() { u32 start_whole_operation_time = get_tmr_us(); - sdmmc_t sdmmc; const pkg1_id_t *pkg1_id; - u8 *pkg1 = _read_pkg1(&sdmmc, &pkg1_id); + u8 *pkg1 = _read_pkg1(&pkg1_id); if (!pkg1) { return; } @@ -909,17 +908,17 @@ static void _save_key(const char *name, const void *data, u32 len, char *outbuf) if (!_key_exists(data)) return; u32 pos = strlen(outbuf); - pos += sprintf(&outbuf[pos], "%s = ", name); + pos += s_printf(&outbuf[pos], "%s = ", name); for (u32 i = 0; i < len; i++) - pos += sprintf(&outbuf[pos], "%02x", *(u8*)(data + i)); - sprintf(&outbuf[pos], "\n"); + pos += s_printf(&outbuf[pos], "%02x", *(u8*)(data + i)); + s_printf(&outbuf[pos], "\n"); _key_count++; } static void _save_key_family(const char *name, const void *data, u32 start_key, u32 num_keys, u32 len, char *outbuf) { char *temp_name = calloc(1, 0x40); for (u32 i = 0; i < num_keys; i++) { - sprintf(temp_name, "%s_%02x", name, i + start_key); + s_printf(temp_name, "%s_%02x", name, i + start_key); _save_key(temp_name, data + i * len, len, outbuf); } free(temp_name); diff --git a/source/libs/fatfs/ffconf.h b/source/libs/fatfs/ffconf.h index 4b914b3..a8a39df 100644 --- a/source/libs/fatfs/ffconf.h +++ b/source/libs/fatfs/ffconf.h @@ -245,7 +245,7 @@ #define FF_FS_NORTC 1 #define FF_NORTC_MON 1 #define FF_NORTC_MDAY 1 -#define FF_NORTC_YEAR 2020 +#define FF_NORTC_YEAR 2021 /* 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/source/link.ld b/source/link.ld index 65d681e..fe49b0c 100644 --- a/source/link.ld +++ b/source/link.ld @@ -5,7 +5,8 @@ SECTIONS { . = __ipl_start; .text : { *(.text._start); - *(._boot_cfg); + KEEP(*(._boot_cfg)); + *(.text._irq_setup); *(.text*); } .data : { diff --git a/source/main.c b/source/main.c index d304c8f..deee446 100644 --- a/source/main.c +++ b/source/main.c @@ -1,8 +1,8 @@ /* * Copyright (c) 2018 naehrwert * - * Copyright (c) 2018-2020 CTCaer - * Copyright (c) 2019-2020 shchmue + * Copyright (c) 2018-2021 CTCaer + * Copyright (c) 2019-2021 shchmue * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -20,7 +20,7 @@ #include #include "config.h" -#include +#include #include #include "gfx/tui.h" #include @@ -57,6 +57,7 @@ volatile nyx_storage_t *nyx_str = (nyx_storage_t *)NYX_STORAGE_ADDR; #define EXT_PAYLOAD_ADDR 0xC0000000 #define RCM_PAYLOAD_ADDR (EXT_PAYLOAD_ADDR + ALIGN(PATCHED_RELOC_SZ, 0x10)) #define COREBOOT_END_ADDR 0xD0000000 +#define COREBOOT_VER_OFF 0x41 #define CBFS_DRAM_EN_ADDR 0x4003e000 #define CBFS_DRAM_MAGIC 0x4452414D // "DRAM" @@ -80,9 +81,10 @@ void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size) } } -int launch_payload(char *path) +int launch_payload(char *path, bool clear_screen) { - gfx_clear_grey(0x1B); + if (clear_screen) + gfx_clear_grey(0x1B); gfx_con_setpos(0, 0); if (!path) return 1; @@ -92,10 +94,10 @@ int launch_payload(char *path) FIL fp; if (f_open(&fp, path, FA_READ)) { + gfx_con.mute = false; EPRINTFARGS("Payload file is missing!\n(%s)", path); - sd_unmount(); - return 1; + goto out; } // Read and copy the payload to our chosen address @@ -108,19 +110,27 @@ int launch_payload(char *path) { coreboot_addr = (void *)(COREBOOT_END_ADDR - size); buf = coreboot_addr; + if (h_cfg.t210b01) + { + f_close(&fp); + + gfx_con.mute = false; + EPRINTF("Coreboot not allowed on Mariko!"); + + goto out; + } } if (f_read(&fp, buf, size, NULL)) { f_close(&fp); - sd_unmount(); - return 1; + goto out; } f_close(&fp); - sd_unmount(); + sd_end(); if (size < 0x30000) { @@ -131,7 +141,12 @@ int launch_payload(char *path) else { reloc_patcher(PATCHED_RELOC_ENTRY, EXT_PAYLOAD_ADDR, 0x7000); - hw_reinit_workaround(true, 0); + + // Get coreboot seamless display magic. + u32 magic = 0; + char *magic_ptr = buf + COREBOOT_VER_OFF; + memcpy(&magic, magic_ptr + strlen(magic_ptr) - 4, 4); + hw_reinit_workaround(true, magic); } // Some cards (Sandisk U1), do not like a fast power cycle. Wait min 100ms. @@ -143,6 +158,8 @@ int launch_payload(char *path) (*ext_payload_ptr)(); } +out: + sd_end(); return 1; } @@ -221,7 +238,8 @@ void launch_tools() free(ments); free(dir); free(filelist); - sd_unmount(); + sd_end(); + return; } } @@ -247,15 +265,12 @@ void launch_tools() else memcpy(dir, file_sec, strlen(file_sec) + 1); - if (launch_payload(dir)) - { - EPRINTF("Failed to launch payload."); - free(dir); - } + launch_payload(dir, true); + EPRINTF("Failed to launch payload."); } out: - sd_unmount(); + sd_end(); free(dir); btn_wait(); @@ -278,15 +293,20 @@ void dump_emunand() dump_keys(); } +power_state_t STATE_POWER_OFF = POWER_OFF_RESET; +power_state_t STATE_REBOOT_FULL = POWER_OFF_REBOOT; +power_state_t STATE_REBOOT_RCM = REBOOT_RCM; +power_state_t STATE_REBOOT_BYPASS_FUSES = REBOOT_BYPASS_FUSES; + ment_t ment_top[] = { MDEF_HANDLER("Dump from SysNAND | Key generation: unk", dump_sysnand, COLOR_RED), MDEF_HANDLER("Dump from EmuNAND | Key generation: unk", dump_emunand, COLOR_ORANGE), MDEF_CAPTION("---------------", COLOR_YELLOW), MDEF_HANDLER("Payloads...", launch_tools, COLOR_GREEN), MDEF_CAPTION("---------------", COLOR_BLUE), - MDEF_HANDLER("Reboot (Normal)", reboot_normal, COLOR_VIOLET), - MDEF_HANDLER("Reboot (RCM)", reboot_rcm, COLOR_RED), - MDEF_HANDLER("Power off", power_off, COLOR_ORANGE), + MDEF_HANDLER_EX("Reboot (OFW)", &STATE_REBOOT_BYPASS_FUSES, power_set_state_ex, COLOR_VIOLET), + MDEF_HANDLER_EX("Reboot (RCM)", &STATE_REBOOT_RCM, power_set_state_ex, COLOR_RED), + MDEF_HANDLER_EX("Power off", &STATE_POWER_OFF, power_set_state_ex, COLOR_ORANGE), MDEF_END() }; @@ -305,7 +325,7 @@ void _get_key_generations(char *sysnand_label, char *emunand_label) u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header. const pkg1_id_t *pkg1_id = pkg1_identify(pkg1 + pk1_offset); if (pkg1_id) { - sprintf(sysnand_label + 36, "% 3d", pkg1_id->kb); + s_printf(sysnand_label + 36, "% 3d", pkg1_id->kb); ment_top[0].caption = sysnand_label; if (h_cfg.emummc_force_disable) { @@ -314,15 +334,15 @@ void _get_key_generations(char *sysnand_label, char *emunand_label) } } - emummc_storage_init_mmc(&storage, &sdmmc); + emummc_storage_init_mmc(); memset(pkg1, 0, PKG1_MAX_SIZE); - emummc_storage_set_mmc_partition(&storage, EMMC_BOOT0); - emummc_storage_read(&storage, PKG1_OFFSET / NX_EMMC_BLOCKSIZE, PKG1_MAX_SIZE / NX_EMMC_BLOCKSIZE, pkg1); - emummc_storage_end(&storage); + emummc_storage_set_mmc_partition(EMMC_BOOT0); + emummc_storage_read(PKG1_OFFSET / NX_EMMC_BLOCKSIZE, PKG1_MAX_SIZE / NX_EMMC_BLOCKSIZE, pkg1); + emummc_storage_end(); pkg1_id = pkg1_identify(pkg1 + pk1_offset); if (pkg1_id) { - sprintf(emunand_label + 36, "% 3d", pkg1_id->kb); + s_printf(emunand_label + 36, "% 3d", pkg1_id->kb); free(pkg1); ment_top[1].caption = emunand_label; } @@ -367,8 +387,9 @@ void ipl_main() display_backlight_pwm_init(); // Overclock BPMP. - bpmp_clk_rate_set(BPMP_CLK_DEFAULT_BOOST); + bpmp_clk_rate_set(h_cfg.t210b01 ? BPMP_CLK_DEFAULT_BOOST : BPMP_CLK_LOWER_BOOST); + // Load emuMMC configuration from SD. emummc_load_cfg(); // Ignore whether emummc is enabled. h_cfg.emummc_force_disable = emu_cfg.sector == 0 && !emu_cfg.path; @@ -401,7 +422,7 @@ void ipl_main() if (h_cfg.rcm_patched) { - ment_top[5].handler = reboot_full; + ment_top[6].data = &STATE_REBOOT_FULL; } // Update key generations listed in menu. diff --git a/source/start.S b/source/start.S index 534f963..269f2c7 100644 --- a/source/start.S +++ b/source/start.S @@ -23,8 +23,8 @@ .extern memset .type memset, %function -.extern ipl_main -.type ipl_main, %function +.extern _irq_setup +.type _irq_setup, %function .globl _start .type _start, %function @@ -67,7 +67,7 @@ _real_start: LDR R2, =__bss_end SUB R2, R2, R0 BL memset - BL ipl_main + BL _irq_setup B . .globl pivot_stack diff --git a/source/storage/emummc.c b/source/storage/emummc.c index baa4560..52a748e 100644 --- a/source/storage/emummc.c +++ b/source/storage/emummc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 CTCaer + * Copyright (c) 2019-2021 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -131,13 +131,13 @@ static int emummc_raw_get_part_off(int part_idx) return 2; } -int emummc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc) +int emummc_storage_init_mmc() { FILINFO fno; emu_cfg.active_part = 0; // Always init eMMC even when in emuMMC. eMMC is needed from the emuMMC driver anyway. - if (!sdmmc_storage_init_mmc(storage, sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400)) + if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400)) return 2; if (!emu_cfg.enabled || h_cfg.emummc_force_disable) @@ -173,21 +173,21 @@ out: return 1; } -int emummc_storage_end(sdmmc_storage_t *storage) +int emummc_storage_end() { if (!emu_cfg.enabled || h_cfg.emummc_force_disable) - sdmmc_storage_end(storage); + sdmmc_storage_end(&emmc_storage); else sd_end(); return 1; } -int emummc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf) +int emummc_storage_read(u32 sector, u32 num_sectors, void *buf) { FIL fp; if (!emu_cfg.enabled || h_cfg.emummc_force_disable) - return sdmmc_storage_read(storage, sector, num_sectors, buf); + return sdmmc_storage_read(&emmc_storage, sector, num_sectors, buf); else if (emu_cfg.sector) { sector += emu_cfg.sector; @@ -228,11 +228,11 @@ int emummc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, v return 1; } -int emummc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf) +int emummc_storage_write(u32 sector, u32 num_sectors, void *buf) { FIL fp; if (!emu_cfg.enabled || h_cfg.emummc_force_disable) - return sdmmc_storage_write(storage, sector, num_sectors, buf); + return sdmmc_storage_write(&emmc_storage, sector, num_sectors, buf); else if (emu_cfg.sector) { sector += emu_cfg.sector; @@ -253,15 +253,13 @@ int emummc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, itoa(file_part, emu_cfg.emummc_file_based_path + strlen(emu_cfg.emummc_file_based_path) - 1, 10); } } + if (f_open(&fp, emu_cfg.emummc_file_based_path, FA_WRITE)) - { - gfx_printf("e5\n"); return 0; - } + f_lseek(&fp, (u64)sector << 9); if (f_write(&fp, buf, (u64)num_sectors << 9, NULL)) { - gfx_printf("e6\n"); f_close(&fp); return 0; } @@ -271,13 +269,12 @@ int emummc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, } } -int emummc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition) +int emummc_storage_set_mmc_partition(u32 partition) { emu_cfg.active_part = partition; + sdmmc_storage_set_mmc_partition(&emmc_storage, partition); - if (!emu_cfg.enabled || h_cfg.emummc_force_disable) - sdmmc_storage_set_mmc_partition(storage, partition); - else if (emu_cfg.sector) + if (!emu_cfg.enabled || h_cfg.emummc_force_disable || emu_cfg.sector) return 1; else { diff --git a/source/storage/emummc.h b/source/storage/emummc.h index 81ad123..e8b1d32 100644 --- a/source/storage/emummc.h +++ b/source/storage/emummc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 CTCaer + * Copyright (c) 2019-2021 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -51,10 +51,10 @@ extern emummc_cfg_t emu_cfg; void emummc_load_cfg(); bool emummc_set_path(char *path); -int emummc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc); -int emummc_storage_end(sdmmc_storage_t *storage); -int emummc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf); -int emummc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf); -int emummc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition); +int emummc_storage_init_mmc(); +int emummc_storage_end(); +int emummc_storage_read(u32 sector, u32 num_sectors, void *buf); +int emummc_storage_write(u32 sector, u32 num_sectors, void *buf); +int emummc_storage_set_mmc_partition(u32 partition); #endif \ No newline at end of file diff --git a/source/storage/nx_emmc.c b/source/storage/nx_emmc.c index be7aa4b..223c449 100644 --- a/source/storage/nx_emmc.c +++ b/source/storage/nx_emmc.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 naehrwert + * Copyright (c) 2019-2021 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -19,6 +20,7 @@ #include "nx_emmc.h" #include "emummc.h" #include +#include #include #include @@ -30,7 +32,11 @@ 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); - emummc_storage_read(storage, NX_GPT_FIRST_LBA, NX_GPT_NUM_BLOCKS, gpt_buf); + emummc_storage_read(NX_GPT_FIRST_LBA, NX_GPT_NUM_BLOCKS, gpt_buf); + + // Check if no GPT or more than max allowed entries. + if (memcmp(&gpt_buf->header.signature, "EFI PART", 8) || gpt_buf->header.num_part_ents > 128) + goto out; for (u32 i = 0; i < gpt_buf->header.num_part_ents; i++) { @@ -52,6 +58,7 @@ void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage) list_append(gpt, &part->link); } +out: free(gpt_buf); } @@ -66,6 +73,7 @@ emmc_part_t *nx_emmc_part_find(link_t *gpt, const char *name) LIST_FOREACH_ENTRY(emmc_part_t, part, gpt, link) if (!strcmp(part->name, name)) return part; + return NULL; } @@ -74,7 +82,8 @@ int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_of // The last LBA is inclusive. if (part->lba_start + sector_off > part->lba_end) return 0; - return emummc_storage_read(storage, part->lba_start + sector_off, num_sectors, buf); + + return emummc_storage_read(part->lba_start + sector_off, num_sectors, buf); } int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf) @@ -82,5 +91,20 @@ int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_o // The last LBA is inclusive. if (part->lba_start + sector_off > part->lba_end) return 0; - return sdmmc_storage_write(storage, part->lba_start + sector_off, num_sectors, buf); + + return emummc_storage_write(part->lba_start + sector_off, num_sectors, buf); +} + +void nx_emmc_get_autorcm_masks(u8 *mod0, u8 *mod1) +{ + if (fuse_read_hw_state() == FUSE_NX_HW_STATE_PROD) + { + *mod0 = 0xF7; + *mod1 = 0x86; + } + else + { + *mod0 = 0x37; + *mod1 = 0x84; + } } diff --git a/source/storage/nx_emmc.h b/source/storage/nx_emmc.h index 5db6a1f..f89f526 100644 --- a/source/storage/nx_emmc.h +++ b/source/storage/nx_emmc.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 naehrwert + * Copyright (c) 2019-2020 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -43,7 +44,9 @@ 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); -int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf); -int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf); +int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf); +int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf); + +void nx_emmc_get_autorcm_masks(u8 *mod0, u8 *mod1); #endif diff --git a/source/storage/nx_emmc_bis.c b/source/storage/nx_emmc_bis.c index a2d19c2..1362274 100644 --- a/source/storage/nx_emmc_bis.c +++ b/source/storage/nx_emmc_bis.c @@ -23,6 +23,7 @@ #include #include +#include #include "../storage/nx_emmc.h" #include "nx_emmc_bis.h" #include @@ -32,7 +33,7 @@ #define CLUSTER_LOOKUP_EMPTY_ENTRY 0xFFFFFFFF #define SECTORS_PER_CLUSTER 0x20 -typedef struct +typedef struct _cluster_cache_t { u32 cluster_num; // index of the cluster in the partition u32 visit_count; // used for debugging/access analysis @@ -41,7 +42,7 @@ typedef struct u8 cluster[XTS_CLUSTER_SIZE]; // the cached cluster itself } cluster_cache_t; -typedef struct +typedef struct _bis_cache_t { u8 emmc_buffer[XTS_CLUSTER_SIZE]; cluster_cache_t cluster_cache[]; @@ -313,8 +314,8 @@ void nx_emmc_bis_cluster_cache_init() free(cluster_lookup_buf); // Check if carveout protected, in case of old hwinit (pre 4.0.0) chainload. - *(vu32 *)NX_BIS_LOOKUP_ADR = 0; - if (*(vu32 *)NX_BIS_LOOKUP_ADR != 0) + *(vu32 *)NX_BIS_LOOKUP_ADDR = 0; + if (*(vu32 *)NX_BIS_LOOKUP_ADDR != 0) { cluster_lookup_buf = (u32 *)malloc(cluster_lookup_size + 0x2000); cluster_lookup = (u32 *)ALIGN((u32)cluster_lookup_buf, 0x1000); @@ -322,7 +323,7 @@ void nx_emmc_bis_cluster_cache_init() else { cluster_lookup_buf = NULL; - cluster_lookup = (u32 *)NX_BIS_LOOKUP_ADR; + cluster_lookup = (u32 *)NX_BIS_LOOKUP_ADDR; } // Clear cluster lookup table and reset end index. diff --git a/source/storage/nx_sd.c b/source/storage/nx_sd.c index fa284fa..f2cec2f 100644 --- a/source/storage/nx_sd.c +++ b/source/storage/nx_sd.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2019 CTCaer + * Copyright (c) 2018-2021 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -59,6 +59,11 @@ bool sd_get_card_removed() return false; } +bool sd_get_card_mounted() +{ + return sd_mounted; +} + u32 sd_get_mode() { return sd_mode; @@ -180,6 +185,11 @@ static void _sd_deinit() void sd_unmount() { _sd_deinit(); } void sd_end() { _sd_deinit(); } +bool sd_is_gpt() +{ + return sd_fs.part_type; +} + void *sd_file_read(const char *path, u32 *fsize) { FIL fp;