From c9b22b2a36ff15aeb57c33f7dbd0ad4e8a4eb726 Mon Sep 17 00:00:00 2001 From: Damien Zhao Date: Sun, 2 Apr 2023 13:21:57 +0800 Subject: [PATCH] uplift bdk Signed-off-by: Damien Zhao --- bdk/display/di.c | 2 +- bdk/input/touch.c | 24 ++- bdk/libs/lv_conf.h | 2 +- bdk/sec/tsec.h | 21 +-- bdk/soc/clock.c | 128 ++++++++----- bdk/soc/clock.h | 8 +- bdk/soc/gpio.c | 82 +++++--- bdk/soc/gpio.h | 1 + bdk/soc/hw_init.c | 8 +- bdk/storage/sd.c | 40 +++- bdk/storage/sd.h | 8 +- bdk/storage/sd_def.h | 85 +++++---- bdk/storage/sdmmc.c | 343 +++++++++++++++++++++++----------- bdk/storage/sdmmc_driver.c | 303 ++++++++++++++++++++---------- bdk/storage/sdmmc_driver.h | 215 +++++++++++++-------- bdk/storage/sdmmc_t210.h | 31 +-- bdk/utils/util.c | 3 - source/gfx/menu.c | 1 + source/keys/keys.c | 19 ++ source/script/functions.c | 1 + source/storage/emmcfile.c | 2 +- source/storage/mountmanager.c | 6 +- source/tegraexplorer/tools.c | 1 + source/utils/utils.c | 1 + 24 files changed, 868 insertions(+), 467 deletions(-) diff --git a/bdk/display/di.c b/bdk/display/di.c index 39bcfe1..f8742a9 100644 --- a/bdk/display/di.c +++ b/bdk/display/di.c @@ -76,7 +76,7 @@ static void _display_dsi_wait_vblank(bool enable) } else { - // Wait for vblank before reseting sync points. + // Wait for vblank before resetting sync points. DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT; // Clear interrupt. while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT)) ; diff --git a/bdk/input/touch.c b/bdk/input/touch.c index 2825ebd..7a986f3 100644 --- a/bdk/input/touch.c +++ b/bdk/input/touch.c @@ -401,23 +401,29 @@ static int touch_init() int touch_power_on() { - // Enable LDO6 for touchscreen AVDD supply. - max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000); - max7762x_regulator_enable(REGULATOR_LDO6, true); - - // Configure touchscreen VDD GPIO. - PINMUX_AUX(PINMUX_AUX_DAP4_SCLK) = PINMUX_PULL_DOWN | 1; - gpio_direction_output(GPIO_PORT_J, GPIO_PIN_7, GPIO_HIGH); - // 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; + PINMUX_AUX(PINMUX_AUX_CAM_I2C_SCL) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_TRISTATE | PINMUX_PULL_DOWN | 2; // Unused. gpio_config(GPIO_PORT_S, GPIO_PIN_3, GPIO_MODE_GPIO); // GC detect. + // Configure touchscreen Touch Reset pin. + PINMUX_AUX(PINMUX_AUX_DAP4_SCLK) = PINMUX_PULL_DOWN | 1; + gpio_direction_output(GPIO_PORT_J, GPIO_PIN_7, GPIO_LOW); + usleep(20); + + // Enable LDO6 for touchscreen AVDD and DVDD supply. + max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000); + max7762x_regulator_enable(REGULATOR_LDO6, true); + // Initialize I2C3. pinmux_config_i2c(I2C_3); clock_enable_i2c(I2C_3); i2c_init(I2C_3); + usleep(1000); + + // Set Touch Reset pin. + gpio_write(GPIO_PORT_J, GPIO_PIN_7, GPIO_HIGH); + usleep(10000); // Wait for the touchscreen module to get ready. touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20, NULL); diff --git a/bdk/libs/lv_conf.h b/bdk/libs/lv_conf.h index 7af36a4..e0dde93 100644 --- a/bdk/libs/lv_conf.h +++ b/bdk/libs/lv_conf.h @@ -149,7 +149,7 @@ /*HAL settings*/ #define LV_TICK_CUSTOM 1 /*1: use a custom tick source (removing the need to manually update the tick with `lv_tick_inc`) */ #if LV_TICK_CUSTOM == 1 -#define LV_TICK_CUSTOM_INCLUDE /*Header for the sys time function*/ +#define LV_TICK_CUSTOM_INCLUDE /*Header for the sys time function*/ #define LV_TICK_CUSTOM_SYS_TIME_EXPR (get_tmr_ms()) /*Expression evaluating to current systime in ms*/ #endif /*LV_TICK_CUSTOM*/ diff --git a/bdk/sec/tsec.h b/bdk/sec/tsec.h index c9851a5..81a2cce 100644 --- a/bdk/sec/tsec.h +++ b/bdk/sec/tsec.h @@ -20,13 +20,11 @@ #include -#define TSEC_KEY_DATA_OFFSET 0x300 - enum tsec_fw_type { // Retail Hovi Keygen. TSEC_FW_TYPE_OLD = 0, // 1.0.0 - 6.1.0. - TSEC_FW_TYPE_EMU = 1, // 6.2.0 emulated enviroment. + TSEC_FW_TYPE_EMU = 1, // 6.2.0 emulated environment. TSEC_FW_TYPE_NEW = 2, // 7.0.0+. }; @@ -40,23 +38,6 @@ typedef struct _tsec_ctxt_t u32 secmon_base; } tsec_ctxt_t; -typedef struct _tsec_key_data_t -{ - u8 debug_key[0x10]; - u8 blob0_auth_hash[0x10]; - u8 blob1_auth_hash[0x10]; - u8 blob2_auth_hash[0x10]; - u8 blob2_aes_iv[0x10]; - u8 hovi_eks_seed[0x10]; - u8 hovi_common_seed[0x10]; - u32 blob0_size; - u32 blob1_size; - u32 blob2_size; - u32 blob3_size; - u32 blob4_size; - u8 reserved[0x7C]; -} tsec_key_data_t; - int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt); #endif diff --git a/bdk/soc/clock.c b/bdk/soc/clock.c index 520bdd6..22c3486 100644 --- a/bdk/soc/clock.c +++ b/bdk/soc/clock.c @@ -39,9 +39,9 @@ static const clock_osc_t _clock_osc_cnt[] = { { 48000, 2836, 3023 } }; -/* clock_t: reset, enable, source, index, clk_src, clk_div */ +/* clk_rst_t: reset, enable, source, index, clk_src, clk_div */ -static const clock_t _clock_uart[] = { +static const clk_rst_t _clock_uart[] = { { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTA, CLK_L_UARTA, 0, 2 }, { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTB, CLK_L_UARTB, 0, 2 }, { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_UARTC, CLK_H_UARTC, 0, 2 }, @@ -50,7 +50,7 @@ static const clock_t _clock_uart[] = { }; //I2C default parameters - TLOW: 4, THIGH: 2, DEBOUNCE: 0, FM_DIV: 26. -static const clock_t _clock_i2c[] = { +static const clk_rst_t _clock_i2c[] = { { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_I2C1, CLK_L_I2C1, 0, 19 }, //20.4MHz -> 100KHz { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C2, CLK_H_I2C2, 0, 4 }, //81.6MHz -> 400KHz { CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_I2C3, CLK_U_I2C3, 0, 4 }, //81.6MHz -> 400KHz @@ -59,68 +59,68 @@ static const clock_t _clock_i2c[] = { { CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_I2C6, CLK_X_I2C6, 0, 19 } //20.4MHz -> 100KHz }; -static clock_t _clock_se = { +static clk_rst_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 // 408MHz. Default: 408MHz. Max: 627.2 MHz. }; -static clock_t _clock_tzram = { +static clk_rst_t _clock_tzram = { CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_NO_SOURCE, CLK_V_TZRAM, 0, 0 }; -static clock_t _clock_host1x = { +static clk_rst_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 // 163.2MHz. Max: 408MHz. }; -static clock_t _clock_tsec = { +static clk_rst_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 // 204MHz. Max: 408MHz. }; -static clock_t _clock_nvdec = { +static clk_rst_t _clock_nvdec = { CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_NVDEC, CLK_Y_NVDEC, 4, 0 // 408 MHz. Max: 716.8/979.2MHz. }; -static clock_t _clock_nvjpg = { +static clk_rst_t _clock_nvjpg = { CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_NVJPG, CLK_Y_NVJPG, 4, 0 // 408 MHz. Max: 627.2/652.8MHz. }; -static clock_t _clock_vic = { +static clk_rst_t _clock_vic = { CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_VIC, CLK_X_VIC, 2, 0 // 408 MHz. Max: 627.2/652.8MHz. }; -static clock_t _clock_sor_safe = { +static clk_rst_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 = { +static clk_rst_t _clock_sor0 = { 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 = { +static clk_rst_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 // 204MHz. }; -static clock_t _clock_kfuse = { +static clk_rst_t _clock_kfuse = { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_KFUSE, 0, 0 }; -static clock_t _clock_cl_dvfs = { +static clk_rst_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 = { +static clk_rst_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 // 136MHz. }; -static clock_t _clock_pwm = { +static clk_rst_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. HOS: PLLP / 54 = 7.55MHz. }; -static clock_t _clock_sdmmc_legacy_tm = { +static clk_rst_t _clock_sdmmc_legacy_tm = { CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM, CLK_Y_SDMMC_LEGACY_TM, 4, 66 }; -static clock_t _clock_apbdma = { +static clk_rst_t _clock_apbdma = { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_APBDMA, 0, 0 // Max: 204MHz. }; -static clock_t _clock_ahbdma = { +static clk_rst_t _clock_ahbdma = { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_AHBDMA, 0, 0 }; -static clock_t _clock_actmon = { +static clk_rst_t _clock_actmon = { CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_ACTMON, CLK_V_ACTMON, 6, 0 // 19.2MHz. }; -static clock_t _clock_extperiph1 = { +static clk_rst_t _clock_extperiph1 = { CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH1, CLK_V_EXTPERIPH1, 0, 0 }; -static clock_t _clock_extperiph2 = { +static clk_rst_t _clock_extperiph2 = { CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH2, CLK_V_EXTPERIPH2, 2, 202 // 4.0MHz }; -void clock_enable(const clock_t *clk) +void clock_enable(const clk_rst_t *clk) { // Put clock into reset. CLOCK(clk->reset) = (CLOCK(clk->reset) & ~BIT(clk->index)) | BIT(clk->index); @@ -137,7 +137,7 @@ void clock_enable(const clock_t *clk) CLOCK(clk->reset) &= ~BIT(clk->index); } -void clock_disable(const clock_t *clk) +void clock_disable(const clk_rst_t *clk) { // Put clock into reset. CLOCK(clk->reset) = (CLOCK(clk->reset) & ~BIT(clk->index)) | BIT(clk->index); @@ -503,7 +503,7 @@ static void _clock_enable_pllc4(u32 mask) usleep(10); // Set PLLC4 dividers. - CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) = (104 << 8) | 4; // DIVM: 4, DIVP: 1. + CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) = (0 << 19) | (104 << 8) | 4; // DIVP: 1, DIVN: 104, DIVM: 4. 998MHz OUT0, 199MHz OUT2. // Enable PLLC4 and wait for Phase and Frequency lock. CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) |= PLLCX_BASE_ENABLE; @@ -684,7 +684,7 @@ static void _clock_sdmmc_clear_enable(u32 id) static void _clock_sdmmc_config_legacy_tm() { - clock_t *clk = &_clock_sdmmc_legacy_tm; + clk_rst_t *clk = &_clock_sdmmc_legacy_tm; if (!(CLOCK(clk->enable) & BIT(clk->index))) clock_enable(clk); } @@ -699,6 +699,7 @@ static clock_sdmmc_t _clock_sdmmc_table[4] = { 0 }; #define SDMMC_CLOCK_SRC_PLLP_OUT0 0x0 #define SDMMC_CLOCK_SRC_PLLC4_OUT2 0x3 +#define SDMMC_CLOCK_SRC_PLLC4_OUT0 0x7 #define SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ 0x1 static int _clock_sdmmc_config_clock_host(u32 *pclock, u32 id, u32 val) @@ -716,79 +717,88 @@ static int _clock_sdmmc_config_clock_host(u32 *pclock, u32 id, u32 val) *pclock = 24728; divisor = 31; // 16.5 div. break; + case 26000: *pclock = 25500; divisor = 30; // 16 div. break; + case 50000: *pclock = 48000; divisor = 15; // 8.5 div. break; + case 52000: *pclock = 51000; divisor = 14; // 8 div. break; - case 81600: // Originally MMC_HS50 for GC FPGA at 40800 KHz, div 18 (real 10). + + case 82000: *pclock = 81600; - divisor = 8; // 5 div. + divisor = 8; // 5 div. break; + case 100000: source = SDMMC_CLOCK_SRC_PLLC4_OUT2; *pclock = 99840; divisor = 2; // 2 div. break; + case 164000: *pclock = 163200; divisor = 3; // 2.5 div. break; - case 200000: // 240MHz evo+. + + case 200000: switch (id) { case SDMMC_1: - source = SDMMC_CLOCK_SRC_PLLC4_OUT2; - break; - case SDMMC_2: - source = SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ; - break; case SDMMC_3: source = SDMMC_CLOCK_SRC_PLLC4_OUT2; break; + case SDMMC_2: case SDMMC_4: - source = SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ; + source = SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ; // div is ignored. break; } *pclock = 199680; divisor = 0; // 1 div. break; - default: - *pclock = 24728; - divisor = 31; // 16.5 div. + +#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT + case 400000: + source = SDMMC_CLOCK_SRC_PLLC4_OUT0; + *pclock = 399360; + divisor = 3; // 2.5 div + break; +#endif } _clock_sdmmc_table[id].clock = val; _clock_sdmmc_table[id].real_clock = *pclock; // Enable PLLC4 if in use by any SDMMC. - if (source) + if (source != SDMMC_CLOCK_SRC_PLLP_OUT0) _clock_enable_pllc4(BIT(id)); // Set SDMMC legacy timeout clock. _clock_sdmmc_config_legacy_tm(); // Set SDMMC clock. + u32 src_div = (source << 29) | divisor; switch (id) { case SDMMC_1: - CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC1) = (source << 29) | divisor; + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC1) = src_div; break; case SDMMC_2: - CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC2) = (source << 29) | divisor; + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC2) = src_div; break; case SDMMC_3: - CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3) = (source << 29) | divisor; + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3) = src_div; break; case SDMMC_4: - CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC4) = (source << 29) | divisor; + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC4) = src_div; break; } @@ -818,54 +828,71 @@ void clock_sdmmc_get_card_clock_div(u32 *pclock, u16 *pdivisor, u32 type) // Get Card clock divisor. switch (type) { - case SDHCI_TIMING_MMC_ID: // Actual IO Freq: 380.59 KHz. + case SDHCI_TIMING_MMC_ID: // Actual card clock: 386.36 KHz. *pclock = 26000; *pdivisor = 66; break; + case SDHCI_TIMING_MMC_LS26: *pclock = 26000; *pdivisor = 1; break; + case SDHCI_TIMING_MMC_HS52: *pclock = 52000; *pdivisor = 1; break; + case SDHCI_TIMING_MMC_HS200: case SDHCI_TIMING_MMC_HS400: case SDHCI_TIMING_UHS_SDR104: *pclock = 200000; *pdivisor = 1; break; - case SDHCI_TIMING_SD_ID: // Actual IO Freq: 380.43 KHz. + + case SDHCI_TIMING_SD_ID: // Actual card clock: 386.38 KHz. *pclock = 25000; *pdivisor = 64; break; + case SDHCI_TIMING_SD_DS12: case SDHCI_TIMING_UHS_SDR12: *pclock = 25000; *pdivisor = 1; break; + case SDHCI_TIMING_SD_HS25: case SDHCI_TIMING_UHS_SDR25: *pclock = 50000; *pdivisor = 1; break; + case SDHCI_TIMING_UHS_SDR50: *pclock = 100000; *pdivisor = 1; break; + case SDHCI_TIMING_UHS_SDR82: *pclock = 164000; *pdivisor = 1; break; - case SDHCI_TIMING_UHS_DDR50: - *pclock = 81600; // Originally MMC_HS50 for GC FPGA at 40800 KHz, div 1. + + case SDHCI_TIMING_UHS_DDR50: // Actual card clock: 40.80 MHz. + *pclock = 82000; *pdivisor = 2; break; - case SDHCI_TIMING_MMC_DDR100: // Actual IO Freq: 99.84 MHz. + + case SDHCI_TIMING_MMC_HS100: // Actual card clock: 99.84 MHz. *pclock = 200000; *pdivisor = 2; break; + +#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT + case SDHCI_TIMING_UHS_DDR200: // Actual card clock: 199.68 KHz. + *pclock = 400000; + *pdivisor = 2; + break; +#endif } } @@ -884,7 +911,8 @@ void clock_sdmmc_enable(u32 id, u32 val) _clock_sdmmc_config_clock_host(&clock, id, val); _clock_sdmmc_set_enable(id); _clock_sdmmc_is_reset(id); - usleep((100000 + clock - 1) / clock); + // Wait 100 cycles for reset and for clocks to stabilize. + usleep((100 * 1000 + clock - 1) / clock); _clock_sdmmc_clear_reset(id); _clock_sdmmc_is_reset(id); } diff --git a/bdk/soc/clock.h b/bdk/soc/clock.h index fa3f241..b2e161b 100644 --- a/bdk/soc/clock.h +++ b/bdk/soc/clock.h @@ -625,7 +625,7 @@ enum CLK_Y_DEV }; /*! Generic clock descriptor. */ -typedef struct _clock_t +typedef struct _clk_rst_t { u16 reset; u16 enable; @@ -633,11 +633,11 @@ typedef struct _clock_t u8 index; u8 clk_src; u8 clk_div; -} clock_t; +} clk_rst_t; /*! Generic clock enable/disable. */ -void clock_enable(const clock_t *clk); -void clock_disable(const clock_t *clk); +void clock_enable(const clk_rst_t *clk); +void clock_disable(const clk_rst_t *clk); /*! Clock control for specific hardware portions. */ void clock_enable_fuse(bool enable); diff --git a/bdk/soc/gpio.c b/bdk/soc/gpio.c index cdd6191..8575333 100644 --- a/bdk/soc/gpio.c +++ b/bdk/soc/gpio.c @@ -18,23 +18,27 @@ #include #include -#define GPIO_BANK_IDX(port) ((port) >> 2) +#define GPIO_BANK_IDX(port) ((port) >> 2) +#define GPIO_PORT_OFFSET(port) ((GPIO_BANK_IDX(port) << 8) + (((port) % 4) << 2)) -#define GPIO_CNF_OFFSET(port) (0x00 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_OE_OFFSET(port) (0x10 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_OUT_OFFSET(port) (0x20 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_IN_OFFSET(port) (0x30 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_INT_STA_OFFSET(port) (0x40 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_INT_ENB_OFFSET(port) (0x50 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_INT_LVL_OFFSET(port) (0x60 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_INT_CLR_OFFSET(port) (0x70 + (((port) >> 2) << 8) + (((port) % 4) << 2)) +#define GPIO_CNF_OFFSET(port) (0x00 + GPIO_PORT_OFFSET(port)) +#define GPIO_OE_OFFSET(port) (0x10 + GPIO_PORT_OFFSET(port)) +#define GPIO_OUT_OFFSET(port) (0x20 + GPIO_PORT_OFFSET(port)) +#define GPIO_IN_OFFSET(port) (0x30 + GPIO_PORT_OFFSET(port)) +#define GPIO_INT_STA_OFFSET(port) (0x40 + GPIO_PORT_OFFSET(port)) +#define GPIO_INT_ENB_OFFSET(port) (0x50 + GPIO_PORT_OFFSET(port)) +#define GPIO_INT_LVL_OFFSET(port) (0x60 + GPIO_PORT_OFFSET(port)) +#define GPIO_INT_CLR_OFFSET(port) (0x70 + GPIO_PORT_OFFSET(port)) -#define GPIO_CNF_MASKED_OFFSET(port) (0x80 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_OE_MASKED_OFFSET(port) (0x90 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_OUT_MASKED_OFFSET(port) (0xA0 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_INT_STA_MASKED_OFFSET(port) (0xC0 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_INT_ENB_MASKED_OFFSET(port) (0xD0 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_INT_LVL_MASKED_OFFSET(port) (0xE0 + (((port) >> 2) << 8) + (((port) % 4) << 2)) +#define GPIO_CNF_MASKED_OFFSET(port) (0x80 + GPIO_PORT_OFFSET(port)) +#define GPIO_OE_MASKED_OFFSET(port) (0x90 + GPIO_PORT_OFFSET(port)) +#define GPIO_OUT_MASKED_OFFSET(port) (0xA0 + GPIO_PORT_OFFSET(port)) +#define GPIO_INT_STA_MASKED_OFFSET(port) (0xC0 + GPIO_PORT_OFFSET(port)) +#define GPIO_INT_ENB_MASKED_OFFSET(port) (0xD0 + GPIO_PORT_OFFSET(port)) +#define GPIO_INT_LVL_MASKED_OFFSET(port) (0xE0 + GPIO_PORT_OFFSET(port)) + +#define GPIO_DB_CTRL_OFFSET(port) (0xB0 + GPIO_PORT_OFFSET(port)) +#define GPIO_DB_CNT_OFFSET(port) (0xF0 + GPIO_PORT_OFFSET(port)) #define GPIO_IRQ_BANK1 32 #define GPIO_IRQ_BANK2 33 @@ -52,7 +56,7 @@ static u8 gpio_bank_irq_ids[8] = { void gpio_config(u32 port, u32 pins, int mode) { - u32 offset = GPIO_CNF_OFFSET(port); + const u32 offset = GPIO_CNF_OFFSET(port); if (mode) GPIO(offset) |= pins; @@ -64,7 +68,7 @@ void gpio_config(u32 port, u32 pins, int mode) void gpio_output_enable(u32 port, u32 pins, int enable) { - u32 port_offset = GPIO_OE_OFFSET(port); + const u32 port_offset = GPIO_OE_OFFSET(port); if (enable) GPIO(port_offset) |= pins; @@ -76,7 +80,7 @@ void gpio_output_enable(u32 port, u32 pins, int enable) void gpio_write(u32 port, u32 pins, int high) { - u32 port_offset = GPIO_OUT_OFFSET(port); + const u32 port_offset = GPIO_OUT_OFFSET(port); if (high) GPIO(port_offset) |= pins; @@ -88,27 +92,47 @@ void gpio_write(u32 port, u32 pins, int high) void gpio_direction_input(u32 port, u32 pins) { - gpio_output_enable(port, pins, GPIO_OUTPUT_DISABLE); gpio_config(port, pins, GPIO_MODE_GPIO); + gpio_output_enable(port, pins, GPIO_OUTPUT_DISABLE); } void gpio_direction_output(u32 port, u32 pins, int high) { - gpio_output_enable(port, pins, GPIO_OUTPUT_ENABLE); gpio_config(port, pins, GPIO_MODE_GPIO); gpio_write(port, pins, high); + gpio_output_enable(port, pins, GPIO_OUTPUT_ENABLE); } int gpio_read(u32 port, u32 pins) { - u32 port_offset = GPIO_IN_OFFSET(port); + const u32 port_offset = GPIO_IN_OFFSET(port); return (GPIO(port_offset) & pins) ? 1 : 0; } +void gpio_set_debounce(u32 port, u32 pins, u32 ms) +{ + const u32 db_ctrl_offset = GPIO_DB_CTRL_OFFSET(port); + const u32 db_cnt_offset = GPIO_DB_CNT_OFFSET(port); + + if (ms) + { + if (ms > 255) + ms = 255; + + // Debounce time affects all pins of the same port. + GPIO(db_cnt_offset) = ms; + GPIO(db_ctrl_offset) = (pins << 8) | pins; + } + else + GPIO(db_ctrl_offset) = (pins << 8) | 0; + + (void)GPIO(db_ctrl_offset); // Commit the write. +} + static void _gpio_interrupt_clear(u32 port, u32 pins) { - u32 port_offset = GPIO_INT_CLR_OFFSET(port); + const u32 port_offset = GPIO_INT_CLR_OFFSET(port); GPIO(port_offset) |= pins; @@ -117,10 +141,10 @@ static void _gpio_interrupt_clear(u32 port, u32 pins) int gpio_interrupt_status(u32 port, u32 pins) { - u32 port_offset = GPIO_INT_STA_OFFSET(port); - u32 enabled = GPIO(GPIO_INT_ENB_OFFSET(port)) & pins; + const u32 port_offset = GPIO_INT_STA_OFFSET(port); + const u32 enabled_mask = GPIO(GPIO_INT_ENB_OFFSET(port)) & pins; - int status = ((GPIO(port_offset) & pins) && enabled) ? 1 : 0; + int status = ((GPIO(port_offset) & pins) && enabled_mask) ? 1 : 0; // Clear the interrupt status. if (status) @@ -131,7 +155,7 @@ int gpio_interrupt_status(u32 port, u32 pins) void gpio_interrupt_enable(u32 port, u32 pins, int enable) { - u32 port_offset = GPIO_INT_ENB_OFFSET(port); + const u32 port_offset = GPIO_INT_ENB_OFFSET(port); // Clear any possible stray interrupt. _gpio_interrupt_clear(port, pins); @@ -146,7 +170,7 @@ void gpio_interrupt_enable(u32 port, u32 pins, int enable) void gpio_interrupt_level(u32 port, u32 pins, int high, int edge, int delta) { - u32 port_offset = GPIO_INT_LVL_OFFSET(port); + const u32 port_offset = GPIO_INT_LVL_OFFSET(port); u32 val = GPIO(port_offset); @@ -175,7 +199,7 @@ void gpio_interrupt_level(u32 port, u32 pins, int high, int edge, int delta) u32 gpio_get_bank_irq_id(u32 port) { - u32 bank_idx = GPIO_BANK_IDX(port); + const u32 bank_idx = GPIO_BANK_IDX(port); return gpio_bank_irq_ids[bank_idx]; -} \ No newline at end of file +} diff --git a/bdk/soc/gpio.h b/bdk/soc/gpio.h index 09c29cf..7f94de5 100644 --- a/bdk/soc/gpio.h +++ b/bdk/soc/gpio.h @@ -89,6 +89,7 @@ void gpio_direction_input(u32 port, u32 pins); void gpio_direction_output(u32 port, u32 pins, int high); void gpio_write(u32 port, u32 pins, int high); int gpio_read(u32 port, u32 pins); +void gpio_set_debounce(u32 port, u32 pins, u32 ms); int gpio_interrupt_status(u32 port, u32 pins); void gpio_interrupt_enable(u32 port, u32 pins, int enable); void gpio_interrupt_level(u32 port, u32 pins, int high, int edge, int delta); diff --git a/bdk/soc/hw_init.c b/bdk/soc/hw_init.c index 91160d0..60cb1ce 100644 --- a/bdk/soc/hw_init.c +++ b/bdk/soc/hw_init.c @@ -254,15 +254,17 @@ static void _config_se_brom() // This memset needs to happen here, else TZRAM will behave weirdly later on. memset((void *)TZRAM_BASE, 0, TZRAM_SIZE); PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_ENABLE; - SE(SE_INT_STATUS_REG) = 0x1F; // Clear all SE interrupts. + + // Clear SE interrupts. + SE(SE_INT_STATUS_REG) = SE_INT_OP_DONE | SE_INT_OUT_DONE | SE_INT_OUT_LL_BUF_WR | SE_INT_IN_DONE | SE_INT_IN_LL_BUF_RD; // Save reset reason. hw_rst_status = PMC(APBDEV_PMC_SCRATCH200); hw_rst_reason = PMC(APBDEV_PMC_RST_STATUS) & PMC_RST_STATUS_MASK; // Clear the boot reason to avoid problems later. - PMC(APBDEV_PMC_SCRATCH200) = 0x0; - PMC(APBDEV_PMC_RST_STATUS) = 0x0; + PMC(APBDEV_PMC_SCRATCH200) = 0; + PMC(APBDEV_PMC_RST_STATUS) = PMC_RST_STATUS_POR; APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) = (APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) & 0xF0) | (7 << 10); } diff --git a/bdk/storage/sd.c b/bdk/storage/sd.c index ce7e078..f2a22ed 100644 --- a/bdk/storage/sd.c +++ b/bdk/storage/sd.c @@ -22,11 +22,18 @@ #include #include +#ifndef BDK_SDMMC_UHS_DDR200_SUPPORT +#define SD_DEFAULT_SPEED SD_UHS_SDR104 +#else +#define SD_DEFAULT_SPEED SD_UHS_DDR208 +#endif + static bool sd_mounted = false; static bool sd_init_done = false; static bool insertion_event = false; static u16 sd_errors[3] = { 0 }; // Init and Read/Write errors. -static u32 sd_mode = SD_UHS_SDR104; +static u32 sd_mode = SD_DEFAULT_SPEED; + sdmmc_t sd_sdmmc; sdmmc_storage_t sd_storage; @@ -79,7 +86,11 @@ u32 sd_get_mode() int sd_init_retry(bool power_cycle) { u32 bus_width = SDMMC_BUS_WIDTH_4; +#ifndef BDK_SDMMC_UHS_DDR200_SUPPORT u32 type = SDHCI_TIMING_UHS_SDR104; +#else + u32 type = SDHCI_TIMING_UHS_DDR200; +#endif // Power cycle SD card. if (power_cycle) @@ -93,21 +104,33 @@ int sd_init_retry(bool power_cycle) { case SD_INIT_FAIL: // Reset to max. return 0; + case SD_1BIT_HS25: bus_width = SDMMC_BUS_WIDTH_1; type = SDHCI_TIMING_SD_HS25; break; + case SD_4BIT_HS25: type = SDHCI_TIMING_SD_HS25; break; + case SD_UHS_SDR82: type = SDHCI_TIMING_UHS_SDR82; break; + case SD_UHS_SDR104: type = SDHCI_TIMING_UHS_SDR104; break; + +#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT + case SD_UHS_DDR208: + type = SDHCI_TIMING_UHS_DDR200; + break; +#endif + default: - sd_mode = SD_UHS_SDR104; + sd_mode = SD_DEFAULT_SPEED; + break; } int res = sdmmc_storage_init_sd(&sd_storage, &sd_sdmmc, bus_width, type); @@ -135,7 +158,7 @@ bool sd_initialize(bool power_cycle) return true; else if (!sdmmc_get_sd_inserted()) // SD Card is not inserted. { - sd_mode = SD_UHS_SDR104; + sd_mode = SD_DEFAULT_SPEED; break; } else @@ -194,8 +217,12 @@ bool sd_mount() static void _sd_deinit(bool deinit) { - if (deinit && sd_mode == SD_INIT_FAIL) - sd_mode = SD_UHS_SDR104; + if (deinit) + { + insertion_event = false; + if (sd_mode == SD_INIT_FAIL) + sd_mode = SD_DEFAULT_SPEED; + } if (sd_init_done) { @@ -205,8 +232,7 @@ static void _sd_deinit(bool deinit) if (deinit) { sdmmc_storage_end(&sd_storage); - sd_init_done = false; - insertion_event = false; + sd_init_done = false; } } sd_mounted = false; diff --git a/bdk/storage/sd.h b/bdk/storage/sd.h index 863fb3c..7c6170b 100644 --- a/bdk/storage/sd.h +++ b/bdk/storage/sd.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2021 CTCaer + * Copyright (c) 2018-2023 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,7 +30,11 @@ enum SD_1BIT_HS25 = 1, SD_4BIT_HS25 = 2, SD_UHS_SDR82 = 3, - SD_UHS_SDR104 = 4 + SD_UHS_SDR104 = 4, +#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT + SD_UHS_DDR208 = 5 +#endif + }; enum diff --git a/bdk/storage/sd_def.h b/bdk/storage/sd_def.h index 5895b15..1316b50 100644 --- a/bdk/storage/sd_def.h +++ b/bdk/storage/sd_def.h @@ -45,15 +45,14 @@ #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_BUSY (1 << 31) /* Card Power up Status */ +#define SD_OCR_VDD_18 (1U << 7) /* VDD voltage 1.8 */ +#define SD_VHD_27_36 (1U << 8) /* VDD voltage 2.7 ~ 3.6 */ +#define SD_OCR_VDD_32_33 (1U << 20) /* VDD voltage 3.2 ~ 3.3 */ +#define SD_OCR_S18R (1U << 24) /* 1.8V switching request */ +#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */ +#define SD_OCR_XPC (1U << 28) /* SDXC power control */ +#define SD_OCR_CCS (1U << 30) /* Card Capacity Status */ +#define SD_OCR_BUSY (1U << 31) /* Card Power up Status */ /* * SD_SWITCH argument format: @@ -90,8 +89,8 @@ #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 */ -#define SD_SCR_BUS_WIDTH_1 (1<<0) -#define SD_SCR_BUS_WIDTH_4 (1<<2) +#define SD_SCR_BUS_WIDTH_1 (1U << 0) +#define SD_SCR_BUS_WIDTH_4 (1U << 2) /* * SD bus widths @@ -102,33 +101,55 @@ /* * SD bus speeds */ -#define UHS_SDR12_BUS_SPEED 0 +#define UHS_SDR12_BUS_SPEED 0 #define HIGH_SPEED_BUS_SPEED 1 -#define UHS_SDR25_BUS_SPEED 1 -#define UHS_SDR50_BUS_SPEED 2 +#define UHS_SDR25_BUS_SPEED 1 +#define UHS_SDR50_BUS_SPEED 2 #define UHS_SDR104_BUS_SPEED 3 -#define UHS_DDR50_BUS_SPEED 4 -#define HS400_BUS_SPEED 5 +#define UHS_DDR50_BUS_SPEED 4 +#define HS400_BUS_SPEED 5 -#define SD_MODE_HIGH_SPEED (1 << HIGH_SPEED_BUS_SPEED) -#define SD_MODE_UHS_SDR12 (1 << UHS_SDR12_BUS_SPEED) -#define SD_MODE_UHS_SDR25 (1 << UHS_SDR25_BUS_SPEED) -#define SD_MODE_UHS_SDR50 (1 << UHS_SDR50_BUS_SPEED) -#define SD_MODE_UHS_SDR104 (1 << UHS_SDR104_BUS_SPEED) -#define SD_MODE_UHS_DDR50 (1 << UHS_DDR50_BUS_SPEED) +#define SD_MODE_HIGH_SPEED (1U << HIGH_SPEED_BUS_SPEED) +#define SD_MODE_UHS_SDR12 (1U << UHS_SDR12_BUS_SPEED) +#define SD_MODE_UHS_SDR25 (1U << UHS_SDR25_BUS_SPEED) +#define SD_MODE_UHS_SDR50 (1U << UHS_SDR50_BUS_SPEED) +#define SD_MODE_UHS_SDR104 (1U << UHS_SDR104_BUS_SPEED) +#define SD_MODE_UHS_DDR50 (1U << UHS_DDR50_BUS_SPEED) -#define SD_DRIVER_TYPE_B 0x01 -#define SD_DRIVER_TYPE_A 0x02 + +#define SD_SET_DRIVER_TYPE_B 0 +#define SD_SET_DRIVER_TYPE_A 1 +#define SD_SET_DRIVER_TYPE_C 2 +#define SD_SET_DRIVER_TYPE_D 3 + +#define SD_DRIVER_TYPE_B (1U << SD_SET_DRIVER_TYPE_B) +#define SD_DRIVER_TYPE_A (1U << SD_SET_DRIVER_TYPE_A) +#define SD_DRIVER_TYPE_C (1U << SD_SET_DRIVER_TYPE_C) +#define SD_DRIVER_TYPE_D (1U << SD_SET_DRIVER_TYPE_D) #define SD_SET_POWER_LIMIT_0_72 0 #define SD_SET_POWER_LIMIT_1_44 1 #define SD_SET_POWER_LIMIT_2_16 2 #define SD_SET_POWER_LIMIT_2_88 3 -#define SD_MAX_POWER_0_72 (1 << SD_SET_POWER_LIMIT_0_72) -#define SD_MAX_POWER_1_44 (1 << SD_SET_POWER_LIMIT_1_44) -#define SD_MAX_POWER_2_16 (1 << SD_SET_POWER_LIMIT_2_16) -#define SD_MAX_POWER_2_88 (1 << SD_SET_POWER_LIMIT_2_88) +#define SD_MAX_POWER_0_72 (1U << SD_SET_POWER_LIMIT_0_72) +#define SD_MAX_POWER_1_44 (1U << SD_SET_POWER_LIMIT_1_44) +#define SD_MAX_POWER_2_16 (1U << SD_SET_POWER_LIMIT_2_16) +#define SD_MAX_POWER_2_88 (1U << SD_SET_POWER_LIMIT_2_88) + +#define SD_SET_CMD_SYSTEM_DEF 0 +#define SD_SET_CMD_SYSTEM_MEC 1 +#define SD_SET_CMD_SYSTEM_OTP 3 +#define SD_SET_CMD_SYSTEM_OSD 3 +#define SD_SET_CMD_SYSTEM_VND 14 +#define UHS_DDR200_BUS_SPEED SD_SET_CMD_SYSTEM_VND + +#define SD_CMD_SYSTEM_DEF (1U << SD_SET_CMD_SYSTEM_DEF) +#define SD_CMD_SYSTEM_MEC (1U << SD_SET_CMD_SYSTEM_MEC) +#define SD_CMD_SYSTEM_OTP (1U << SD_SET_CMD_SYSTEM_OTP) +#define SD_CMD_SYSTEM_OSD (1U << SD_SET_CMD_SYSTEM_OSD) +#define SD_CMD_SYSTEM_VND (1U << SD_SET_CMD_SYSTEM_VND) +#define SD_MODE_UHS_DDR200 SD_CMD_SYSTEM_VND /* * SD_SWITCH mode @@ -140,14 +161,14 @@ * SD_SWITCH function groups */ #define SD_SWITCH_GRP_ACCESS 0 -#define SD_SWITCH_GRP_CMDSYS 1 -#define SD_SWITCH_GRP_DRVSTR 2 -#define SD_SWITCH_GRP_PWRLIM 3 +#define SD_SWITCH_GRP_CMDSYS 1 +#define SD_SWITCH_GRP_DRVSTR 2 +#define SD_SWITCH_GRP_PWRLIM 3 /* * SD_SWITCH access modes */ #define SD_SWITCH_ACCESS_DEF 0 -#define SD_SWITCH_ACCESS_HS 1 +#define SD_SWITCH_ACCESS_HS 1 #endif /* SD_DEF_H */ diff --git a/bdk/storage/sdmmc.c b/bdk/storage/sdmmc.c index 7c5b12b..c042f59 100644 --- a/bdk/storage/sdmmc.c +++ b/bdk/storage/sdmmc.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -35,8 +36,9 @@ u32 sd_power_cycle_time_start; static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size) { const u32 mask = (size < 32 ? 1 << size : 0) - 1; - const u32 off = 3 - ((start) / 32); + const u32 off = 3 - ((start) / 32); const u32 shft = (start) & 31; + u32 res = resp[off] >> shft; if (size + shft > 32) res |= resp[off - 1] << ((32 - shft) % 32); @@ -577,7 +579,7 @@ static int _mmc_storage_enable_HS(sdmmc_storage_t *storage, bool check_sts_befor if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_MMC_HS52)) return 0; -DPRINTF("[MMC] switched to HS52\n"); + DPRINTF("[MMC] switched to HS52\n"); storage->csd.busspeed = 52; if (check_sts_before_clk_setup || _sdmmc_storage_check_status(storage)) @@ -597,7 +599,7 @@ static int _mmc_storage_enable_HS200(sdmmc_storage_t *storage) if (!sdmmc_tuning_execute(storage->sdmmc, SDHCI_TIMING_MMC_HS200, MMC_SEND_TUNING_BLOCK_HS200)) return 0; -DPRINTF("[MMC] switched to HS200\n"); + DPRINTF("[MMC] switched to HS200\n"); storage->csd.busspeed = 200; return _sdmmc_storage_check_status(storage); @@ -622,7 +624,7 @@ static int _mmc_storage_enable_HS400(sdmmc_storage_t *storage) if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_MMC_HS400)) return 0; -DPRINTF("[MMC] switched to HS400\n"); + DPRINTF("[MMC] switched to HS400\n"); storage->csd.busspeed = 400; return _sdmmc_storage_check_status(storage); @@ -668,44 +670,47 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_wid storage->sdmmc = sdmmc; 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; -DPRINTF("[MMC] after init\n"); + DPRINTF("[MMC]-[init: bus: %d, type: %d]\n", bus_width, type); - usleep(1000 + (74000 + sdmmc->divisor - 1) / sdmmc->divisor); + if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_MMC_ID)) + return 0; + DPRINTF("[MMC] after init\n"); + + // Wait 1ms + 74 cycles. + usleep(1000 + (74 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock); if (!_sdmmc_storage_go_idle_state(storage)) return 0; -DPRINTF("[MMC] went to idle state\n"); + DPRINTF("[MMC] went to idle state\n"); if (!_mmc_storage_get_op_cond(storage, SDMMC_POWER_1_8)) return 0; -DPRINTF("[MMC] got op cond\n"); + DPRINTF("[MMC] got op cond\n"); if (!_sdmmc_storage_get_cid(storage)) return 0; -DPRINTF("[MMC] got cid\n"); + DPRINTF("[MMC] got cid\n"); if (!_mmc_storage_set_relative_addr(storage)) return 0; -DPRINTF("[MMC] set relative addr\n"); + DPRINTF("[MMC] set relative addr\n"); if (!_sdmmc_storage_get_csd(storage)) return 0; -DPRINTF("[MMC] got csd\n"); + DPRINTF("[MMC] got csd\n"); _mmc_storage_parse_csd(storage); if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_MMC_LS26)) return 0; -DPRINTF("[MMC] after setup clock\n"); + DPRINTF("[MMC] after setup clock\n"); if (!_sdmmc_storage_select_card(storage)) return 0; -DPRINTF("[MMC] card selected\n"); + DPRINTF("[MMC] card selected\n"); if (!_sdmmc_storage_set_blocklen(storage, 512)) return 0; -DPRINTF("[MMC] set blocklen to 512\n"); + DPRINTF("[MMC] set blocklen to 512\n"); // Check system specification version, only version 4.0 and later support below features. if (storage->csd.mmca_vsn < CSD_SPEC_VER_4) @@ -713,11 +718,11 @@ DPRINTF("[MMC] set blocklen to 512\n"); if (!_mmc_storage_switch_buswidth(storage, bus_width)) return 0; -DPRINTF("[MMC] switched buswidth\n"); + DPRINTF("[MMC] switched buswidth\n"); if (!mmc_storage_get_ext_csd(storage, (u8 *)SDMMC_UPPER_BUFFER)) return 0; -DPRINTF("[MMC] got ext_csd\n"); + DPRINTF("[MMC] got ext_csd\n"); _mmc_storage_parse_cid(storage); // This needs to be after csd and ext_csd. @@ -725,13 +730,13 @@ DPRINTF("[MMC] got ext_csd\n"); if (storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_AUTO_BKOPS_MASK)) { _mmc_storage_enable_auto_bkops(storage); -DPRINTF("[MMC] BKOPS enabled\n"); + DPRINTF("[MMC] BKOPS enabled\n"); } */ if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type)) return 0; -DPRINTF("[MMC] successfully switched to HS mode\n"); + DPRINTF("[MMC] successfully switched to HS mode\n"); sdmmc_card_clock_powersave(storage->sdmmc, SDMMC_POWER_SAVE_ENABLE); @@ -800,15 +805,17 @@ static int _sd_storage_send_if_cond(sdmmc_storage_t *storage, bool *is_sdsc) 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 + // Support for Current > 150mA. u32 arg = !is_sdsc ? SD_OCR_XPC : 0; - // Support for handling block-addressed SDHC cards + // Support for handling block-addressed SDHC cards. arg |= !is_sdsc ? SD_OCR_CCS : 0; - // Support for 1.8V + // Support for 1.8V signaling. 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. + // Support for 3.3V power supply (VDD1). 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, R1_SKIP_STATE_CHECK, is_sdsc ? R1_ILLEGAL_COMMAND : 0, &cmdbuf, NULL, NULL)) return 0; @@ -828,7 +835,7 @@ static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, bool is_sdsc, int b // Check if power up is done. if (cond & SD_OCR_BUSY) { -DPRINTF("[SD] op cond: %08X, lv: %d\n", cond, bus_uhs_support); + DPRINTF("[SD] op cond: %08X, lv: %d\n", cond, bus_uhs_support); // Check if card is high capacity. if (cond & SD_OCR_CCS) @@ -840,16 +847,20 @@ DPRINTF("[SD] op cond: %08X, lv: %d\n", cond, bus_uhs_support); // Switch to 1.8V signaling. if (_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY)) { + if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_UHS_SDR12)) + return 0; + if (!sdmmc_enable_low_voltage(storage->sdmmc)) return 0; + storage->is_low_voltage = 1; -DPRINTF("-> switched to low voltage\n"); + DPRINTF("-> switched to low voltage\n"); } } else { -DPRINTF("[SD] no low voltage support\n"); + DPRINTF("[SD] no low voltage support\n"); } return 1; @@ -897,8 +908,7 @@ static void _sd_storage_parse_scr(sdmmc_storage_t *storage) // unstuff_bits can parse only 4 u32 u32 resp[4]; - resp[3] = *(u32 *)&storage->raw_scr[4]; - resp[2] = *(u32 *)&storage->raw_scr[0]; + memcpy(&resp[2], storage->raw_scr, 8); storage->scr.sda_vsn = unstuff_bits(resp, 56, 4); storage->scr.bus_widths = unstuff_bits(resp, 48, 4); @@ -957,8 +967,6 @@ static int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL)) return 0; - //gfx_hexdump(0, (u8 *)buf, 64); - u32 tmp = 0; sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); return _sdmmc_storage_check_card_status(tmp); @@ -992,59 +1000,139 @@ static void _sd_storage_set_power_limit(sdmmc_storage_t *storage, u16 power_limi { u32 pwr = SD_SET_POWER_LIMIT_0_72; -// If UHS-I only, anything above 1.44W defaults to 1.44W. -#if SDMMC_UHS2_SUPPORT + // If UHS-I only, anything above 1.44W defaults to 1.44W. if (power_limit & SD_MAX_POWER_2_88) pwr = SD_SET_POWER_LIMIT_2_88; else if (power_limit & SD_MAX_POWER_2_16) pwr = SD_SET_POWER_LIMIT_2_16; else if (power_limit & SD_MAX_POWER_1_44) pwr = SD_SET_POWER_LIMIT_1_44; -#else - if (power_limit & SD_MAX_POWER_1_44) - pwr = SD_SET_POWER_LIMIT_1_44; -#endif _sd_storage_switch(storage, buf, SD_SWITCH_SET, SD_SWITCH_GRP_PWRLIM, pwr); - if (((buf[15] >> 4) & 0x0F) == pwr) + switch ((buf[15] >> 4) & 0x0F) { - switch (pwr) - { -#if SDMMC_UHS2_SUPPORT - case SD_SET_POWER_LIMIT_2_88: -DPRINTF("[SD] power limit raised to 2880 mW\n"); - break; + case SD_SET_POWER_LIMIT_2_88: + DPRINTF("[SD] power limit raised to 2880 mW\n"); + break; - case SD_SET_POWER_LIMIT_2_16: -DPRINTF("[SD] power limit raised to 2160 mW\n"); - break; -#endif - case SD_SET_POWER_LIMIT_1_44: -DPRINTF("[SD] power limit raised to 1440 mW\n"); - break; + case SD_SET_POWER_LIMIT_2_16: + DPRINTF("[SD] power limit raised to 2160 mW\n"); + break; - default: - case SD_SET_POWER_LIMIT_0_72: -DPRINTF("[SD] power limit defaulted to 720 mW\n"); - break; - } + case SD_SET_POWER_LIMIT_1_44: + DPRINTF("[SD] power limit raised to 1440 mW\n"); + break; + + default: + case SD_SET_POWER_LIMIT_0_72: + DPRINTF("[SD] power limit defaulted to 720 mW\n"); + break; } } -static int _sd_storage_enable_highspeed(sdmmc_storage_t *storage, u32 hs_type, u8 *buf) +int _sd_storage_set_driver_type(sdmmc_storage_t *storage, u32 driver, u8 *buf) +{ + if (!_sd_storage_switch(storage, buf, SD_SWITCH_CHECK, SD_SWITCH_GRP_DRVSTR, driver)) + return 0; + + u32 driver_out = buf[15] & 0xF; + if (driver_out != driver) + return 0; + DPRINTF("[SD] supports Driver Strength %d\n", driver); + + if (!_sd_storage_switch(storage, buf, SD_SWITCH_SET, SD_SWITCH_GRP_DRVSTR, driver)) + return 0; + + if (driver_out != (buf[15] & 0xF)) + return 0; + DPRINTF("[SD] card accepted Driver Strength %d\n", driver); + + sdmmc_setup_drv_type(storage->sdmmc, driver); + + return 1; +} + +/* + * SD Card DDR200 (DDR208) support + * + * Proper procedure: + * 1. Check that Vendor Specific Command System is supported. + * Used as Enable DDR200 Bus. + * 2. Enable DDR200 bus mode via setting 14 to Group 2 via CMD6. + * Access Mode group is left to default 0 (SDR12). + * 3. Setup clock to 200 or 208 MHz. + * 4. Set host to DDR bus mode that supports such high clocks. + * Some hosts have special mode, others use DDR50 and others HS400. + * 5. Execute Tuning. + * + * The true validation that this value in Group 2 activates it, is that DDR50 bus + * and clocks/timings work fully after that point. + * + * On Tegra X1, that can be done with DDR50 host mode. + * Tuning though can't be done automatically on any DDR mode. + * So it needs to be done manually and selected tap will be applied from the biggest + * sampling window. + * + * Finally, all that simply works, because the marketing materials for DDR200 are + * basically overstatements to sell the feature. DDR200 is simply SDR104 in DDR mode, + * so sampling on rising and falling edge and with variable output data window. + * It can be supported by any host that is fast enough to support DDR at 200/208MHz + * and can do hw/sw tuning for finding the proper sampling window in that mode. + */ +#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT +static int _sd_storage_enable_DDR200(sdmmc_storage_t *storage, u8 *buf) +{ + u32 cmd_system = UHS_DDR200_BUS_SPEED; + if (!_sd_storage_switch(storage, buf, SD_SWITCH_CHECK, SD_SWITCH_GRP_CMDSYS, cmd_system)) + return 0; + + u32 system_out = (buf[16] >> 4) & 0xF; + if (system_out != cmd_system) + return 0; + DPRINTF("[SD] supports DDR200 mode\n"); + + u16 total_pwr_consumption = ((u16)buf[0] << 8) | buf[1]; + DPRINTF("[SD] max power: %d mW\n", total_pwr_consumption * 3600 / 1000); + storage->card_power_limit = total_pwr_consumption; + + if (total_pwr_consumption <= 800) + { + if (!_sd_storage_switch(storage, buf, SD_SWITCH_SET, SD_SWITCH_GRP_CMDSYS, cmd_system)) + return 0; + + if (system_out != ((buf[16] >> 4) & 0xF)) + return 0; + DPRINTF("[SD] card accepted DDR200\n"); + + if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_UHS_DDR200)) + return 0; + DPRINTF("[SD] after setup clock DDR200\n"); + + if (!sdmmc_tuning_execute(storage->sdmmc, SDHCI_TIMING_UHS_DDR200, MMC_SEND_TUNING_BLOCK)) + return 0; + DPRINTF("[SD] after tuning DDR200\n"); + + return _sdmmc_storage_check_status(storage); + } + + DPRINTF("[SD] card max power over limit\n"); + return 0; +} +#endif + +static int _sd_storage_set_card_bus_speed(sdmmc_storage_t *storage, u32 hs_type, u8 *buf) { if (!_sd_storage_switch(storage, buf, SD_SWITCH_CHECK, SD_SWITCH_GRP_ACCESS, hs_type)) return 0; -DPRINTF("[SD] supports (U)HS mode: %d\n", buf[16] & 0xF); u32 type_out = buf[16] & 0xF; if (type_out != hs_type) return 0; -DPRINTF("[SD] supports selected (U)HS mode\n"); + DPRINTF("[SD] supports selected (U)HS mode %d\n", buf[16] & 0xF); u16 total_pwr_consumption = ((u16)buf[0] << 8) | buf[1]; -DPRINTF("[SD] max power: %d mW\n", total_pwr_consumption * 3600 / 1000); + DPRINTF("[SD] max power: %d mW\n", total_pwr_consumption * 3600 / 1000); storage->card_power_limit = total_pwr_consumption; if (total_pwr_consumption <= 800) @@ -1058,7 +1146,7 @@ DPRINTF("[SD] max power: %d mW\n", total_pwr_consumption * 3600 / 1000); return 1; } -DPRINTF("[SD] card max power over limit\n"); + DPRINTF("[SD] card max power over limit\n"); return 0; } @@ -1071,22 +1159,35 @@ static int _sd_storage_enable_uhs_low_volt(sdmmc_storage_t *storage, u32 type, u return 0; u8 access_mode = buf[13]; - u16 power_limit = buf[7] | buf[6] << 8; -DPRINTF("[SD] access: %02X, power: %02X\n", access_mode, power_limit); - - // Try to raise the power limit to let the card perform better. - _sd_storage_set_power_limit(storage, power_limit, buf); + u16 power_limit = buf[7] | buf[6] << 8; +#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT + u16 cmd_system = buf[11] | buf[10] << 8; +#endif + DPRINTF("[SD] access: %02X, power: %02X\n", access_mode, power_limit); u32 hs_type = 0; switch (type) { +#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT + case SDHCI_TIMING_UHS_DDR200: + // Fall through if DDR200 is not supported. + if (cmd_system & SD_MODE_UHS_DDR200) + { + DPRINTF("[SD] setting bus speed to DDR200\n"); + storage->csd.busspeed = 200; + _sd_storage_set_power_limit(storage, power_limit, buf); + return _sd_storage_enable_DDR200(storage, buf); + } +#endif + case SDHCI_TIMING_UHS_SDR104: case SDHCI_TIMING_UHS_SDR82: // Fall through if not supported. if (access_mode & SD_MODE_UHS_SDR104) { + type = SDHCI_TIMING_UHS_SDR104; hs_type = UHS_SDR104_BUS_SPEED; -DPRINTF("[SD] bus speed set to SDR104\n"); + DPRINTF("[SD] setting bus speed to SDR104\n"); switch (type) { case SDHCI_TIMING_UHS_SDR104: @@ -1098,49 +1199,60 @@ DPRINTF("[SD] bus speed set to SDR104\n"); } break; } + case SDHCI_TIMING_UHS_SDR50: if (access_mode & SD_MODE_UHS_SDR50) { - type = SDHCI_TIMING_UHS_SDR50; + type = SDHCI_TIMING_UHS_SDR50; hs_type = UHS_SDR50_BUS_SPEED; -DPRINTF("[SD] bus speed set to SDR50\n"); + DPRINTF("[SD] setting bus speed to SDR50\n"); storage->csd.busspeed = 50; break; } /* + case SDHCI_TIMING_UHS_DDR50: + if (access_mode & SD_MODE_UHS_DDR50) + { + type = SDHCI_TIMING_UHS_DDR50; + hs_type = UHS_DDR50_BUS_SPEED; + DPRINTF("[SD] setting bus speed to DDR50\n"); + storage->csd.busspeed = 50; + break; + } +*/ case SDHCI_TIMING_UHS_SDR25: if (access_mode & SD_MODE_UHS_SDR25) { type = SDHCI_TIMING_UHS_SDR25; hs_type = UHS_SDR25_BUS_SPEED; -DPRINTF("[SD] bus speed set to SDR25\n"); + DPRINTF("[SD] setting bus speed to SDR25\n"); storage->csd.busspeed = 25; break; } -*/ - case SDHCI_TIMING_UHS_SDR12: - if (!(access_mode & SD_MODE_UHS_SDR12)) - return 0; - type = SDHCI_TIMING_UHS_SDR12; - hs_type = UHS_SDR12_BUS_SPEED; -DPRINTF("[SD] bus speed set to SDR12\n"); - storage->csd.busspeed = 12; - break; default: - return 0; - break; + DPRINTF("[SD] bus speed defaulted to SDR12\n"); + storage->csd.busspeed = 12; + return 1; } - if (!_sd_storage_enable_highspeed(storage, hs_type, buf)) + // Try to raise the power limit to let the card perform better. + if (hs_type != UHS_SDR25_BUS_SPEED) + _sd_storage_set_power_limit(storage, power_limit, buf); + + // Setup and set selected card and bus speed. + if (!_sd_storage_set_card_bus_speed(storage, hs_type, buf)) return 0; -DPRINTF("[SD] card accepted UHS\n"); + DPRINTF("[SD] card accepted UHS\n"); + if (!sdmmc_setup_clock(storage->sdmmc, type)) return 0; -DPRINTF("[SD] after setup clock\n"); + DPRINTF("[SD] after setup clock\n"); + if (!sdmmc_tuning_execute(storage->sdmmc, type, MMC_SEND_TUNING_BLOCK)) return 0; -DPRINTF("[SD] after tuning\n"); + DPRINTF("[SD] after tuning\n"); + return _sdmmc_storage_check_status(storage); } @@ -1151,7 +1263,7 @@ static int _sd_storage_enable_hs_high_volt(sdmmc_storage_t *storage, u8 *buf) u8 access_mode = buf[13]; u16 power_limit = buf[7] | buf[6] << 8; -DPRINTF("[SD] access: %02X, power: %02X\n", access_mode, power_limit); + DPRINTF("[SD] access: %02X, power: %02X\n", access_mode, power_limit); // Try to raise the power limit to let the card perform better. _sd_storage_set_power_limit(storage, power_limit, buf); @@ -1159,7 +1271,7 @@ DPRINTF("[SD] access: %02X, power: %02X\n", access_mode, power_limit); if (!(access_mode & SD_MODE_HIGH_SPEED)) return 1; - if (!_sd_storage_enable_highspeed(storage, HIGH_SPEED_BUS_SPEED, buf)) + if (!_sd_storage_set_card_bus_speed(storage, HIGH_SPEED_BUS_SPEED, buf)) return 0; if (!_sdmmc_storage_check_status(storage)) @@ -1259,7 +1371,7 @@ int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf) if (!(storage->csd.cmdclass & CCC_APP_SPEC)) { -DPRINTF("[SD] ssr: Not supported\n"); + DPRINTF("[SD] ssr: Not supported\n"); return 0; } @@ -1323,7 +1435,7 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage) break; default: -DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure); + DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure); break; } @@ -1340,6 +1452,7 @@ static bool _sdmmc_storage_get_bus_uhs_support(u32 bus_width, u32 type) case SDHCI_TIMING_UHS_SDR104: case SDHCI_TIMING_UHS_SDR82: case SDHCI_TIMING_UHS_DDR50: + case SDHCI_TIMING_UHS_DDR200: if (bus_width == SDMMC_BUS_WIDTH_4) return true; default: @@ -1362,7 +1475,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_widt 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); + DPRINTF("[SD]-[init: bus: %d, type: %d]\n", bus_width, type); // Some cards (SanDisk U1), do not like a fast power cycle. Wait min 100ms. sdmmc_storage_init_wait_sd(); @@ -1370,61 +1483,62 @@ DPRINTF("[SD] init: bus: %d, type: %d\n", bus_width, type); memset(storage, 0, sizeof(sdmmc_storage_t)); storage->sdmmc = sdmmc; - if (!sdmmc_init(sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, SDMMC_POWER_SAVE_DISABLE)) + if (!sdmmc_init(sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID)) return 0; -DPRINTF("[SD] after init\n"); + DPRINTF("[SD] after init\n"); - usleep(1000 + (74000 + sdmmc->divisor - 1) / sdmmc->divisor); + // Wait 1ms + 74 cycles. + usleep(1000 + (74 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock); if (!_sdmmc_storage_go_idle_state(storage)) return 0; -DPRINTF("[SD] went to idle state\n"); + DPRINTF("[SD] went to idle state\n"); if (!_sd_storage_send_if_cond(storage, &is_sdsc)) return 0; -DPRINTF("[SD] after send if cond\n"); + DPRINTF("[SD] after send if cond\n"); if (!_sd_storage_get_op_cond(storage, is_sdsc, bus_uhs_support)) return 0; -DPRINTF("[SD] got op cond\n"); + DPRINTF("[SD] got op cond\n"); if (!_sdmmc_storage_get_cid(storage)) return 0; -DPRINTF("[SD] got cid\n"); + DPRINTF("[SD] got cid\n"); _sd_storage_parse_cid(storage); if (!_sd_storage_get_rca(storage)) return 0; -DPRINTF("[SD] got rca (= %04X)\n", storage->rca); + DPRINTF("[SD] got rca (= %04X)\n", storage->rca); if (!_sdmmc_storage_get_csd(storage)) return 0; -DPRINTF("[SD] got csd\n"); + DPRINTF("[SD] got csd\n"); _sd_storage_parse_csd(storage); if (!storage->is_low_voltage) { if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_DS12)) return 0; -DPRINTF("[SD] after setup default clock\n"); + DPRINTF("[SD] after setup default clock\n"); } if (!_sdmmc_storage_select_card(storage)) return 0; -DPRINTF("[SD] card selected\n"); + DPRINTF("[SD] card selected\n"); if (!_sdmmc_storage_set_blocklen(storage, 512)) return 0; -DPRINTF("[SD] set blocklen to 512\n"); + DPRINTF("[SD] set blocklen to 512\n"); // 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"); + DPRINTF("[SD] cleared card detect\n"); if (!sd_storage_get_scr(storage, buf)) return 0; -DPRINTF("[SD] got scr\n"); + DPRINTF("[SD] got scr\n"); // 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) @@ -1433,26 +1547,26 @@ DPRINTF("[SD] got scr\n"); return 0; sdmmc_set_bus_width(storage->sdmmc, SDMMC_BUS_WIDTH_4); -DPRINTF("[SD] switched to wide bus width\n"); + 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"); + DPRINTF("[SD] SD does not support wide bus width\n"); } if (storage->is_low_voltage) { if (!_sd_storage_enable_uhs_low_volt(storage, type, buf)) return 0; -DPRINTF("[SD] enabled UHS\n"); + DPRINTF("[SD] enabled UHS\n"); } 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; -DPRINTF("[SD] enabled HS\n"); + DPRINTF("[SD] enabled HS\n"); switch (bus_width) { case SDMMC_BUS_WIDTH_4: @@ -1468,7 +1582,7 @@ DPRINTF("[SD] enabled HS\n"); // Parse additional card info from sd status. if (sd_storage_get_ssr(storage, buf)) { -DPRINTF("[SD] got sd status\n"); + DPRINTF("[SD] got sd status\n"); } sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE); @@ -1514,15 +1628,16 @@ int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc) memset(storage, 0, sizeof(sdmmc_storage_t)); storage->sdmmc = sdmmc; - if (!sdmmc_init(sdmmc, SDMMC_2, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_DDR100, SDMMC_POWER_SAVE_DISABLE)) + if (!sdmmc_init(sdmmc, SDMMC_2, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS100)) return 0; -DPRINTF("[gc] after init\n"); + DPRINTF("[GC] after init\n"); - usleep(1000 + (10000 + sdmmc->divisor - 1) / sdmmc->divisor); + // Wait 1ms + 10 clock cycles. + usleep(1000 + (10 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock); - if (!sdmmc_tuning_execute(storage->sdmmc, SDHCI_TIMING_MMC_DDR100, MMC_SEND_TUNING_BLOCK_HS200)) + if (!sdmmc_tuning_execute(storage->sdmmc, SDHCI_TIMING_MMC_HS100, MMC_SEND_TUNING_BLOCK_HS200)) return 0; -DPRINTF("[gc] after tuning\n"); + DPRINTF("[GC] after tuning\n"); sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE); diff --git a/bdk/storage/sdmmc_driver.c b/bdk/storage/sdmmc_driver.c index e153805..27d25fe 100644 --- a/bdk/storage/sdmmc_driver.c +++ b/bdk/storage/sdmmc_driver.c @@ -34,9 +34,8 @@ //#define ERROR_EXTRA_PRINTING #define DPRINTF(...) -#ifdef BDK_SDMMC_OC_AND_EXTRA_PRINT +#ifdef BDK_SDMMC_EXTRA_PRINT #define ERROR_EXTRA_PRINTING -#define SDMMC_EMMC_OC #endif /*! SCMMC controller base addresses. */ @@ -109,13 +108,13 @@ void sdmmc_set_bus_width(sdmmc_t *sdmmc, u32 bus_width) void sdmmc_save_tap_value(sdmmc_t *sdmmc) { - sdmmc->venclkctl_tap = sdmmc->regs->venclkctl >> 16; + sdmmc->venclkctl_tap = (sdmmc->regs->venclkctl & 0xFF0000) >> 16; sdmmc->venclkctl_set = 1; } static int _sdmmc_config_tap_val(sdmmc_t *sdmmc, u32 type) { - const u32 dqs_trim_val = 0x28; + const u32 dqs_trim_val = 40; // 24 if HS533/HS667. const u8 tap_values_t210[4] = { 4, 0, 3, 0 }; u32 tap_val = 0; @@ -123,7 +122,7 @@ static int _sdmmc_config_tap_val(sdmmc_t *sdmmc, u32 type) if (type == SDHCI_TIMING_MMC_HS400) sdmmc->regs->vencapover = (sdmmc->regs->vencapover & 0xFFFFC0FF) | (dqs_trim_val << 8); - sdmmc->regs->ventunctl0 &= ~TEGRA_MMC_VNDR_TUN_CTRL0_TAP_VAL_UPDATED_BY_HW; + sdmmc->regs->ventunctl0 &= ~SDHCI_TEGRA_TUNING_TAP_HW_UPDATED; if (type == SDHCI_TIMING_MMC_HS400) { @@ -189,21 +188,21 @@ static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power) sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; } - // Enable E_INPUT power. - if (!(sdmmc->regs->sdmemcmppadctl & TEGRA_MMC_SDMEMCOMPPADCTRL_PAD_E_INPUT_PWRD)) + // Enable E_INPUT (SD) or Disable E_PWRD (eMMC) power. + if (!(sdmmc->regs->sdmemcmppadctl & SDHCI_TEGRA_PADCTRL_E_INPUT_PWRD)) { - sdmmc->regs->sdmemcmppadctl |= TEGRA_MMC_SDMEMCOMPPADCTRL_PAD_E_INPUT_PWRD; + sdmmc->regs->sdmemcmppadctl |= SDHCI_TEGRA_PADCTRL_E_INPUT_PWRD; _sdmmc_commit_changes(sdmmc); usleep(1); } // Enable auto calibration and start auto configuration. - sdmmc->regs->autocalcfg |= TEGRA_MMC_AUTOCALCFG_AUTO_CAL_ENABLE | TEGRA_MMC_AUTOCALCFG_AUTO_CAL_START; + sdmmc->regs->autocalcfg |= SDHCI_TEGRA_AUTOCAL_ENABLE | SDHCI_TEGRA_AUTOCAL_START; _sdmmc_commit_changes(sdmmc); usleep(2); u32 timeout = get_tmr_ms() + 10; - while (sdmmc->regs->autocalsts & TEGRA_MMC_AUTOCALSTS_AUTO_CAL_ACTIVE) + while (sdmmc->regs->autocalsts & SDHCI_TEGRA_AUTOCAL_ACTIVE) { if (get_tmr_ms() > timeout) { @@ -226,22 +225,18 @@ static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power) // In case auto calibration fails, we load suggested standard values. if (!timeout) { + sdmmc->regs->autocalcfg &= ~SDHCI_TEGRA_AUTOCAL_ENABLE; _sdmmc_pad_config_fallback(sdmmc, power); - sdmmc->regs->autocalcfg &= ~TEGRA_MMC_AUTOCALCFG_AUTO_CAL_ENABLE; } - // Disable E_INPUT to conserve power. - sdmmc->regs->sdmemcmppadctl &= ~TEGRA_MMC_SDMEMCOMPPADCTRL_PAD_E_INPUT_PWRD; + // Disable E_INPUT (SD) or enable E_PWRD (eMMC) to conserve power. + sdmmc->regs->sdmemcmppadctl &= ~SDHCI_TEGRA_PADCTRL_E_INPUT_PWRD; if (should_enable_sd_clock) sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; } -#ifdef SDMMC_EMMC_OC -static int _sdmmc_dll_cal_execute(sdmmc_t *sdmmc, bool overclock) -#else static int _sdmmc_dll_cal_execute(sdmmc_t *sdmmc) -#endif { int result = 1, should_disable_sd_clock = 0; @@ -251,17 +246,15 @@ static int _sdmmc_dll_cal_execute(sdmmc_t *sdmmc) sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; } -#ifdef SDMMC_EMMC_OC - // Add -4 TX_DLY_CODE_OFFSET if HS533. - if (sdmmc->id == SDMMC_4 && overclock) - sdmmc->regs->vendllcalcfg = sdmmc->regs->vendllcalcfg &= 0xFFFFC07F | (0x7C << 7); -#endif + // Add -4 TX_DLY_CODE_OFFSET if HS533/HS667. + // if (sdmmc->id == SDMMC_4 && sdmmc->card_clock > 208000) + // sdmmc->regs->vendllctl0 = sdmmc->regs->vendllctl0 &= 0xFFFFC07F | (0x7C << 7); - sdmmc->regs->vendllcalcfg |= TEGRA_MMC_DLLCAL_CFG_EN_CALIBRATE; + sdmmc->regs->vendllcalcfg |= SDHCI_TEGRA_DLLCAL_CALIBRATE; _sdmmc_commit_changes(sdmmc); u32 timeout = get_tmr_ms() + 5; - while (sdmmc->regs->vendllcalcfg & TEGRA_MMC_DLLCAL_CFG_EN_CALIBRATE) + while (sdmmc->regs->vendllcalcfg & SDHCI_TEGRA_DLLCAL_CALIBRATE) { if (get_tmr_ms() > timeout) { @@ -271,7 +264,7 @@ static int _sdmmc_dll_cal_execute(sdmmc_t *sdmmc) } timeout = get_tmr_ms() + 10; - while (sdmmc->regs->vendllcalcfgsts & TEGRA_MMC_DLLCAL_CFG_STATUS_DLL_ACTIVE) + while (sdmmc->regs->vendllcalcfgsts & SDHCI_TEGRA_DLLCAL_ACTIVE) { if (get_tmr_ms() > timeout) { @@ -286,7 +279,7 @@ out:; return result; } -static void _sdmmc_reset(sdmmc_t *sdmmc) +static void _sdmmc_reset_cmd_data(sdmmc_t *sdmmc) { sdmmc->regs->swrst |= SDHCI_RESET_CMD | SDHCI_RESET_DATA; _sdmmc_commit_changes(sdmmc); @@ -304,6 +297,13 @@ static void _sdmmc_reset_all(sdmmc_t *sdmmc) ; } +void sdmmc_setup_drv_type(sdmmc_t *sdmmc, u32 type) +{ + sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & (~SDHCI_CTRL_DRV_TYPE_MASK)) | SDHCI_CTRL_DRV_TYPE(type); + + _sdmmc_commit_changes(sdmmc); +} + int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type) { // Disable the SD clock if it was enabled, and reenable it later. @@ -316,7 +316,7 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type) _sdmmc_config_tap_val(sdmmc, type); - _sdmmc_reset(sdmmc); + _sdmmc_reset_cmd_data(sdmmc); switch (type) { @@ -330,22 +330,20 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type) case SDHCI_TIMING_MMC_HS52: case SDHCI_TIMING_SD_HS25: - sdmmc->regs->hostctl |= SDHCI_CTRL_HISPD; // SD only? + sdmmc->regs->hostctl |= SDHCI_CTRL_HISPD; sdmmc->regs->hostctl2 &= ~SDHCI_CTRL_VDD_180; break; case SDHCI_TIMING_MMC_HS200: - case SDHCI_TIMING_UHS_SDR50: // T210 Errata for SDR50, the host must be set to SDR104. + case SDHCI_TIMING_UHS_SDR50: // T210 Errata: the host must be set to SDR104 to WAR a CRC issue. case SDHCI_TIMING_UHS_SDR104: case SDHCI_TIMING_UHS_SDR82: - case SDHCI_TIMING_UHS_DDR50: - case SDHCI_TIMING_MMC_DDR100: + case SDHCI_TIMING_MMC_HS100: sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & (~SDHCI_CTRL_UHS_MASK)) | UHS_SDR104_BUS_SPEED; sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180; break; case SDHCI_TIMING_MMC_HS400: - // Non standard. sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & (~SDHCI_CTRL_UHS_MASK)) | HS400_BUS_SPEED; sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180; break; @@ -359,6 +357,14 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type) sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & (~SDHCI_CTRL_UHS_MASK)) | UHS_SDR12_BUS_SPEED; sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180; break; + + case SDHCI_TIMING_UHS_DDR50: +#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT + case SDHCI_TIMING_UHS_DDR200: +#endif + sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & (~SDHCI_CTRL_UHS_MASK)) | UHS_DDR50_BUS_SPEED; + sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180; + break; } _sdmmc_commit_changes(sdmmc); @@ -367,31 +373,24 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type) u16 divisor; clock_sdmmc_get_card_clock_div(&clock, &divisor, type); clock_sdmmc_config_clock_source(&clock, sdmmc->id, clock); - sdmmc->divisor = (clock + divisor - 1) / divisor; + sdmmc->card_clock = (clock + divisor - 1) / divisor; //if divisor != 1 && divisor << 31 -> error - u16 div = divisor >> 1; - divisor = 0; - if (div > 0xFF) - divisor = div >> SDHCI_DIVIDER_SHIFT; + u16 div_lo = divisor >> 1; + u16 div_hi = 0; + if (div_lo > 0xFF) + div_hi = div_lo >> SDHCI_DIV_LO_SHIFT; - sdmmc->regs->clkcon = (sdmmc->regs->clkcon & ~(SDHCI_DIV_MASK | SDHCI_DIV_HI_MASK)) - | (div << SDHCI_DIVIDER_SHIFT) | (divisor << SDHCI_DIVIDER_HI_SHIFT); + sdmmc->regs->clkcon = (sdmmc->regs->clkcon & ~(SDHCI_DIV_MASK | SDHCI_DIV_HI_MASK)) | + (div_lo << SDHCI_DIV_LO_SHIFT) | (div_hi << SDHCI_DIV_HI_SHIFT); // Enable the SD clock again. if (should_enable_sd_clock) sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; if (type == SDHCI_TIMING_MMC_HS400) - { -#ifdef SDMMC_EMMC_OC - bool overclock_en = clock > 208000; - return _sdmmc_dll_cal_execute(sdmmc, overclock_en); -#else return _sdmmc_dll_cal_execute(sdmmc); -#endif - } return 1; } @@ -524,7 +523,7 @@ static int _sdmmc_wait_cmd_data_inhibit(sdmmc_t *sdmmc, bool wait_dat) while (sdmmc->regs->prnsts & SDHCI_CMD_INHIBIT) if (get_tmr_ms() > timeout) { - _sdmmc_reset(sdmmc); + _sdmmc_reset_cmd_data(sdmmc); return 0; } @@ -534,7 +533,7 @@ static int _sdmmc_wait_cmd_data_inhibit(sdmmc_t *sdmmc, bool wait_dat) while (sdmmc->regs->prnsts & SDHCI_DATA_INHIBIT) if (get_tmr_ms() > timeout) { - _sdmmc_reset(sdmmc); + _sdmmc_reset_cmd_data(sdmmc); return 0; } } @@ -550,7 +549,7 @@ static int _sdmmc_wait_card_busy(sdmmc_t *sdmmc) while (!(sdmmc->regs->prnsts & SDHCI_DATA_0_LVL)) if (get_tmr_ms() > timeout) { - _sdmmc_reset(sdmmc); + _sdmmc_reset_cmd_data(sdmmc); return 0; } @@ -611,8 +610,9 @@ static int _sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, bool is_data_presen if (is_data_present) cmdflags |= SDHCI_CMD_DATA; + sdmmc->regs->argument = cmd->arg; - sdmmc->regs->cmdreg = (cmd->cmd << 8) | cmdflags; + sdmmc->regs->cmdreg = SDHCI_CMD_IDX(cmd->cmd) | cmdflags; return 1; } @@ -627,10 +627,8 @@ static void _sdmmc_send_tuning_cmd(sdmmc_t *sdmmc, u32 cmd) _sdmmc_send_cmd(sdmmc, &cmdbuf, true); } -static int _sdmmc_tuning_execute_once(sdmmc_t *sdmmc, u32 cmd) +static int _sdmmc_tuning_execute_once(sdmmc_t *sdmmc, u32 cmd, u32 tap) { - if (sdmmc->powersave_enabled) - return 0; if (!_sdmmc_wait_cmd_data_inhibit(sdmmc, true)) return 0; @@ -640,11 +638,21 @@ static int _sdmmc_tuning_execute_once(sdmmc_t *sdmmc, u32 cmd) sdmmc->regs->norintsts = sdmmc->regs->norintsts; sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; +#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT + // Set tap if manual tuning. + if (tap != HW_TAP_TUNING) + { + sdmmc->regs->ventunctl0 &= ~SDHCI_TEGRA_TUNING_TAP_HW_UPDATED; + sdmmc->regs->venclkctl = (sdmmc->regs->venclkctl & 0xFF00FFFF) | (tap << 16); + sdmmc->regs->ventunctl0 |= SDHCI_TEGRA_TUNING_TAP_HW_UPDATED; + } +#endif + _sdmmc_send_tuning_cmd(sdmmc, cmd); _sdmmc_commit_changes(sdmmc); usleep(1); - _sdmmc_reset(sdmmc); + _sdmmc_reset_cmd_data(sdmmc); sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; _sdmmc_commit_changes(sdmmc); @@ -657,59 +665,167 @@ static int _sdmmc_tuning_execute_once(sdmmc_t *sdmmc, u32 cmd) sdmmc->regs->norintsts = SDHCI_INT_DATA_AVAIL; sdmmc->regs->norintstsen &= ~SDHCI_INT_DATA_AVAIL; _sdmmc_commit_changes(sdmmc); - usleep((1000 * 8 + sdmmc->divisor - 1) / sdmmc->divisor); + usleep((8 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock); // Wait 8 cycles. return 1; } } - _sdmmc_reset(sdmmc); + _sdmmc_reset_cmd_data(sdmmc); sdmmc->regs->norintstsen &= ~SDHCI_INT_DATA_AVAIL; _sdmmc_commit_changes(sdmmc); - usleep((1000 * 8 + sdmmc->divisor - 1) / sdmmc->divisor); + usleep((8 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock); // Wait 8 cycles. return 0; } +#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT +typedef struct _sdmmc_manual_tuning_t +{ + u32 result[8]; + u32 num_iter; + u32 tap_start; + u32 tap_end; +} sdmmc_manual_tuning_t; + +static int _sdmmc_manual_tuning_set_tap(sdmmc_t *sdmmc, sdmmc_manual_tuning_t *tuning) +{ + u32 tap_start = INVALID_TAP; + u32 win_size = 0; + u32 best_tap = 0; + u32 best_size = 0; + + for (u32 i = 0; i < tuning->num_iter; i++) + { + u32 iter_end = i == (tuning->num_iter - 1) ? 1 : 0; + u32 stable = tuning->result[i / 32] & BIT(i % 32); + if (stable && !iter_end) + { + if (tap_start == INVALID_TAP) + tap_start = i; + + win_size++; + } + else + { + if (tap_start != INVALID_TAP) + { + u32 tap_end = !iter_end ? (i - 1) : i; + + // Check if window is wider. + if (win_size > best_size) + { + best_tap = (tap_start + tap_end) / 2; + best_size = win_size + iter_end; + + } + + tap_start = INVALID_TAP; + win_size = 0; + } + } + } + + // Check if failed. + if (!best_tap) + return 0; + + sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; + sdmmc->regs->ventunctl0 &= ~SDHCI_TEGRA_TUNING_TAP_HW_UPDATED; + + // Set tap. + sdmmc->regs->venclkctl = (sdmmc->regs->venclkctl & 0xFF00FFFF) | (best_tap << 16); + + sdmmc->regs->ventunctl0 |= SDHCI_TEGRA_TUNING_TAP_HW_UPDATED; + sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; + + return 1; +} + +/* + * SD Card DDR200 (DDR208) support + * + * On Tegra X1, that can be done with DDR50 host mode. + * Tuning though can't be done automatically on any DDR mode. + * So it needs to be done manually and selected tap will be applied from the biggest + * sampling window. + */ +static int sdmmc_tuning_execute_ddr200(sdmmc_t *sdmmc) +{ + sdmmc_manual_tuning_t manual_tuning = { 0 }; + manual_tuning.num_iter = 128; + + sdmmc->regs->ventunctl1 = 0; // step_size 1. + sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFF1FFF) | (2 << 13); // 128 Tries. + sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFFE03F) | (1 << 6); // 1x Multiplier. + sdmmc->regs->ventunctl0 |= SDHCI_TEGRA_TUNING_TAP_HW_UPDATED; + + sdmmc->regs->hostctl2 |= SDHCI_CTRL_EXEC_TUNING; + + for (u32 i = 0; i < manual_tuning.num_iter; i++) + { + _sdmmc_tuning_execute_once(sdmmc, MMC_SEND_TUNING_BLOCK, i); + + // Save result for manual tuning. + int sampled = (sdmmc->regs->hostctl2 >> SDHCI_CTRL_TUNED_CLK_SHIFT) & 1; + manual_tuning.result[i / 32] |= sampled << (i % 32); + + if (!(sdmmc->regs->hostctl2 & SDHCI_CTRL_EXEC_TUNING)) + break; + } + + return _sdmmc_manual_tuning_set_tap(sdmmc, &manual_tuning); +} +#endif + int sdmmc_tuning_execute(sdmmc_t *sdmmc, u32 type, u32 cmd) { - u32 max = 0, flag = 0; + u32 num_iter, flag; + + if (sdmmc->powersave_enabled) + return 0; switch (type) { case SDHCI_TIMING_MMC_HS200: - case SDHCI_TIMING_MMC_HS400: case SDHCI_TIMING_UHS_SDR104: case SDHCI_TIMING_UHS_SDR82: - max = 128; + num_iter = 128; flag = (2 << 13); // 128 iterations. break; case SDHCI_TIMING_UHS_SDR50: - case SDHCI_TIMING_UHS_DDR50: - case SDHCI_TIMING_MMC_DDR100: - max = 256; + case SDHCI_TIMING_UHS_DDR50: // HW tuning is not supported on DDR modes. But it sets tap to 0 which is proper. + case SDHCI_TIMING_MMC_HS100: + num_iter = 256; flag = (4 << 13); // 256 iterations. break; + case SDHCI_TIMING_MMC_HS400: case SDHCI_TIMING_UHS_SDR12: case SDHCI_TIMING_UHS_SDR25: return 1; +#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT + case SDHCI_TIMING_UHS_DDR200: + return sdmmc_tuning_execute_ddr200(sdmmc); +#endif + default: return 0; } - sdmmc->regs->ventunctl1 = 0; // step_size 1. + sdmmc->regs->ventunctl1 = 0; // step_size 1. + sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFF1FFF) | flag; // Tries. + sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFFE03F) | (1 << 6); // 1x Multiplier. + sdmmc->regs->ventunctl0 |= SDHCI_TEGRA_TUNING_TAP_HW_UPDATED; - sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFF1FFF) | flag; // Tries. - sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFFE03F) | (1 << 6); // 1x Multiplier. - sdmmc->regs->ventunctl0 |= TEGRA_MMC_VNDR_TUN_CTRL0_TAP_VAL_UPDATED_BY_HW; sdmmc->regs->hostctl2 |= SDHCI_CTRL_EXEC_TUNING; - for (u32 i = 0; i < max; i++) + for (u32 i = 0; i < num_iter; i++) { - _sdmmc_tuning_execute_once(sdmmc, cmd); + _sdmmc_tuning_execute_once(sdmmc, cmd, HW_TAP_TUNING); + if (!(sdmmc->regs->hostctl2 & SDHCI_CTRL_EXEC_TUNING)) break; } @@ -737,7 +853,7 @@ static int _sdmmc_enable_internal_clock(sdmmc_t *sdmmc) // Enable 32bit addressing if used (sysad. if blkcnt it fallbacks to 16bit). sdmmc->regs->hostctl2 |= SDHCI_HOST_VERSION_4_EN; - if (!(sdmmc->regs->capareg & SDHCI_CAN_64BIT)) + if (!(sdmmc->regs->capareg & SDHCI_CAP_64BIT)) return 0; sdmmc->regs->hostctl2 |= SDHCI_ADDRESSING_64BIT_EN; @@ -767,8 +883,8 @@ static int _sdmmc_autocal_config_offset(sdmmc_t *sdmmc, u32 power) { if (!sdmmc->t210b01) { - off_pd = 123; - off_pu = 123; + off_pd = 0x7B; // -5. + off_pu = 0x7B; // -5. } else { @@ -780,7 +896,7 @@ static int _sdmmc_autocal_config_offset(sdmmc_t *sdmmc, u32 power) { if (!sdmmc->t210b01) { - off_pd = 125; + off_pd = 0x7D; // -3. off_pu = 0; } } @@ -812,7 +928,7 @@ static u32 _sdmmc_check_mask_interrupt(sdmmc_t *sdmmc, u16 *pout, u16 mask) u16 norintsts = sdmmc->regs->norintsts; u16 errintsts = sdmmc->regs->errintsts; -DPRINTF("norintsts %08X, errintsts %08X\n", norintsts, errintsts); + DPRINTF("norintsts %08X, errintsts %08X\n", norintsts, errintsts); if (pout) *pout = norintsts; @@ -847,7 +963,7 @@ static int _sdmmc_wait_response(sdmmc_t *sdmmc) break; if (result != SDMMC_MASKINT_NOERROR || get_tmr_ms() > timeout) { - _sdmmc_reset(sdmmc); + _sdmmc_reset_cmd_data(sdmmc); return 0; } } @@ -897,11 +1013,11 @@ int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp) should_disable_sd_clock = true; sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; _sdmmc_commit_changes(sdmmc); - usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor); + usleep((8 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock); // Wait 8 cycles. } int result = _sdmmc_stop_transmission_inner(sdmmc, rsp); - usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor); + usleep((8 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock); // Wait 8 cycles. if (should_disable_sd_clock) sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; @@ -934,9 +1050,9 @@ static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req) if (blkcnt_out) *blkcnt_out = blkcnt; - u32 trnmode = SDHCI_TRNS_DMA; + u32 trnmode = SDHCI_TRNS_DMA | SDHCI_TRNS_RTYPE_R1; - // Set mulitblock request. + // Set multiblock request. if (req->is_multi_block) trnmode |= SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN; @@ -988,15 +1104,17 @@ static int _sdmmc_update_dma(sdmmc_t *sdmmc) if (result != SDMMC_MASKINT_NOERROR) { #ifdef ERROR_EXTRA_PRINTING - EPRINTFARGS("SDMMC%d: %08X!", sdmmc->id + 1, result); + EPRINTFARGS("SDMMC%d: int error!", sdmmc->id + 1); #endif - _sdmmc_reset(sdmmc); + _sdmmc_reset_cmd_data(sdmmc); + return 0; } } while (get_tmr_ms() < timeout); } while (sdmmc->regs->blkcnt != blkcnt); - _sdmmc_reset(sdmmc); + _sdmmc_reset_cmd_data(sdmmc); + return 0; } @@ -1039,7 +1157,7 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_ if (!result) EPRINTFARGS("SDMMC%d: Transfer timeout!", sdmmc->id + 1); #endif -DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result, + DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result, sdmmc->regs->rspreg0, sdmmc->regs->rspreg1, sdmmc->regs->rspreg2, sdmmc->regs->rspreg3); if (result) { @@ -1171,6 +1289,7 @@ static int _sdmmc_config_sdmmc1(bool t210b01) APB_MISC(APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL) = 1; // Configure SDMMC1 CLK pinmux, based on state and SoC type. + PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) &= ~PINMUX_SCHMT; if (PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) != (PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PULL_DOWN)) // Check if CLK pad is already configured. PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | (t210b01 ? PINMUX_PULL_NONE : PINMUX_PULL_DOWN); @@ -1244,7 +1363,7 @@ static void _sdmmc_config_emmc(u32 id, bool t210b01) } } -int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int powersave_enable) +int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type) { u32 clock; u16 divisor; @@ -1301,11 +1420,10 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int p sdmmc->clock_stopped = 0; // Set default pad IO trimming configuration. - sdmmc->regs->iospare |= 0x80000; // Enable muxing. - sdmmc->regs->veniotrimctl &= 0xFFFFFFFB; // Set Band Gap VREG to supply DLL. + sdmmc->regs->iospare |= BIT(19); // Enable 1 cycle delayed cmd_oen. + sdmmc->regs->veniotrimctl &= ~BIT(2); // Set Band Gap VREG to supply DLL. sdmmc->regs->venclkctl = (sdmmc->regs->venclkctl & 0xE0FFFFFB) | ((u32)trim_values[sdmmc->id] << 24); - sdmmc->regs->sdmemcmppadctl = - (sdmmc->regs->sdmemcmppadctl & TEGRA_MMC_SDMEMCOMPPADCTRL_COMP_VREF_SEL_MASK) | vref_sel; + sdmmc->regs->sdmemcmppadctl = (sdmmc->regs->sdmemcmppadctl & ~SDHCI_TEGRA_PADCTRL_VREF_SEL_MASK) | vref_sel; // Configure auto calibration values. if (!_sdmmc_autocal_config_offset(sdmmc, power)) @@ -1322,7 +1440,7 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int p if (sdmmc_setup_clock(sdmmc, type)) { - sdmmc_card_clock_powersave(sdmmc, powersave_enable); + sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_DISABLE); _sdmmc_card_clock_enable(sdmmc); _sdmmc_commit_changes(sdmmc); @@ -1408,11 +1526,11 @@ int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *b should_disable_sd_clock = 1; sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; _sdmmc_commit_changes(sdmmc); - usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor); + usleep((8 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock); // Wait 8 cycles. } int result = _sdmmc_execute_cmd_inner(sdmmc, cmd, req, blkcnt_out); - usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor); + usleep((8 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock); // Wait 8 cycles. if (should_disable_sd_clock) sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; @@ -1425,9 +1543,6 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc) if (sdmmc->id != SDMMC_1) return 0; - if (!sdmmc_setup_clock(sdmmc, SDHCI_TIMING_UHS_SDR12)) - return 0; - _sdmmc_commit_changes(sdmmc); // Switch to 1.8V and wait for regulator to stabilize. Assume max possible wait needed. diff --git a/bdk/storage/sdmmc_driver.h b/bdk/storage/sdmmc_driver.h index 43263b8..bbef04e 100644 --- a/bdk/storage/sdmmc_driver.h +++ b/bdk/storage/sdmmc_driver.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2022 CTCaer + * Copyright (c) 2018-2023 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,6 @@ #define SDMMC_POWER_1_8 1 #define SDMMC_POWER_3_3 2 -/*! SDMMC bus widths. */ -#define SDMMC_BUS_WIDTH_1 0 -#define SDMMC_BUS_WIDTH_4 1 -#define SDMMC_BUS_WIDTH_8 2 - /*! SDMMC response types. */ #define SDMMC_RSP_TYPE_0 0 #define SDMMC_RSP_TYPE_1 1 @@ -45,25 +40,30 @@ #define SDMMC_RSP_TYPE_4 4 #define SDMMC_RSP_TYPE_5 5 +/*! SDMMC bus widths. */ +#define SDMMC_BUS_WIDTH_1 0 +#define SDMMC_BUS_WIDTH_4 1 +#define SDMMC_BUS_WIDTH_8 2 + /*! SDMMC mask interrupt status. */ #define SDMMC_MASKINT_MASKED 0 #define SDMMC_MASKINT_NOERROR 1 #define SDMMC_MASKINT_ERROR 2 -/*! SDMMC present state. */ +/*! SDMMC present state. 0x24. */ #define SDHCI_CMD_INHIBIT BIT(0) #define SDHCI_DATA_INHIBIT BIT(1) #define SDHCI_DAT_LINE_ACTIVE BIT(2) #define SDHCI_RETUNING_REQUEST BIT(3) -#define SDHCI_EMMC_LINE_LVL_MASK 0xF0 -#define SDHCI_DATA_4_LVL BIT(4) // eMMC only. -#define SDHCI_DATA_5_LVL BIT(5) // eMMC only. -#define SDHCI_DATA_6_LVL BIT(6) // eMMC only. -#define SDHCI_DATA_7_LVL BIT(7) // eMMC only. +#define SDHCI_EMMC_LINE_LVL_MASK (0xFU << 4) +#define SDHCI_DATA_4_LVL BIT(4) // eMMC only. +#define SDHCI_DATA_5_LVL BIT(5) // eMMC only. +#define SDHCI_DATA_6_LVL BIT(6) // eMMC only. +#define SDHCI_DATA_7_LVL BIT(7) // eMMC only. #define SDHCI_DOING_WRITE BIT(8) -#define SDHCI_DOING_READ BIT(9) // SD only. -#define SDHCI_SPACE_AVAILABLE BIT(10) -#define SDHCI_DATA_AVAILABLE BIT(11) +#define SDHCI_DOING_READ BIT(9) // SD only. +#define SDHCI_SPACE_AVAILABLE BIT(10) // Write buffer empty. +#define SDHCI_DATA_AVAILABLE BIT(11) // Read buffer has data. #define SDHCI_CARD_PRESENT BIT(16) #define SDHCI_CD_STABLE BIT(17) #define SDHCI_CD_LVL BIT(18) @@ -74,18 +74,21 @@ #define SDHCI_DATA_2_LVL BIT(22) #define SDHCI_DATA_3_LVL BIT(23) #define SDHCI_CMD_LVL BIT(24) -#define SDHCI_CMD_NOT_ISSUED BIT(27) -/*! SDMMC transfer mode. */ -#define SDHCI_TRNS_DMA BIT(0) -#define SDHCI_TRNS_BLK_CNT_EN BIT(1) -#define SDHCI_TRNS_AUTO_CMD12 BIT(2) -#define SDHCI_TRNS_AUTO_CMD23 BIT(3) -#define SDHCI_TRNS_WRITE 0x00 // Bit4. -#define SDHCI_TRNS_READ BIT(4) -#define SDHCI_TRNS_MULTI BIT(5) +/*! SDMMC transfer mode. 0x0C. */ +#define SDHCI_TRNS_DMA BIT(0) +#define SDHCI_TRNS_BLK_CNT_EN BIT(1) +#define SDHCI_TRNS_AUTO_CMD12 (1U << 2) +#define SDHCI_TRNS_AUTO_CMD23 (2U << 2) +#define SDHCI_TRNS_WRITE (0U << 4) +#define SDHCI_TRNS_READ BIT(4) +#define SDHCI_TRNS_MULTI BIT(5) +#define SDHCI_TRNS_RTYPE_R1 (0U << 6) +#define SDHCI_TRNS_RTYPE_R5 BIT(6) +#define SDHCI_TRNS_RSP_ERR_CHK BIT(7) +#define SDHCI_TRNS_RSP_INT_DIS BIT(8) -/*! SDMMC command. */ +/*! SDMMC command. 0x0E. */ #define SDHCI_CMD_RESP_MASK 0x3 #define SDHCI_CMD_RESP_NO_RESP 0x0 #define SDHCI_CMD_RESP_LEN136 0x1 @@ -94,77 +97,79 @@ #define SDHCI_CMD_CRC BIT(3) #define SDHCI_CMD_INDEX BIT(4) #define SDHCI_CMD_DATA BIT(5) -#define SDHCI_CMD_ABORTCMD 0xC0 +#define SDHCI_CMD_TYPE_NORMAL (0U << 6) +#define SDHCI_CMD_TYPE_SUSPEND (1U << 6) +#define SDHCI_CMD_TYPE_RESUME (2U << 6) +#define SDHCI_CMD_TYPE_ABORT (3U << 6) +#define SDHCI_CMD_IDX(cmd) ((cmd) << 8) -/*! SDMMC host control. */ + +/*! SDMMC host control. 0x28. */ #define SDHCI_CTRL_LED BIT(0) #define SDHCI_CTRL_4BITBUS BIT(1) // SD only. #define SDHCI_CTRL_HISPD BIT(2) // SD only. -#define SDHCI_CTRL_DMA_MASK 0x18 -#define SDHCI_CTRL_SDMA 0x00 -#define SDHCI_CTRL_ADMA1 0x08 -#define SDHCI_CTRL_ADMA32 0x10 -#define SDHCI_CTRL_ADMA64 0x18 +#define SDHCI_CTRL_DMA_MASK (3U << 3) +#define SDHCI_CTRL_SDMA (0U << 3) +#define SDHCI_CTRL_ADMA1 (1U << 3) +#define SDHCI_CTRL_ADMA32 (2U << 3) +#define SDHCI_CTRL_ADMA64 (3U << 3) #define SDHCI_CTRL_8BITBUS BIT(5) // eMMC only (or UHS-II). #define SDHCI_CTRL_CDTEST_INS BIT(6) #define SDHCI_CTRL_CDTEST_EN BIT(7) -/*! SDMMC host control 2. */ -#define SDHCI_CTRL_UHS_MASK 0x7 -#define SDHCI_CTRL_VDD_180 BIT(3) -#define SDHCI_CTRL_DRV_TYPE_B (0U << 4) -#define SDHCI_CTRL_DRV_TYPE_A (1U << 4) -#define SDHCI_CTRL_DRV_TYPE_C (2U << 4) -#define SDHCI_CTRL_DRV_TYPE_D (3U << 4) -#define SDHCI_CTRL_EXEC_TUNING BIT(6) -#define SDHCI_CTRL_TUNED_CLK BIT(7) -#define SDHCI_HOST_VERSION_4_EN BIT(12) -#define SDHCI_ADDRESSING_64BIT_EN BIT(13) -#define SDHCI_CTRL_PRESET_VAL_EN BIT(15) +/*! SDMMC host control 2. 0x3E. */ +#define SDHCI_CTRL_UHS_MASK 0x7 +#define SDHCI_CTRL_VDD_180 BIT(3) +#define SDHCI_CTRL_DRV_TYPE_MASK (3U << 4) +#define SDHCI_CTRL_DRV_TYPE_B (0U << 4) +#define SDHCI_CTRL_DRV_TYPE_A (1U << 4) +#define SDHCI_CTRL_DRV_TYPE_C (2U << 4) +#define SDHCI_CTRL_DRV_TYPE_D (3U << 4) +#define SDHCI_CTRL_DRV_TYPE(type) ((type) << 4) +#define SDHCI_CTRL_EXEC_TUNING BIT(6) +#define SDHCI_CTRL_TUNED_CLK_SHIFT 7 +#define SDHCI_CTRL_TUNED_CLK BIT(7) +#define SDHCI_HOST_VERSION_4_EN BIT(12) +#define SDHCI_ADDRESSING_64BIT_EN BIT(13) +#define SDHCI_CTRL_PRESET_VAL_EN BIT(15) -/*! SDMMC power control. */ +/*! SDMMC power control. 0x29. */ #define SDHCI_POWER_ON BIT(0) -#define SDHCI_POWER_180 0x0A -#define SDHCI_POWER_300 0x0C -#define SDHCI_POWER_330 0x0E +#define SDHCI_POWER_180 (5U << 1) +#define SDHCI_POWER_300 (6U << 1) +#define SDHCI_POWER_330 (7U << 1) #define SDHCI_POWER_MASK 0xF1 // UHS-II only. -// /*! SDMMC max current. */ -// #define SDHCI_MAX_CURRENT_330_MASK 0xFF -// #define SDHCI_MAX_CURRENT_180_MASK 0xFF0000 -// #define SDHCI_MAX_CURRENT_MULTIPLIER 4 - -/*! SDMMC clock control. */ -#define SDHCI_CLOCK_INT_EN BIT(0) -#define SDHCI_CLOCK_INT_STABLE BIT(1) +/*! SDMMC clock control. 0x2C. */ +#define SDHCI_CLOCK_INT_EN BIT(0) // Internal Clock. +#define SDHCI_CLOCK_INT_STABLE BIT(1) // Internal Clock Stable. #define SDHCI_CLOCK_CARD_EN BIT(2) #define SDHCI_PROG_CLOCK_MODE BIT(5) -#define SDHCI_DIVIDER_HI_SHIFT 6 -#define SDHCI_DIV_HI_MASK (3U << SDHCI_DIVIDER_HI_SHIFT) -#define SDHCI_DIVIDER_SHIFT 8 -#define SDHCI_DIV_MASK (0xFFU << SDHCI_DIVIDER_SHIFT) +#define SDHCI_DIV_HI_SHIFT 6 +#define SDHCI_DIV_HI_MASK (3U << SDHCI_DIV_HI_SHIFT) +#define SDHCI_DIV_LO_SHIFT 8 +#define SDHCI_DIV_MASK (0xFFU << SDHCI_DIV_LO_SHIFT) -/*! SDMMC software reset. */ +/*! SDMMC software reset. 0x2F. */ #define SDHCI_RESET_ALL BIT(0) #define SDHCI_RESET_CMD BIT(1) #define SDHCI_RESET_DATA BIT(2) -/*! SDMMC interrupt status and control. */ +/*! SDMMC interrupt status and control. 0x30/0x34. */ #define SDHCI_INT_RESPONSE BIT(0) #define SDHCI_INT_DATA_END BIT(1) #define SDHCI_INT_BLK_GAP BIT(2) #define SDHCI_INT_DMA_END BIT(3) -#define SDHCI_INT_SPACE_AVAIL BIT(4) -#define SDHCI_INT_DATA_AVAIL BIT(5) +#define SDHCI_INT_SPACE_AVAIL BIT(4) // Write buffer empty. +#define SDHCI_INT_DATA_AVAIL BIT(5) // Read buffer has data. #define SDHCI_INT_CARD_INSERT BIT(6) #define SDHCI_INT_CARD_REMOVE BIT(7) #define SDHCI_INT_CARD_INT BIT(8) #define SDHCI_INT_RETUNE BIT(12) -#define SDHCI_INT_CQE BIT(14) #define SDHCI_INT_ERROR BIT(15) -/*! SDMMC error interrupt status and control. */ +/*! SDMMC error interrupt status and control. 0x32/0x36. */ #define SDHCI_ERR_INT_TIMEOUT BIT(0) #define SDHCI_ERR_INT_CRC BIT(1) #define SDHCI_ERR_INT_END_BIT BIT(2) @@ -173,16 +178,65 @@ #define SDHCI_ERR_INT_DATA_CRC BIT(5) #define SDHCI_ERR_INT_DATA_END_BIT BIT(6) #define SDHCI_ERR_INT_BUS_POWER BIT(7) -#define SDHCI_ERR_INT_AUTO_CMD_ERR BIT(8) -#define SDHCI_ERR_INT_ADMA_ERROR BIT(9) -#define SDHCI_ERR_INT_TUNE_ERROR BIT(10) -#define SDHCI_ERR_INT_RSP_ERROR BIT(11) +#define SDHCI_ERR_INT_AUTO_CMD12 BIT(8) +#define SDHCI_ERR_INT_ADMA BIT(9) +#define SDHCI_ERR_INT_TUNE BIT(10) +#define SDHCI_ERR_INT_RSP BIT(11) +#define SDHCI_ERR_INT_TARGET_RSP BIT(12) +#define SDHCI_ERR_INT_SPI BIT(13) +#define SDHCI_ERR_INT_VND_BOOT_TMO BIT(14) +#define SDHCI_ERR_INT_VND_BOOT_ACK BIT(15) #define SDHCI_ERR_INT_ALL_EXCEPT_ADMA_BUSPWR \ - (SDHCI_ERR_INT_AUTO_CMD_ERR | SDHCI_ERR_INT_DATA_END_BIT | \ - SDHCI_ERR_INT_DATA_CRC | SDHCI_ERR_INT_DATA_TIMEOUT | \ - SDHCI_ERR_INT_INDEX | SDHCI_ERR_INT_END_BIT | \ - SDHCI_ERR_INT_CRC | SDHCI_ERR_INT_TIMEOUT) + (SDHCI_ERR_INT_AUTO_CMD12 | SDHCI_ERR_INT_DATA_END_BIT | \ + SDHCI_ERR_INT_DATA_CRC | SDHCI_ERR_INT_DATA_TIMEOUT | \ + SDHCI_ERR_INT_INDEX | SDHCI_ERR_INT_END_BIT | \ + SDHCI_ERR_INT_CRC | SDHCI_ERR_INT_TIMEOUT) + +/*! Host Capability 1. 0x40. */ +#define SDHCI_CAP_TM_CLK_FREQ_MASK 0x3F +#define SDHCI_CAP_TM_UNIT_MHZ BIT(7) +#define SDHCI_CAP_BASE_CLK_FREQ_MASK (0xFFU << 8) +#define SDHCI_CAP_MAX_BLK_LEN_MASK (3U << 16) +#define SDHCI_CAP_EMMC_8BIT BIT(18) +#define SDHCI_CAP_ADMA2 BIT(19) +#define SDHCI_CAP_HISPD BIT(21) +#define SDHCI_CAP_SDMA BIT(22) +#define SDHCI_CAP_SUSPEND_RESUME BIT(23) +#define SDHCI_CAP_3_3_V BIT(24) +#define SDHCI_CAP_3_0_V BIT(25) +#define SDHCI_CAP_1_8_V BIT(26) +#define SDHCI_CAP_64BIT BIT(28) +#define SDHCI_CAP_ASYNC_INT BIT(29) +#define SDHCI_CAP_SLOT_TYPE_MASK (3U << 30) +#define SDHCI_CAP_SLOT_TYPE_REMOVABLE (0U << 30) +#define SDHCI_CAP_SLOT_TYPE_EMBEDDED (1U << 30) +#define SDHCI_CAP_SLOT_TYPE_SHARED (2U << 30) +#define SDHCI_CAP_SLOT_TYPE_UHS2 (3U << 30) + +/*! Host Capability 2. 0x44. */ +#define SDHCI_CAP_SDR50 BIT(0) +#define SDHCI_CAP_SDR5104 BIT(1) +#define SDHCI_CAP_DDR50 BIT(2) +#define SDHCI_CAP_UHS2 BIT(3) +#define SDHCI_CAP_DRV_TYPE_A BIT(4) +#define SDHCI_CAP_DRV_TYPE_C BIT(5) +#define SDHCI_CAP_DRV_TYPE_D BIT(6) +#define SDHCI_CAP_RSP_TIMER_CNT_MASK (0xFU << 8) +#define SDHCI_CAP_SDR50_TUNING BIT(13) +#define SDHCI_CAP_RSP_MODES_MASK (3U << 14) +#define SDHCI_CAP_CLK_MULT (0xFFU << 16) +#define SDHCI_CAP_ADMA3 BIT(27) +#define SDHCI_CAP_VDD2_1_8V BIT(28) + +/*! SDMMC max current. 0x48 */ +#define SDHCI_MAX_CURRENT_3_3_V_MASK (0xFFU << 0) +#define SDHCI_MAX_CURRENT_3_0_V_MASK (0xFFU << 8) +#define SDHCI_MAX_CURRENT_1_8_V_MASK (0xFFU << 16) +#define SDHCI_MAX_CURRENT_MULTIPLIER 4 + +/*! SDMMC max current. 0x4C */ +#define SDHCI_MAX_CURRENT_1_8_V_VDD2_MASK (0xFFU << 0) /*! SD bus speeds. */ #define UHS_SDR12_BUS_SPEED 0 @@ -209,9 +263,8 @@ #define SDHCI_TIMING_UHS_DDR50 12 // SDR104 with a 163.2MHz -> 81.6MHz clock. #define SDHCI_TIMING_UHS_SDR82 13 // GC FPGA. Obsolete and Repurposed. MMC_HS50 -> SDR82. -#define SDHCI_TIMING_MMC_DDR100 14 // GC ASIC. - -#define SDHCI_CAN_64BIT BIT(28) +#define SDHCI_TIMING_MMC_HS100 14 // GC ASIC. +#define SDHCI_TIMING_UHS_DDR200 15 /*! SDMMC Low power features. */ #define SDMMC_POWER_SAVE_DISABLE 0 @@ -220,12 +273,15 @@ /*! Helper for SWITCH command argument. */ #define SDMMC_SWITCH(mode, index, value) (((mode) << 24) | ((index) << 16) | ((value) << 8)) +#define HW_TAP_TUNING 0x100 +#define INVALID_TAP 0x100 + /*! SDMMC controller context. */ typedef struct _sdmmc_t { t210_sdmmc_t *regs; u32 id; - u32 divisor; + u32 card_clock; u32 clock_stopped; int powersave_enabled; int manual_cal; @@ -263,13 +319,14 @@ int sdmmc_get_io_power(sdmmc_t *sdmmc); u32 sdmmc_get_bus_width(sdmmc_t *sdmmc); void sdmmc_set_bus_width(sdmmc_t *sdmmc, u32 bus_width); void sdmmc_save_tap_value(sdmmc_t *sdmmc); +void sdmmc_setup_drv_type(sdmmc_t *sdmmc, u32 type); int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type); void sdmmc_card_clock_powersave(sdmmc_t *sdmmc, int powersave_enable); int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type); int sdmmc_tuning_execute(sdmmc_t *sdmmc, u32 type, u32 cmd); int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp); bool sdmmc_get_sd_inserted(); -int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int powersave_enable); +int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type); void sdmmc_end(sdmmc_t *sdmmc); void sdmmc_init_cmd(sdmmc_cmd_t *cmdbuf, u16 cmd, u32 arg, u32 rsp_type, u32 check_busy); int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out); diff --git a/bdk/storage/sdmmc_t210.h b/bdk/storage/sdmmc_t210.h index 50686e4..dfea7d5 100644 --- a/bdk/storage/sdmmc_t210.h +++ b/bdk/storage/sdmmc_t210.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2019 CTCaer + * Copyright (c) 2018-2023 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -21,14 +21,15 @@ #include #include -#define TEGRA_MMC_VNDR_TUN_CTRL0_TAP_VAL_UPDATED_BY_HW 0x20000 -#define TEGRA_MMC_DLLCAL_CFG_EN_CALIBRATE 0x80000000 -#define TEGRA_MMC_DLLCAL_CFG_STATUS_DLL_ACTIVE 0x80000000 -#define TEGRA_MMC_SDMEMCOMPPADCTRL_PAD_E_INPUT_PWRD 0x80000000 -#define TEGRA_MMC_SDMEMCOMPPADCTRL_COMP_VREF_SEL_MASK 0xFFFFFFF0 -#define TEGRA_MMC_AUTOCALCFG_AUTO_CAL_ENABLE 0x20000000 -#define TEGRA_MMC_AUTOCALCFG_AUTO_CAL_START 0x80000000 -#define TEGRA_MMC_AUTOCALSTS_AUTO_CAL_ACTIVE 0x80000000 +#define SDHCI_TEGRA_TUNING_TAP_HW_UPDATED BIT(17) +#define SDHCI_TEGRA_DLLCAL_CALIBRATE BIT(31) +#define SDHCI_TEGRA_DLLCAL_ACTIVE BIT(31) +#define SDHCI_TEGRA_PADCTRL_E_INPUT_PWRD BIT(31) +#define SDHCI_TEGRA_PADCTRL_VREF_SEL_MASK 0xF +#define SDHCI_TEGRA_AUTOCAL_SLW_OVERRIDE BIT(28) +#define SDHCI_TEGRA_AUTOCAL_ENABLE BIT(29) +#define SDHCI_TEGRA_AUTOCAL_START BIT(31) +#define SDHCI_TEGRA_AUTOCAL_ACTIVE BIT(31) typedef struct _t210_sdmmc_t { @@ -72,21 +73,21 @@ typedef struct _t210_sdmmc_t // ADMA3 not supported. 1.8V VDD2 supported. /* 0x44 */ vu32 capareg_hi; -/* 0x48 */ vu32 maxcurr; // Get information by another method. Can be overriden via maxcurrover and maxcurrover_hi. -/* 0x4C */ vu8 rsvd0[4]; // 4C-4F reserved for more max current. -/* 0x50 */ vu16 setacmd12err; +/* 0x48 */ vu32 maxcurr; // Get information by another method. Can be overriden via maxcurrover and maxcurrover_hi. +/* 0x4C */ vu32 maxcurr_hi; +/* 0x50 */ vu16 setacmd12err; // Force error in acmd12errsts. /* 0x52 */ vu16 setinterr; /* 0x54 */ vu8 admaerr; -/* 0x55 */ vu8 rsvd1[3]; // 55-57 reserved. +/* 0x55 */ vu8 rsvd1[3]; // 55-57 reserved. /* 0x58 */ vu32 admaaddr; /* 0x5C */ vu32 admaaddr_hi; /* 0x60 */ vu16 presets[11]; /* 0x76 */ vu16 rsvd2; /* 0x78 */ vu32 adma3addr; /* 0x7C */ vu32 adma3addr_hi; -/* 0x80 */ vu8 uhs2[124]; // 80-FB UHS-II. +/* 0x80 */ vu8 uhs2[124]; // 80-FB UHS-II. /* 0xFC */ vu16 slotintsts; -/* 0xFE */ vu16 hcver; // 0x303 (4.00). +/* 0xFE */ vu16 hcver; // 0x303 (4.00). /* UHS-II range. Used for Vendor registers here */ /* 0x100 */ vu32 venclkctl; diff --git a/bdk/utils/util.c b/bdk/utils/util.c index e88232a..5f00fe0 100644 --- a/bdk/utils/util.c +++ b/bdk/utils/util.c @@ -263,9 +263,6 @@ void power_set_state(power_state_t state) // 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(); - // Set power state. switch (state) { diff --git a/source/gfx/menu.c b/source/gfx/menu.c index 80cd6a6..8b1c7ee 100644 --- a/source/gfx/menu.c +++ b/source/gfx/menu.c @@ -3,6 +3,7 @@ #include "gfx.h" #include "gfxutils.h" #include "../hid/hid.h" +#include #include #include #include diff --git a/source/keys/keys.c b/source/keys/keys.c index c35cd93..8af89b6 100644 --- a/source/keys/keys.c +++ b/source/keys/keys.c @@ -34,6 +34,25 @@ #include +#define TSEC_KEY_DATA_OFFSET 0x300 + +typedef struct _tsec_key_data_t +{ + u8 debug_key[0x10]; + u8 blob0_auth_hash[0x10]; + u8 blob1_auth_hash[0x10]; + u8 blob2_auth_hash[0x10]; + u8 blob2_aes_iv[0x10]; + u8 hovi_eks_seed[0x10]; + u8 hovi_common_seed[0x10]; + u32 blob0_size; + u32 blob1_size; + u32 blob2_size; + u32 blob3_size; + u32 blob4_size; + u8 reserved[0x7C]; +} tsec_key_data_t; + extern hekate_config h_cfg; #define DPRINTF(x) diff --git a/source/script/functions.c b/source/script/functions.c index ac6ae87..96a52fc 100644 --- a/source/script/functions.c +++ b/source/script/functions.c @@ -7,6 +7,7 @@ #include "lexer.h" #include +#include #include "../fs/fsutils.h" #include "../gfx/gfxutils.h" #include "../hid/hid.h" diff --git a/source/storage/emmcfile.c b/source/storage/emmcfile.c index 09068c4..069e036 100644 --- a/source/storage/emmcfile.c +++ b/source/storage/emmcfile.c @@ -167,7 +167,7 @@ ErrCode_t DumpOrWriteEmmcPart(const char *path, const char *part, u8 write, u8 f else { emummc_storage_set_mmc_partition(&emmc_storage, 0); - emmc_part_t *system_part = nx_emmc_part_find(GetCurGPT(), part); + emmc_part_t *system_part = emmc_part_find(GetCurGPT(), part); if (!system_part) return newErrCode(TE_ERR_PARTITION_NOT_FOUND); diff --git a/source/storage/mountmanager.c b/source/storage/mountmanager.c index 1740302..256be11 100644 --- a/source/storage/mountmanager.c +++ b/source/storage/mountmanager.c @@ -40,7 +40,7 @@ void disconnectMMC(){ if (TConf.currentMMCConnected != MMC_CONN_None){ TConf.currentMMCConnected = MMC_CONN_None; emummc_storage_end(&emmc_storage); - nx_emmc_gpt_free(&curGpt); + emmc_gpt_free(&curGpt); } } @@ -55,7 +55,7 @@ int connectMMC(u8 mmcType){ if (!res){ TConf.currentMMCConnected = mmcType; emummc_storage_set_mmc_partition(&emmc_storage, 0); - nx_emmc_gpt_parse(&curGpt, &emmc_storage); + emmc_gpt_parse(&curGpt); } return res; // deal with the errors later lol @@ -69,7 +69,7 @@ ErrCode_t mountMMCPart(const char *partition){ emummc_storage_set_mmc_partition(&emmc_storage, 0); // why i have to do this twice beats me - emmc_part_t *system_part = nx_emmc_part_find(&curGpt, partition); + emmc_part_t *system_part = emmc_part_find(&curGpt, partition); if (!system_part) return newErrCode(TE_ERR_PARTITION_NOT_FOUND); diff --git a/source/tegraexplorer/tools.c b/source/tegraexplorer/tools.c index 2c97985..caa82d6 100644 --- a/source/tegraexplorer/tools.c +++ b/source/tegraexplorer/tools.c @@ -19,6 +19,7 @@ #include #include "../fs/fscopy.h" #include "../utils/utils.h" +#include void DumpSysFw(){ char sysPath[25 + 36 + 3 + 1]; // 24 for "bis:/Contents/registered", 36 for ncaName.nca, 3 for /00, and 1 to make sure :) diff --git a/source/utils/utils.c b/source/utils/utils.c index 89335af..302021d 100644 --- a/source/utils/utils.c +++ b/source/utils/utils.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "vector.h" #include "../gfx/gfxutils.h" #include "../gfx/gfx.h"