update bdk

Signed-off-by: Damien Zhao <zdm65477730@126.com>
This commit is contained in:
Damien Zhao
2025-05-13 19:49:02 +08:00
parent 22b1fda1d5
commit 246486a46e
26 changed files with 595 additions and 423 deletions

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2024 CTCaer
* Copyright (c) 2018-2025 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,
@@ -37,8 +37,8 @@
extern volatile nyx_storage_t *nyx_str;
static u32 _display_id = 0;
static u32 _dsi_bl = -1;
static bool _nx_aula = false;
static u32 _dsi_bl = -1;
static bool _nx_aula = false;
static void _display_panel_and_hw_end(bool no_panel_deinit);
@@ -265,16 +265,9 @@ int display_dsi_vblank_read(u8 cmd, u32 len, void *data)
void display_dsi_write(u8 cmd, u32 len, void *data)
{
static u8 *fifo8 = NULL;
static u32 *fifo32 = NULL;
u32 host_control;
// Allocate fifo buffer.
if (!fifo32)
{
fifo32 = malloc(DSI_STATUS_RX_FIFO_SIZE * 8 * sizeof(u32));
fifo8 = (u8 *)fifo32;
}
u32 fifo32[DSI_STATUS_TX_FIFO_SIZE] = {0};
u8 *fifo8 = (u8 *)fifo32;
// Prepare data for long write.
if (len >= 2)
@@ -319,15 +312,8 @@ void display_dsi_write(u8 cmd, u32 len, void *data)
void display_dsi_vblank_write(u8 cmd, u32 len, void *data)
{
static u8 *fifo8 = NULL;
static u32 *fifo32 = NULL;
// Allocate fifo buffer.
if (!fifo32)
{
fifo32 = malloc(DSI_STATUS_RX_FIFO_SIZE * 8 * sizeof(u32));
fifo8 = (u8 *)fifo32;
}
u32 fifo32[DSI_STATUS_TX_FIFO_SIZE] = {0};
u8 *fifo8 = (u8 *)fifo32;
// Prepare data for long write.
if (len >= 2)
@@ -571,7 +557,7 @@ void display_init()
* When switching to the 16ff pad brick, the clock lane termination control
* is separated from data lane termination. This change of the mipi cal
* brings in a bug that the DSI pad clock termination code can't be loaded
* in one time calibration. Trigger calibration twice.
* in one time calibration on T210B01. Trigger calibration twice.
*/
reg_write_array((u32 *)MIPI_CAL_BASE, _di_mipi_pad_cal_config, ARRAY_SIZE(_di_mipi_pad_cal_config));
for (u32 i = 0; i < 2; i++)

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2024 CTCaer
* Copyright (c) 2018-2025 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,
@@ -520,6 +520,7 @@
#define DSI_STATUS 0x15
#define DSI_STATUS_RX_FIFO_SIZE 0x1F
#define DSI_STATUS_TX_FIFO_SIZE 0x20 // Actual depth is 64.
#define DSI_INIT_SEQ_CONTROL 0x1A
#define DSI_INIT_SEQ_DATA_0 0x1B
@@ -717,7 +718,7 @@
#define MIPI_DCS_READ_DDB_CONTINUE 0xA8 // 0x100 size.
/*! MIPI DCS Panel Private CMDs. */
#define MIPI_DCS_PRIV_SM_SET_COLOR_MODE 0xA0
#define MIPI_DCS_PRIV_SM_SET_COLOR_MODE 0xA0 // 43 bytes.
#define MIPI_DCS_PRIV_SM_SET_REG_OFFSET 0xB0
#define MIPI_DCS_PRIV_SM_SET_ELVSS 0xB1 // OLED backlight tuning. Byte7: PWM transition time in frames.
#define MIPI_DCS_PRIV_SET_POWER_CONTROL 0xB1
@@ -727,6 +728,7 @@
#define MIPI_DCS_PRIV_UNK_D6 0xD6
#define MIPI_DCS_PRIV_UNK_D8 0xD8
#define MIPI_DCS_PRIV_UNK_D9 0xD9
#define MIPI_DCS_PRIV_SM_DISPLAY_ID 0xDD
// LVL1 LVL2 LVL3 UNK0 UNK1
#define MIPI_DCS_PRIV_SM_SET_REGS_LOCK 0xE2 // Samsung: Lock (default): 5A5A A5A5 A5A5 A500 A500. Unlock: A5A5 5A5A 5A5A UNK UNK.
#define MIPI_DCS_PRIV_READ_EXTC_CMD_SPI 0xFE // Read EXTC Command In SPI. 1 byte. 0-6: EXT_SPI_CNT, 7:EXT_SP.
@@ -765,19 +767,21 @@
#define DCS_CONTROL_DISPLAY_SM_FLASHLIGHT BIT(2)
#define DCS_CONTROL_DISPLAY_BACKLIGHT_CTRL BIT(2)
#define DCS_CONTROL_DISPLAY_DIMMING_CTRL BIT(3)
#define DCS_CONTROL_DISPLAY_DIMMING_CTRL BIT(3) // Transition fading.
#define DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL BIT(5)
#define DCS_CONTROL_DISPLAY_HBM_CTRL0 BIT(6)
#define DCS_CONTROL_DISPLAY_HBM_CTRL1 BIT(7)
#define DCS_SM_COLOR_MODE_SATURATED 0x00 // Disabled. Similar to vivid but over-saturated. Wide gamut?
#define DCS_SM_COLOR_MODE_SATURATED 0x00 // Disabled. Based on Vivid but over-saturated.
#define DCS_SM_COLOR_MODE_WASHED 0x45
#define DCS_SM_COLOR_MODE_BASIC 0x03
#define DCS_SM_COLOR_MODE_BASIC 0x03 // Real natural profile.
#define DCS_SM_COLOR_MODE_POR_RESET 0x20 // Reset value on power on.
#define DCS_SM_COLOR_MODE_NATURAL 0x23 // Not actually natural..
#define DCS_SM_COLOR_MODE_VIVID 0x65
#define DCS_SM_COLOR_MODE_NIGHT0 0x43 // Based on washed out.
#define DCS_SM_COLOR_MODE_NIGHT1 0x15 // Based on basic.
#define DCS_SM_COLOR_MODE_NIGHT2 0x35 // Based on natural.
#define DCS_SM_COLOR_MODE_NIGHT3 0x75 // Based on vivid.
#define DCS_SM_COLOR_MODE_NATURAL 0x23 // Not actually natural.. Extra saturation.
#define DCS_SM_COLOR_MODE_VIVID 0x65 // Saturated.
#define DCS_SM_COLOR_MODE_NIGHT0 0x43 // Based on Washed Out.
#define DCS_SM_COLOR_MODE_NIGHT1 0x15 // Based on Basic.
#define DCS_SM_COLOR_MODE_NIGHT2 0x35 // Based on Natural.
#define DCS_SM_COLOR_MODE_NIGHT3 0x75 // Based on Vivid.
#define DCS_SM_COLOR_MODE_ENABLE BIT(0)

View File

@@ -70,8 +70,6 @@ void set_als_cfg(als_ctxt_t *als_ctxt, u8 gain, u8 cycle)
if (!cycle)
cycle = 1;
else if (cycle > 255)
cycle = 255;
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_GAIN_REG), gain);
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_TIMING_REG), (256 - cycle));

View File

@@ -4699,13 +4699,20 @@ FRESULT f_lseek (
DWORD *f_expand_cltbl (
FIL* fp, /* Pointer to the file object */
UINT tblsz, /* Size of table */
UINT tblsz, /* Size of table (2 DWORDs + 2 DWORDs per fragment) */
FSIZE_t ofs /* File pointer from top of file */
)
{
/*
* Cluster table structure:
* Size (DWORD)
* Padding (DWORD)
* (Cluster Offset (DWORD) + Sequential clusters (DWORD)) * Fragments
*/
if (fp->flag & FA_WRITE) f_lseek(fp, ofs); /* Expand file if write is enabled */
if (!fp->cltbl) { /* Allocate memory for cluster link table */
fp->cltbl = (DWORD *)ff_memalloc(tblsz);
if (!fp->cltbl) return (void *)0;
fp->cltbl[0] = tblsz;
}
if (f_lseek(fp, CREATE_LINKMAP)) { /* Create cluster link table */

View File

@@ -292,7 +292,7 @@ FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt); /* Allocate a contiguous
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */
FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */
FRESULT f_fdisk_mod (BYTE pdrv, const DWORD* szt, void* work); /* Modded version of f_fdisk that works:tm: */
FRESULT f_fdisk_mod (BYTE pdrv, const DWORD* szt, void* work); /* Modded version of f_fdisk that works:tm: */
FRESULT f_setcp (WORD cp); /* Set current code page */
int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */
int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */

View File

@@ -29,127 +29,128 @@ int bq24193_get_property(enum BQ24193_reg_prop prop, int *value)
{
u8 data;
switch (prop) {
case BQ24193_InputVoltageLimit: // Input voltage limit (mV).
data = bq24193_get_reg(BQ24193_InputSource);
data = (data & BQ24193_INCONFIG_VINDPM_MASK) >> 3;
*value = 0;
*value += ((data >> 0) & 1) ? 80 : 0;
*value += ((data >> 1) & 1) ? 160 : 0;
*value += ((data >> 2) & 1) ? 320 : 0;
*value += ((data >> 3) & 1) ? 640 : 0;
*value += 3880;
switch (prop)
{
case BQ24193_InputVoltageLimit: // Input voltage limit (mV).
data = bq24193_get_reg(BQ24193_InputSource);
data = (data & BQ24193_INCONFIG_VINDPM_MASK) >> 3;
*value = 0;
*value += ((data >> 0) & 1) ? 80 : 0;
*value += ((data >> 1) & 1) ? 160 : 0;
*value += ((data >> 2) & 1) ? 320 : 0;
*value += ((data >> 3) & 1) ? 640 : 0;
*value += 3880;
break;
case BQ24193_InputCurrentLimit: // Input current limit (mA).
data = bq24193_get_reg(BQ24193_InputSource);
data &= BQ24193_INCONFIG_INLIMIT_MASK;
switch (data)
{
case 0:
*value = 100;
break;
case BQ24193_InputCurrentLimit: // Input current limit (mA).
data = bq24193_get_reg(BQ24193_InputSource);
data &= BQ24193_INCONFIG_INLIMIT_MASK;
switch (data)
{
case 0:
*value = 100;
break;
case 1:
*value = 150;
break;
case 2:
*value = 500;
break;
case 3:
*value = 900;
break;
case 4:
*value = 1200;
break;
case 5:
*value = 1500;
break;
case 6:
*value = 2000;
break;
case 7:
*value = 3000;
break;
}
case 1:
*value = 150;
break;
case BQ24193_SystemMinimumVoltage: // Minimum system voltage limit (mV).
data = bq24193_get_reg(BQ24193_PORConfig);
*value = (data & BQ24193_PORCONFIG_SYSMIN_MASK) >> 1;
*value *= 100;
*value += 3000;
case 2:
*value = 500;
break;
case BQ24193_FastChargeCurrentLimit: // Fast charge current limit (mA).
data = bq24193_get_reg(BQ24193_ChrgCurr);
data = (data & BQ24193_CHRGCURR_ICHG_MASK) >> 2;
*value = 0;
*value += ((data >> 0) & 1) ? 64 : 0;
*value += ((data >> 1) & 1) ? 128 : 0;
*value += ((data >> 2) & 1) ? 256 : 0;
*value += ((data >> 3) & 1) ? 512 : 0;
*value += ((data >> 4) & 1) ? 1024 : 0;
*value += ((data >> 5) & 1) ? 2048 : 0;
*value += 512;
data = bq24193_get_reg(BQ24193_ChrgCurr);
data &= BQ24193_CHRGCURR_20PCT_MASK;
if (data)
*value = *value * 20 / 100; // Fast charge current limit is 20%.
case 3:
*value = 900;
break;
case BQ24193_ChargeVoltageLimit: // Charge voltage limit (mV).
data = bq24193_get_reg(BQ24193_ChrgVolt);
data = (data & BQ24193_CHRGVOLT_VREG) >> 2;
*value = 0;
*value += ((data >> 0) & 1) ? 16 : 0;
*value += ((data >> 1) & 1) ? 32 : 0;
*value += ((data >> 2) & 1) ? 64 : 0;
*value += ((data >> 3) & 1) ? 128 : 0;
*value += ((data >> 4) & 1) ? 256 : 0;
*value += ((data >> 5) & 1) ? 512 : 0;
*value += 3504;
case 4:
*value = 1200;
break;
case BQ24193_RechargeThreshold: // Recharge voltage threshold less than voltage limit (mV).
data = bq24193_get_reg(BQ24193_ChrgVolt);
data &= BQ24193_IRTHERMAL_THERM_MASK;
if (data)
*value = 300;
else
*value = 100;
case 5:
*value = 1500;
break;
case BQ24193_ThermalRegulation: // Thermal regulation threshold (oC).
data = bq24193_get_reg(BQ24193_IRCompThermal);
data &= BQ24193_IRTHERMAL_THERM_MASK;
switch (data)
{
case 0:
*value = 60;
break;
case 1:
*value = 80;
break;
case 2:
*value = 100;
break;
case 3:
*value = 120;
break;
}
case 6:
*value = 2000;
break;
case BQ24193_ChargeStatus: // 0: Not charging, 1: Pre-charge, 2: Fast charging, 3: Charge termination done
data = bq24193_get_reg(BQ24193_Status);
*value = (data & BQ24193_STATUS_CHRG_MASK) >> 4;
case 7:
*value = 3000;
break;
case BQ24193_TempStatus: // 0: Normal, 2: Warm, 3: Cool, 5: Cold, 6: Hot.
data = bq24193_get_reg(BQ24193_FaultReg);
*value = data & BQ24193_FAULT_THERM_MASK;
}
break;
case BQ24193_SystemMinimumVoltage: // Minimum system voltage limit (mV).
data = bq24193_get_reg(BQ24193_PORConfig);
*value = (data & BQ24193_PORCONFIG_SYSMIN_MASK) >> 1;
*value *= 100;
*value += 3000;
break;
case BQ24193_FastChargeCurrentLimit: // Fast charge current limit (mA).
data = bq24193_get_reg(BQ24193_ChrgCurr);
data = (data & BQ24193_CHRGCURR_ICHG_MASK) >> 2;
*value = 0;
*value += ((data >> 0) & 1) ? 64 : 0;
*value += ((data >> 1) & 1) ? 128 : 0;
*value += ((data >> 2) & 1) ? 256 : 0;
*value += ((data >> 3) & 1) ? 512 : 0;
*value += ((data >> 4) & 1) ? 1024 : 0;
*value += ((data >> 5) & 1) ? 2048 : 0;
*value += 512;
data = bq24193_get_reg(BQ24193_ChrgCurr);
data &= BQ24193_CHRGCURR_20PCT_MASK;
if (data)
*value = *value * 20 / 100; // Fast charge current limit is 20%.
break;
case BQ24193_ChargeVoltageLimit: // Charge voltage limit (mV).
data = bq24193_get_reg(BQ24193_ChrgVolt);
data = (data & BQ24193_CHRGVOLT_VREG) >> 2;
*value = 0;
*value += ((data >> 0) & 1) ? 16 : 0;
*value += ((data >> 1) & 1) ? 32 : 0;
*value += ((data >> 2) & 1) ? 64 : 0;
*value += ((data >> 3) & 1) ? 128 : 0;
*value += ((data >> 4) & 1) ? 256 : 0;
*value += ((data >> 5) & 1) ? 512 : 0;
*value += 3504;
break;
case BQ24193_RechargeThreshold: // Recharge voltage threshold less than voltage limit (mV).
data = bq24193_get_reg(BQ24193_ChrgVolt);
data &= BQ24193_IRTHERMAL_THERM_MASK;
if (data)
*value = 300;
else
*value = 100;
break;
case BQ24193_ThermalRegulation: // Thermal regulation threshold (oC).
data = bq24193_get_reg(BQ24193_IRCompThermal);
data &= BQ24193_IRTHERMAL_THERM_MASK;
switch (data)
{
case 0:
*value = 60;
break;
case BQ24193_DevID: // Dev ID.
data = bq24193_get_reg(BQ24193_VendorPart);
*value = data & BQ24193_VENDORPART_DEV_MASK;
case 1:
*value = 80;
break;
case BQ24193_ProductNumber: // Product number.
data = bq24193_get_reg(BQ24193_VendorPart);
*value = (data & BQ24193_VENDORPART_PN_MASK) >> 3;
case 2:
*value = 100;
break;
default:
return -1;
case 3:
*value = 120;
break;
}
break;
case BQ24193_ChargeStatus: // 0: Not charging, 1: Pre-charge, 2: Fast charging, 3: Charge termination done
data = bq24193_get_reg(BQ24193_Status);
*value = (data & BQ24193_STATUS_CHRG_MASK) >> 4;
break;
case BQ24193_TempStatus: // 0: Normal, 2: Warm, 3: Cool, 5: Cold, 6: Hot.
data = bq24193_get_reg(BQ24193_FaultReg);
*value = data & BQ24193_FAULT_THERM_MASK;
break;
case BQ24193_DevID: // Dev ID.
data = bq24193_get_reg(BQ24193_VendorPart);
*value = data & BQ24193_VENDORPART_DEV_MASK;
break;
case BQ24193_ProductNumber: // Product number.
data = bq24193_get_reg(BQ24193_VendorPart);
*value = (data & BQ24193_VENDORPART_PN_MASK) >> 3;
break;
default:
return -1;
}
return 0;
}

View File

@@ -327,7 +327,7 @@ void max77620_config_default()
return;
// Set default voltages and enable regulators.
for (u32 i = 1; i <= REGULATOR_LDO8; i++)
for (u32 i = REGULATOR_SD1; i <= REGULATOR_LDO8; i++)
{
max77620_regulator_config_fps(i);
max7762x_regulator_set_voltage(i, _pmic_regulators[i].uv_default);

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2024 CTCaer
* Copyright (c) 2018-2025 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -19,7 +19,6 @@
#include "se.h"
#include <memory_map.h>
#include <mem/heap.h>
#include <soc/bpmp.h>
#include <soc/hw_init.h>
#include <soc/pmc.h>
@@ -185,7 +184,7 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr
if (!src || !dst)
return 0;
u8 *block = (u8 *)zalloc(SE_AES_BLOCK_SIZE);
u32 block[SE_AES_BLOCK_SIZE / sizeof(u32)] = {0};
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
@@ -193,7 +192,6 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr
int res = _se_execute_oneshot(op, block, SE_AES_BLOCK_SIZE, block, SE_AES_BLOCK_SIZE);
memcpy(dst, block, dst_size);
free(block);
return res;
}
@@ -458,7 +456,8 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_s
int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, void *src, u32 secsize)
{
int res = 0;
u8 *tweak = (u8 *)malloc(SE_AES_BLOCK_SIZE);
u32 tmp[SE_AES_BLOCK_SIZE / sizeof(u32)];
u8 *tweak = (u8 *)tmp;
u8 *pdst = (u8 *)dst;
u8 *psrc = (u8 *)src;
@@ -487,8 +486,7 @@ int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst
res = 1;
out:;
free(tweak);
out:
return res;
}
@@ -583,15 +581,15 @@ int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64
return 0;
// Src size of 0 is not supported, so return null string sha256.
// if (!src_size)
// {
// const u8 null_hash[SE_SHA_256_SIZE] = {
// 0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14, 0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24,
// 0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, 0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55
// };
// memcpy(hash, null_hash, SE_SHA_256_SIZE);
// return 1;
// }
if (!src_size)
{
const u8 null_hash[SE_SHA_256_SIZE] = {
0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14, 0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24,
0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, 0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55
};
memcpy(hash, null_hash, SE_SHA_256_SIZE);
return 1;
}
// Setup config for SHA256.
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG);
@@ -653,9 +651,14 @@ int se_calc_sha256_finalize(void *hash, u32 *msg_left)
int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size)
{
int res = 0;
u8 *secret = (u8 *)malloc(0x40);
u8 *ipad = (u8 *)malloc(0x40 + src_size);
u8 *opad = (u8 *)malloc(0x60);
u8 tmp1[0x40] = {0};
u8 tmp2[0x40 + src_size];
u8 tmp3[0x60] = {0};
memset(tmp2, 0, 0x40 + src_size);
u8 *secret = (u8 *)tmp1;
u8 *ipad = (u8 *)tmp2;
u8 *opad = (u8 *)tmp3;
if (key_size > 0x40)
{
@@ -688,9 +691,6 @@ int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *ke
res = 1;
out:;
free(secret);
free(ipad);
free(opad);
return res;
}
@@ -770,8 +770,11 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
int se_aes_cmac_128(u32 ks, void *dst, const void *src, u32 src_size)
{
int res = 0;
u8 *key = (u8 *)zalloc(SE_KEY_128_SIZE);
u8 *last_block = (u8 *)zalloc(SE_AES_BLOCK_SIZE);
u32 tmp1[SE_KEY_128_SIZE / sizeof(u32)] = {0};
u32 tmp2[SE_AES_BLOCK_SIZE / sizeof(u32)] = {0};
u8 *key = (u8 *)tmp1;
u8 *last_block = (u8 *)tmp2;
se_aes_iv_clear(ks);
se_aes_iv_updated_clear(ks);
@@ -820,8 +823,6 @@ int se_aes_cmac_128(u32 ks, void *dst, const void *src, u32 src_size)
for (u32 i = 0; i < (SE_KEY_128_SIZE / 4); i++)
dst32[i] = SE(SE_HASH_RESULT_REG + (i * 4));
out:;
free(key);
free(last_block);
out:
return res;
}

View File

@@ -47,7 +47,7 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_
int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot);
int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size);
int se_calc_sha256_finalize(void *hash, u32 *msg_left);
int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size);
int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size);
int se_gen_prng128(void *dst);
int se_aes_cmac_128(u32 ks, void *dst, const void *src, u32 src_size);

View File

@@ -24,7 +24,9 @@
#include <sec/se_t210.h>
#include <soc/fuse.h>
#include <soc/hw_init.h>
#include <soc/pmc.h>
#include <soc/t210.h>
#include <soc/timer.h>
#include <utils/types.h>
static const u32 evp_thunk_template[] = {

View File

@@ -304,7 +304,7 @@ enum
void fuse_disable_program();
u32 fuse_read_odm(u32 idx);
u32 fuse_read_odm_keygen_rev();
u32 fuse_read_bootrom_rev();
u32 fuse_read_bootrom_rev();
u32 fuse_read_dramid(bool raw_id);
u32 fuse_read_hw_state();
u32 fuse_read_hw_type();

View File

@@ -85,6 +85,7 @@
#define AXBAR_BASE 0x702D0800
#define I2S_BASE 0x702D1000
#define ADMA_BASE 0x702E2000
#define AMC_BASE 0x702EF000
#define SE2_BASE 0x70412000
#define SE_PKA1_BASE 0x70420000
#define TZRAM_BASE 0x7C010000
@@ -151,6 +152,7 @@
#define CL_DVFS(off) MMIO_REG32(CL_DVFS_BASE, off)
#define I2S(off) MMIO_REG32(I2S_BASE, off)
#define ADMA(off) MMIO_REG32(ADMA_BASE, off)
#define AMC(off) MMIO_REG32(AMC_BASE, off)
#define SE2(off) MMIO_REG32(SE2_BASE, off)
#define SE_PKA1(off) MMIO_REG32(SE_PKA1_BASE, off)
#define USB(off) MMIO_REG32(USB_BASE, off)
@@ -199,7 +201,7 @@
/*! AHB Gizmo registers. */
#define AHB_ARBITRATION_PRIORITY_CTRL 0x8
#define PRIORITY_CTRL_WEIGHT(x) (((x) & 7) << 29)
#define PRIORITY_SELECT_USB BIT(6) // USB-OTG.
#define PRIORITY_SELECT_USB BIT(6) // USB-OTG.
#define PRIORITY_SELECT_USB2 BIT(18) // USB-HSIC.
#define PRIORITY_SELECT_USB3 BIT(17) // XUSB.
#define AHB_GIZMO_AHB_MEM 0x10
@@ -210,7 +212,7 @@
#define AHB_GIZMO_USB 0x20
#define AHB_GIZMO_SDMMC4 0x48
#define AHB_GIZMO_USB2 0x7C
#define AHB_GIZMO_USB3 0x80
#define AHB_GIZMO_USB3 0x80 // Doesn't exist on T21x??
#define AHB_GIZMO_IMMEDIATE BIT(18)
#define AHB_ARBITRATION_XBAR_CTRL 0xE0
#define AHB_AHB_MEM_PREFETCH_CFG3 0xE4
@@ -219,9 +221,9 @@
#define AHB_AHB_MEM_PREFETCH_CFG2 0xF4
#define MST_ID(x) (((x) & 0x1F) << 26)
#define MEM_PREFETCH_AHBDMA_MST_ID MST_ID(5)
#define MEM_PREFETCH_USB_MST_ID MST_ID(6) // USB-OTG.
#define MEM_PREFETCH_USB2_MST_ID MST_ID(18) // USB-HSIC.
#define MEM_PREFETCH_USB3_MST_ID MST_ID(17) // XUSB.
#define MEM_PREFETCH_USB_MST_ID MST_ID(6) // USB-OTG. Doesn't exist on T210B01.
#define MEM_PREFETCH_USB2_MST_ID MST_ID(18) // USB-HSIC. Doesn't exist on T210B01.
#define MEM_PREFETCH_USB3_MST_ID MST_ID(17) // XUSB. Doesn't exist on T210B01.
#define MEM_PREFETCH_ADDR_BNDRY(x) (((x) & 0xF) << 21)
#define MEM_PREFETCH_ENABLE BIT(31)
#define AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID 0xFC

View File

@@ -70,6 +70,8 @@
#define UART_MCR_CTS_EN BIT(5)
#define UART_MCR_RTS_EN BIT(6)
#define UART_FIFO_SIZE 36
typedef struct _uart_t
{
/* 0x00 */ vu32 UART_THR_DLAB;

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2005-2007 Pierre Ossman, All Rights Reserved.
* Copyright (c) 2018-2023 CTCaer
* Copyright (c) 2018-2025 CTCaer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,11 +17,16 @@
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */
#define SD_SWITCH_VOLTAGE 11 /* ac R1 */
/* Class 2 */
#define SD_ADDR_EXT 22 /* ac [5:0] R1 */
/* class 10 */
#define SD_SWITCH 6 /* adtc [31:0] See below R1 */
/* class 5 */
#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */
#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */
/* class 11 */
#define SD_READ_EXTR_SINGLE 48 /* adtc [31:0] R1 */
#define SD_WRITE_EXTR_SINGLE 49 /* adtc [31:0] R1 */
/* Application commands */
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2023 CTCaer
* Copyright (c) 2018-2025 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -18,6 +18,7 @@
#include <string.h>
#include <mem/heap.h>
#include <mem/mc.h>
#include <soc/timer.h>
#include <storage/emmc.h>
#include <storage/sdmmc.h>
@@ -28,14 +29,26 @@
#include <memory_map.h>
#include <gfx_utils.h>
//#define SDMMC_DEBUG_PRINT_SD_REGS
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DPRINTF(...)
//#define SDMMC_DEBUG_PRINT_SD_REGS
#ifdef SDMMC_DEBUG_PRINT_SD_REGS
#define DREGPRINTF(...) gfx_printf(__VA_ARGS__)
#else
#define DREGPRINTF(...)
#endif
#ifdef BDK_SDMMC_EXTRA_PRINT
#define ERROR_EXTRA_PRINTING
#endif
u32 sd_power_cycle_time_start;
static inline u32 unstuff_bits(const u32 *resp, u32 start, u32 size)
{
start %= 128;
const u32 mask = (size < 32 ? 1 << size : 0) - 1;
const u32 off = 3 - ((start) / 32);
const u32 shft = (start) & 31;
@@ -53,7 +66,7 @@ static inline u32 unstuff_bits(const u32 *resp, u32 start, u32 size)
static int _sdmmc_storage_check_card_status(u32 res)
{
//Error mask:
//TODO: R1_SWITCH_ERROR can be skipped for certain card types.
//!WARN: R1_SWITCH_ERROR is reserved on SD. The card isn't supposed to use it.
if (res &
(R1_OUT_OF_RANGE | R1_ADDRESS_ERROR | R1_BLOCK_LEN_ERROR |
R1_ERASE_SEQ_ERROR | R1_ERASE_PARAM | R1_WP_VIOLATION |
@@ -74,7 +87,7 @@ static int _sdmmc_storage_execute_cmd_type1_ex(sdmmc_storage_t *storage, u32 *re
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0;
sdmmc_get_rsp(storage->sdmmc, resp, 4, SDMMC_RSP_TYPE_1);
sdmmc_get_cached_rsp(storage->sdmmc, resp, SDMMC_RSP_TYPE_1);
if (mask)
*resp &= ~mask;
@@ -106,7 +119,7 @@ static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage)
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0;
sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_cid, 16, SDMMC_RSP_TYPE_2);
sdmmc_get_cached_rsp(storage->sdmmc, (u32 *)storage->raw_cid, SDMMC_RSP_TYPE_2);
return 1;
}
@@ -123,7 +136,7 @@ static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage)
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0;
sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_csd, 16, SDMMC_RSP_TYPE_2);
sdmmc_get_cached_rsp(storage->sdmmc, (u32 *)storage->raw_csd, SDMMC_RSP_TYPE_2);
return 1;
}
@@ -152,7 +165,7 @@ int sdmmc_storage_execute_vendor_cmd(sdmmc_storage_t *storage, u32 arg)
return 0;
u32 resp;
sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_1);
sdmmc_get_cached_rsp(storage->sdmmc, &resp, SDMMC_RSP_TYPE_1);
resp = -1;
u32 timeout = get_tmr_ms() + 1500;
@@ -229,6 +242,10 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
return 0;
}
sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
if (!_sdmmc_storage_check_card_status(tmp))
return 0;
return 1;
}
@@ -246,6 +263,43 @@ int sdmmc_storage_end(sdmmc_storage_t *storage)
return 1;
}
static int _sdmmc_storage_handle_io_error(sdmmc_storage_t *storage, bool first_reinit)
{
int res = 0;
if (storage->sdmmc->id == SDMMC_1 || storage->sdmmc->id == SDMMC_4)
{
if (storage->sdmmc->id == SDMMC_1)
{
sd_error_count_increment(SD_ERROR_RW_FAIL);
if (first_reinit)
res = sd_initialize(true);
else
{
res = sd_init_retry(true);
if (!res)
sd_error_count_increment(SD_ERROR_INIT_FAIL);
}
}
else if (storage->sdmmc->id == SDMMC_4)
{
emmc_error_count_increment(EMMC_ERROR_RW_FAIL);
if (first_reinit)
res = emmc_initialize(true);
else
{
res = emmc_init_retry(true);
if (!res)
emmc_error_count_increment(EMMC_ERROR_INIT_FAIL);
}
}
}
return res;
}
static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf, u32 is_write)
{
u8 *bbuf = (u8 *)buf;
@@ -257,6 +311,15 @@ static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 nu
if (!storage->initialized)
return 0;
// Check if out of bounds.
if (((u64)sector + num_sectors) > storage->sec_cnt)
{
#ifdef ERROR_EXTRA_PRINTING
EPRINTFARGS("SDMMC%d: Out of bounds!", storage->sdmmc->id + 1);
#endif
return 0;
}
while (sct_total)
{
u32 blkcnt = 0;
@@ -276,51 +339,18 @@ reinit_try:
} while (retries);
// Disk IO failure! Reinit SD/EMMC to a lower speed.
if (storage->sdmmc->id == SDMMC_1 || storage->sdmmc->id == SDMMC_4)
if (_sdmmc_storage_handle_io_error(storage, first_reinit))
{
int res = 0;
if (storage->sdmmc->id == SDMMC_1)
{
sd_error_count_increment(SD_ERROR_RW_FAIL);
if (first_reinit)
res = sd_initialize(true);
else
{
res = sd_init_retry(true);
if (!res)
sd_error_count_increment(SD_ERROR_INIT_FAIL);
}
}
else if (storage->sdmmc->id == SDMMC_4)
{
emmc_error_count_increment(EMMC_ERROR_RW_FAIL);
if (first_reinit)
res = emmc_initialize(true);
else
{
res = emmc_init_retry(true);
if (!res)
emmc_error_count_increment(EMMC_ERROR_INIT_FAIL);
}
}
// Reset values for a retry.
blkcnt = 0;
retries = 3;
first_reinit = false;
// If successful reinit, restart xfer.
if (res)
{
bbuf = (u8 *)buf;
sct_off = sector;
sct_total = num_sectors;
bbuf = (u8 *)buf;
sct_off = sector;
sct_total = num_sectors;
goto reinit_try;
}
goto reinit_try;
}
// Failed.
@@ -394,7 +424,7 @@ static int _mmc_storage_get_op_cond_inner(sdmmc_storage_t *storage, u32 *pout, u
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0;
return sdmmc_get_rsp(storage->sdmmc, pout, 4, SDMMC_RSP_TYPE_3);
return sdmmc_get_cached_rsp(storage->sdmmc, pout, SDMMC_RSP_TYPE_3);
}
static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power)
@@ -478,12 +508,12 @@ static void _mmc_storage_parse_csd(sdmmc_storage_t *storage)
{
u32 *raw_csd = (u32 *)storage->raw_csd;
storage->csd.mmca_vsn = unstuff_bits(raw_csd, 122, 4);
storage->csd.structure = unstuff_bits(raw_csd, 126, 2);
storage->csd.cmdclass = unstuff_bits(raw_csd, 84, 12);
storage->csd.mmca_vsn = unstuff_bits(raw_csd, 122, 4);
storage->csd.structure = unstuff_bits(raw_csd, 126, 2);
storage->csd.cmdclass = unstuff_bits(raw_csd, 84, 12);
storage->csd.read_blkbits = unstuff_bits(raw_csd, 80, 4);
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
storage->sec_cnt = storage->csd.capacity;
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
storage->sec_cnt = storage->csd.capacity;
}
static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
@@ -532,12 +562,40 @@ int mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
return 0;
u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
_mmc_storage_parse_ext_csd(storage, buf);
return _sdmmc_storage_check_card_status(tmp);
}
int sd_storage_get_ext_reg(sdmmc_storage_t *storage, u8 fno, u8 page, u16 address, u32 len, void *buf)
{
if (!(storage->scr.cmds & BIT(2)))
return 0;
sdmmc_cmd_t cmdbuf;
u32 arg = fno << 27 | page << 18 | address << 9 | (len - 1);
sdmmc_init_cmd(&cmdbuf, SD_READ_EXTR_SINGLE, arg, SDMMC_RSP_TYPE_1, 0);
sdmmc_req_t reqbuf;
reqbuf.buf = buf;
reqbuf.blksize = SDMMC_DAT_BLOCKSIZE;
reqbuf.num_sectors = 1;
reqbuf.is_write = 0;
reqbuf.is_multi_block = 0;
reqbuf.is_auto_stop_trn = 0;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
return 0;
u32 tmp = 0;
sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
return _sdmmc_storage_check_card_status(tmp);
}
static int _mmc_storage_switch(sdmmc_storage_t *storage, u32 arg)
{
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SWITCH, arg, 1, R1_SKIP_STATE_CHECK);
@@ -814,7 +872,7 @@ void _sd_storage_debug_print_csd(const u32 *raw_csd)
gfx_printf("WRITE_BLK_MISALIGN: %X\n", unstuff_bits(raw_csd, 78, 1));
gfx_printf("READ_BLK_MISALIGN: %X\n", unstuff_bits(raw_csd, 77, 1));
gfx_printf("DSR_IMP: %X\n", unstuff_bits(raw_csd, 76, 1));
gfx_printf("C_SIZE: %06X\n", unstuff_bits(raw_csd, 48, 22));
gfx_printf("C_SIZE: %06X\n", unstuff_bits(raw_csd, 48, 28)); // CSD 3 (SDUC).
gfx_printf("ERASE_BLK_LEN: %X\n", unstuff_bits(raw_csd, 46, 1));
gfx_printf("SECTOR_SIZE: %02X\n", unstuff_bits(raw_csd, 39, 6));
@@ -831,8 +889,8 @@ void _sd_storage_debug_print_csd(const u32 *raw_csd)
gfx_printf("TMP_WRITE_PROTECT: %X\n", unstuff_bits(raw_csd, 12, 1));
gfx_printf("FILE_FORMAT: %X\n", unstuff_bits(raw_csd, 10, 2));
gfx_printf("--RSVD-- %02X %02X %X %X %02X %X\n",
unstuff_bits(raw_csd, 120, 6), unstuff_bits(raw_csd, 70, 6),
gfx_printf("--RSVD-- %02X %X %X %02X %X\n",
unstuff_bits(raw_csd, 120, 6),
unstuff_bits(raw_csd, 47, 1), unstuff_bits(raw_csd, 29, 2),
unstuff_bits(raw_csd, 16, 5), unstuff_bits(raw_csd, 8, 2));
}
@@ -871,39 +929,39 @@ void _sd_storage_debug_print_ssr(const u8 *raw_ssr)
gfx_printf("\nSD Status:\n");
gfx_printf("DAT_BUS_WIDTH: %X\n", unstuff_bits(raw_ssr0, 510 - 384, 2));
gfx_printf("SECURED_MODE: %X\n", unstuff_bits(raw_ssr0, 509 - 384, 1));
gfx_printf("SECURITY_FUNCTIONS: %02X\n", unstuff_bits(raw_ssr0, 502 - 384, 6));
gfx_printf("SD_CARD_TYPE: %04X\n", unstuff_bits(raw_ssr0, 480 - 384, 16));
gfx_printf("SZ_OF_PROTECTED_AREA: %08X\n", unstuff_bits(raw_ssr0, 448 - 384, 32));
gfx_printf("SPEED_CLASS: %02X\n", unstuff_bits(raw_ssr0, 440 - 384, 8));
gfx_printf("PERFORMANCE_MOVE: %02X\n", unstuff_bits(raw_ssr0, 432 - 384, 8));
gfx_printf("AU_SIZE: %X\n", unstuff_bits(raw_ssr0, 428 - 384, 4));
gfx_printf("ERAZE_SIZE: %04X\n", unstuff_bits(raw_ssr0, 408 - 384, 16));
gfx_printf("ERASE_TIMEOUT: %02X\n", unstuff_bits(raw_ssr0, 402 - 384, 6));
gfx_printf("ERASE_OFFSET: %X\n", unstuff_bits(raw_ssr0, 400 - 384, 2));
gfx_printf("UHS_SPEED_GRADE: %X\n", unstuff_bits(raw_ssr0, 396 - 384, 4));
gfx_printf("UHS_AU_SIZE: %X\n", unstuff_bits(raw_ssr0, 392 - 384, 4));
gfx_printf("VIDEO_SPEED_CLASS: %02X\n", unstuff_bits(raw_ssr0, 384 - 384, 8));
gfx_printf("DAT_BUS_WIDTH: %X\n", unstuff_bits(raw_ssr0, 510, 2));
gfx_printf("SECURED_MODE: %X\n", unstuff_bits(raw_ssr0, 509, 1));
gfx_printf("SECURITY_FUNCTIONS: %02X\n", unstuff_bits(raw_ssr0, 502, 6));
gfx_printf("SD_CARD_TYPE: %04X\n", unstuff_bits(raw_ssr0, 480, 16));
gfx_printf("SZ_OF_PROTECTED_AREA: %08X\n", unstuff_bits(raw_ssr0, 448, 32));
gfx_printf("SPEED_CLASS: %02X\n", unstuff_bits(raw_ssr0, 440, 8));
gfx_printf("PERFORMANCE_MOVE: %02X\n", unstuff_bits(raw_ssr0, 432, 8));
gfx_printf("AU_SIZE: %X\n", unstuff_bits(raw_ssr0, 428, 4));
gfx_printf("ERAZE_SIZE: %04X\n", unstuff_bits(raw_ssr0, 408, 16));
gfx_printf("ERASE_TIMEOUT: %02X\n", unstuff_bits(raw_ssr0, 402, 6));
gfx_printf("ERASE_OFFSET: %X\n", unstuff_bits(raw_ssr0, 400, 2));
gfx_printf("UHS_SPEED_GRADE: %X\n", unstuff_bits(raw_ssr0, 396, 4));
gfx_printf("UHS_AU_SIZE: %X\n", unstuff_bits(raw_ssr0, 392, 4));
gfx_printf("VIDEO_SPEED_CLASS: %02X\n", unstuff_bits(raw_ssr0, 384, 8));
gfx_printf("VSC_AU_SIZE: %03X\n", unstuff_bits(raw_ssr1, 368 - 256, 10));
gfx_printf("SUS_ADDR: %06X\n", unstuff_bits(raw_ssr1, 346 - 256, 22));
gfx_printf("APP_PERF_CLASS: %X\n", unstuff_bits(raw_ssr1, 336 - 256, 4));
gfx_printf("PERFORMANCE_ENHANCE: %02X\n", unstuff_bits(raw_ssr1, 328 - 256, 8));
gfx_printf("DISCARD_SUPPORT: %X\n", unstuff_bits(raw_ssr1, 313 - 256, 1));
gfx_printf("FULE_SUPPORT: %X\n", unstuff_bits(raw_ssr1, 312 - 256, 1));
gfx_printf("VSC_AU_SIZE: %03X\n", unstuff_bits(raw_ssr1, 368, 10));
gfx_printf("SUS_ADDR: %06X\n", unstuff_bits(raw_ssr1, 346, 22));
gfx_printf("APP_PERF_CLASS: %X\n", unstuff_bits(raw_ssr1, 336, 4));
gfx_printf("PERFORMANCE_ENHANCE: %02X\n", unstuff_bits(raw_ssr1, 328, 8));
gfx_printf("DISCARD_SUPPORT: %X\n", unstuff_bits(raw_ssr1, 313, 1));
gfx_printf("FULE_SUPPORT: %X\n", unstuff_bits(raw_ssr1, 312, 1));
gfx_printf("--RSVD-- %02X %X %02X %02X %04X\n",
unstuff_bits(raw_ssr0, 496 - 384, 6), unstuff_bits(raw_ssr0, 424 - 384, 4),
unstuff_bits(raw_ssr1, 378 - 256, 6), unstuff_bits(raw_ssr1, 340 - 256, 6),
unstuff_bits(raw_ssr1, 314 - 256, 14));
unstuff_bits(raw_ssr0, 496, 6), unstuff_bits(raw_ssr0, 424, 4),
unstuff_bits(raw_ssr1, 378, 6), unstuff_bits(raw_ssr1, 340, 6),
unstuff_bits(raw_ssr1, 314, 14));
gfx_printf("VENDOR_1: %06X %08X\n",
unstuff_bits(raw_ssr1, 288 - 256, 24), unstuff_bits(raw_ssr1, 256 - 256, 32));
unstuff_bits(raw_ssr1, 288, 24), unstuff_bits(raw_ssr1, 256, 32));
gfx_printf("VENDOR_2: %08X %08X %08X %08X\n",
unstuff_bits(raw_ssr2, 224 - 128, 32), unstuff_bits(raw_ssr2, 192 - 128, 32),
unstuff_bits(raw_ssr2, 160 - 128, 32), unstuff_bits(raw_ssr2, 128 - 128, 32));
unstuff_bits(raw_ssr2, 224, 32), unstuff_bits(raw_ssr2, 192, 32),
unstuff_bits(raw_ssr2, 160, 32), unstuff_bits(raw_ssr2, 128, 32));
gfx_printf("VENDOR_3: %08X %08X %08X %08X\n",
unstuff_bits(raw_ssr3, 96 - 0, 32), unstuff_bits(raw_ssr3, 64, 32),
unstuff_bits(raw_ssr3, 32 - 0, 32), unstuff_bits(raw_ssr3, 0, 32));
@@ -917,13 +975,19 @@ static int _sd_storage_send_if_cond(sdmmc_storage_t *storage, bool *is_sdsc)
sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, vhd_pattern, SDMMC_RSP_TYPE_5, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
{
*is_sdsc = 1; // The SD Card is version 1.X
return 1;
// The SD Card is version 1.X (SDSC) if there is no response.
if (storage->sdmmc->error_sts == SDHCI_ERR_INT_CMD_TIMEOUT)
{
*is_sdsc = 1;
return 1;
}
return 0;
}
// For Card version >= 2.0, parse results.
u32 resp = 0;
sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5);
sdmmc_get_cached_rsp(storage->sdmmc, &resp, SDMMC_RSP_TYPE_5);
// Check if VHD was accepted and pattern was properly returned.
if ((resp & 0xFFF) == vhd_pattern)
@@ -949,7 +1013,7 @@ static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, boo
if (!_sd_storage_execute_app_cmd(storage, R1_SKIP_STATE_CHECK, is_sdsc ? R1_ILLEGAL_COMMAND : 0, &cmdbuf, NULL, NULL))
return 0;
return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3);
return sdmmc_get_cached_rsp(storage->sdmmc, cond, SDMMC_RSP_TYPE_3);
}
static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, bool is_sdsc, int bus_uhs_support)
@@ -972,7 +1036,7 @@ static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, bool is_sdsc, int b
storage->has_sector_access = 1;
// Check if card supports 1.8V signaling.
if (cond & SD_ROCR_S18A && bus_uhs_support)
if (cond & SD_ROCR_S18A && bus_uhs_support && !storage->is_low_voltage)
{
// Switch to 1.8V signaling.
if (_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
@@ -1016,7 +1080,7 @@ static int _sd_storage_get_rca(sdmmc_storage_t *storage)
break;
u32 resp = 0;
if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_4))
if (!sdmmc_get_cached_rsp(storage->sdmmc, &resp, SDMMC_RSP_TYPE_4))
break;
if (resp >> 16)
@@ -1047,11 +1111,17 @@ static void _sd_storage_parse_scr(sdmmc_storage_t *storage)
storage->scr.sda_vsn = unstuff_bits(resp, 56, 4);
storage->scr.bus_widths = unstuff_bits(resp, 48, 4);
/* If v2.0 is supported, check if Physical Layer Spec v3.0 is supported */
// If v2.0 is supported, check if Physical Layer Spec v3.0 is supported.
if (storage->scr.sda_vsn == SCR_SPEC_VER_2)
storage->scr.sda_spec3 = unstuff_bits(resp, 47, 1);
if (storage->scr.sda_spec3)
storage->scr.cmds = unstuff_bits(resp, 32, 2);
{
u8 sda_spec4 = unstuff_bits(resp, 42, 1);
if (sda_spec4)
storage->scr.cmds = unstuff_bits(resp, 32, 4);
else
storage->scr.cmds = unstuff_bits(resp, 32, 2);
}
}
int sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf)
@@ -1071,9 +1141,9 @@ int sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf)
return 0;
u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
//Prepare buffer for unstuff_bits
for (int i = 0; i < 8; i+=4)
for (u32 i = 0; i < 8; i+=4)
{
storage->raw_scr[i + 3] = buf[i];
storage->raw_scr[i + 2] = buf[i + 1];
@@ -1102,7 +1172,7 @@ static int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf)
return 0;
u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
return _sdmmc_storage_check_card_status(tmp);
}
@@ -1126,7 +1196,7 @@ static int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int
return 0;
u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
return _sdmmc_storage_check_card_status(tmp);
}
@@ -1242,7 +1312,7 @@ static int _sd_storage_enable_DDR200(sdmmc_storage_t *storage, u8 *buf)
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;
storage->max_power = total_pwr_consumption;
if (total_pwr_consumption <= 800)
{
@@ -1281,7 +1351,7 @@ static int _sd_storage_set_card_bus_speed(sdmmc_storage_t *storage, u32 hs_type,
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;
storage->max_power = total_pwr_consumption;
if (total_pwr_consumption <= 800)
{
@@ -1493,10 +1563,10 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
_sd_storage_debug_print_ssr(storage->raw_ssr);
#endif
storage->ssr.bus_width = (unstuff_bits(raw_ssr1, 510 - 384, 2) & SD_BUS_WIDTH_4) ? 4 : 1;
storage->ssr.protected_size = unstuff_bits(raw_ssr1, 448 - 384, 32);
storage->ssr.bus_width = (unstuff_bits(raw_ssr1, 510, 2) & SD_BUS_WIDTH_4) ? 4 : 1;
storage->ssr.protected_size = unstuff_bits(raw_ssr1, 448, 32);
u32 speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8);
u32 speed_class = unstuff_bits(raw_ssr1, 440, 8);
switch(speed_class)
{
case 0:
@@ -1514,12 +1584,94 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
storage->ssr.speed_class = speed_class;
break;
}
storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4);
storage->ssr.video_class = unstuff_bits(raw_ssr1, 384 - 384, 8);
storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4);
storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396, 4);
storage->ssr.video_class = unstuff_bits(raw_ssr1, 384, 8);
storage->ssr.app_class = unstuff_bits(raw_ssr2, 336, 4);
storage->ssr.au_size = unstuff_bits(raw_ssr1, 428 - 384, 4);
storage->ssr.uhs_au_size = unstuff_bits(raw_ssr1, 392 - 384, 4);
storage->ssr.au_size = unstuff_bits(raw_ssr1, 428, 4);
storage->ssr.uhs_au_size = unstuff_bits(raw_ssr1, 392, 4);
storage->ssr.perf_enhance = unstuff_bits(raw_ssr2, 328, 8);
}
int sd_storage_parse_perf_enhance(sdmmc_storage_t *storage, u8 fno, u8 page, u16 offset, u8 *buf)
{
// Check status reg for support.
storage->ser.cache = (storage->ssr.perf_enhance >> 2) & BIT(0);
storage->ser.cmdq = (storage->ssr.perf_enhance >> 3) & 0x1F;
if (!sd_storage_get_ext_reg(storage, fno, page, offset, 512, buf))
{
storage->ser.cache_ext = 0;
storage->ser.cmdq_ext = 0;
return 0;
}
storage->ser.cache_ext = buf[4] & BIT(0);
storage->ser.cmdq_ext = buf[6] & 0x1F;
return 1;
}
static void _sd_storage_parse_ext_reg(sdmmc_storage_t *storage, u8 *buf, u16 *addr_next)
{
u16 addr = *addr_next;
// Address to the next extension.
*addr_next = (buf[addr + 41] << 8) | buf[addr + 40];
u16 sfc = (buf[addr + 1] << 8) | buf[addr];
u32 reg_sets = buf[addr + 42];
#ifdef SDMMC_DEBUG_PRINT_SD_REGS
for (u32 i = 0; i < reg_sets; i++)
{
u32 reg_set_addr;
memcpy(&reg_set_addr, &buf[addr + 44 + 4 * i], 4);
u16 off = reg_set_addr & 0x1FF;
u8 page = reg_set_addr >> 9 & 0xFF;
u8 fno = reg_set_addr >> 18 & 0xFF;
gfx_printf("Addr: %04X sfc:%02X - fno:%02X, page:%02X, off:%04X\n", addr, sfc, fno, page, off);
}
#endif
// Parse Performance Enhance.
if (sfc == 2 && reg_sets == 1)
{
u32 reg_set0_addr;
memcpy(&reg_set0_addr, &buf[addr + 44], 4);
u16 off = reg_set0_addr & 0x1FF;
u8 page = reg_set0_addr >> 9 & 0xFF;
u8 fno = reg_set0_addr >> 18 & 0xFF;
if (sd_storage_parse_perf_enhance(storage, fno, page, off, buf))
storage->ser.valid = 1;
}
}
void sd_storage_get_ext_regs(sdmmc_storage_t *storage, u8 *buf)
{
DREGPRINTF("SD Extension Registers:\n\n");
if (!(storage->scr.cmds & BIT(2)))
{
DREGPRINTF("Not Supported!\n");
return;
}
if (!sd_storage_get_ext_reg(storage, 0, 0, 0, 512, buf))
{
DREGPRINTF("Failed to get general info!\n");
return;
}
u16 size = (buf[3] << 8) | buf[2];
u16 addr_next = 16;
u32 num_ext = buf[4];
for (u32 i = 0; i < num_ext && addr_next < size; i++)
_sd_storage_parse_ext_reg(storage, buf, &addr_next);
}
int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
@@ -1545,10 +1697,10 @@ int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
return 0;
u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
// Convert buffer to LE.
for (int i = 0; i < SDMMC_CMD_BLOCKSIZE; i += 4)
for (u32 i = 0; i < SDMMC_CMD_BLOCKSIZE; i += 4)
{
storage->raw_ssr[i + 3] = buf[i];
storage->raw_ssr[i + 2] = buf[i + 1];
@@ -1645,7 +1797,7 @@ void sdmmc_storage_init_wait_sd()
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
{
u32 tmp = 0;
int is_sdsc = 0;
bool is_sdsc = 0;
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER;
bool bus_uhs_support = _sdmmc_storage_get_bus_uhs_support(bus_width, type);
@@ -1790,7 +1942,7 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
return 0;
}
if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_1))
if (!sdmmc_get_cached_rsp(storage->sdmmc, &resp, SDMMC_RSP_TYPE_1))
return 0;
if (!_sdmmc_storage_check_card_status(resp))
return 0;

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2022 CTCaer
* Copyright (c) 2018-2025 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,
@@ -174,20 +174,30 @@ typedef struct _sd_ssr
u8 app_class;
u8 au_size;
u8 uhs_au_size;
u8 perf_enhance;
u32 protected_size;
} sd_ssr_t;
typedef struct _sd_ext_reg_t
{
u8 cmdq;
u8 cmdq_ext;
u8 cache;
u8 cache_ext;
int valid;
} sd_ext_reg_t;
/*! SDMMC storage context. */
typedef struct _sdmmc_storage_t
{
sdmmc_t *sdmmc;
u32 rca;
int has_sector_access;
u32 sec_cnt;
int is_low_voltage;
u32 partition;
int initialized;
u32 card_power_limit;
int is_low_voltage;
int has_sector_access;
u32 rca;
u32 sec_cnt;
u32 partition;
u32 max_power;
u8 raw_cid[0x10];
u8 raw_csd[0x10];
u8 raw_scr[8];
@@ -197,6 +207,7 @@ typedef struct _sdmmc_storage_t
mmc_ext_csd_t ext_csd;
sd_scr_t scr;
sd_ssr_t ssr;
sd_ext_reg_t ser;
} sdmmc_storage_t;
typedef struct _sd_func_modes_t
@@ -221,9 +232,13 @@ int sdmmc_storage_vendor_sandisk_report(sdmmc_storage_t *storage, void *buf);
int mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf);
int sd_storage_get_ext_reg(sdmmc_storage_t *storage, u8 fno, u8 page, u16 offset, u32 len, void *buf);
int sd_storage_get_fmodes(sdmmc_storage_t *storage, u8 *buf, sd_func_modes_t *functions);
int sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf);
int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf);
u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage);
void sd_storage_get_ext_regs(sdmmc_storage_t *storage, u8 *buf);
int sd_storage_parse_perf_enhance(sdmmc_storage_t *storage, u8 fno, u8 page, u16 offset, u8 *buf);
#endif

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2024 CTCaer
* Copyright (c) 2018-2025 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -212,7 +212,7 @@ static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power)
// Use 0x1F mask for all.
u8 autocal_pu_status = sdmmc->regs->autocalsts & 0x1F;
if (!autocal_pu_status)
EPRINTFARGS("SDMMC%d: Comp Pad open!", sdmmc->id + 1);
EPRINTFARGS("SDMMC%d: Comp Pad open!", sdmmc->id + 1); // Or resistance is extreme.
else if (autocal_pu_status == 0x1F)
EPRINTFARGS("SDMMC%d: Comp Pad short to gnd!", sdmmc->id + 1);
#endif
@@ -394,8 +394,8 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
static void _sdmmc_card_clock_enable(sdmmc_t *sdmmc)
{
// Recalibrate conditionally.
if (sdmmc->manual_cal && !sdmmc->powersave_enabled)
// Recalibrate periodically if needed.
if (sdmmc->periodic_calibration && !sdmmc->powersave_enabled)
_sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc));
if (!sdmmc->powersave_enabled)
@@ -414,8 +414,8 @@ static void _sdmmc_card_clock_disable(sdmmc_t *sdmmc)
void sdmmc_card_clock_powersave(sdmmc_t *sdmmc, int powersave_enable)
{
// Recalibrate periodically for SDMMC1.
if (sdmmc->manual_cal && !powersave_enable && sdmmc->card_clock_enabled)
// Recalibrate periodically if needed.
if (sdmmc->periodic_calibration && !powersave_enable && sdmmc->card_clock_enabled)
_sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc));
sdmmc->powersave_enabled = powersave_enable;
@@ -431,7 +431,7 @@ void sdmmc_card_clock_powersave(sdmmc_t *sdmmc, int powersave_enable)
sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN;
}
static int _sdmmc_cache_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
static int _sdmmc_cache_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 type)
{
switch (type)
{
@@ -439,33 +439,14 @@ static int _sdmmc_cache_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
case SDMMC_RSP_TYPE_3:
case SDMMC_RSP_TYPE_4:
case SDMMC_RSP_TYPE_5:
if (size < 4)
return 0;
rsp[0] = sdmmc->regs->rspreg0;
rsp[0] = sdmmc->regs->rspreg[0];
break;
case SDMMC_RSP_TYPE_2:
if (size < 0x10)
return 0;
// CRC is stripped, so shifting is needed.
u32 tempreg;
for (int i = 0; i < 4; i++)
for (u32 i = 0; i < 4; i++)
{
switch(i)
{
case 0:
tempreg = sdmmc->regs->rspreg3;
break;
case 1:
tempreg = sdmmc->regs->rspreg2;
break;
case 2:
tempreg = sdmmc->regs->rspreg1;
break;
case 3:
tempreg = sdmmc->regs->rspreg0;
break;
}
u32 tempreg = sdmmc->regs->rspreg[3 - i];
rsp[i] = tempreg << 8;
if (i != 0)
@@ -480,7 +461,7 @@ static int _sdmmc_cache_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
return 1;
}
int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
int sdmmc_get_cached_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 type)
{
if (!rsp || sdmmc->expected_rsp_type != type)
return 0;
@@ -491,18 +472,12 @@ int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
case SDMMC_RSP_TYPE_3:
case SDMMC_RSP_TYPE_4:
case SDMMC_RSP_TYPE_5:
if (size < 4)
return 0;
rsp[0] = sdmmc->rsp[0];
break;
case SDMMC_RSP_TYPE_2:
if (size < 16)
return 0;
rsp[0] = sdmmc->rsp[0];
rsp[1] = sdmmc->rsp[1];
rsp[2] = sdmmc->rsp[2];
rsp[3] = sdmmc->rsp[3];
for (u32 i = 0; i < 4; i++)
rsp[i] = sdmmc->rsp[i];
break;
default:
@@ -915,6 +890,7 @@ static void _sdmmc_enable_interrupts(sdmmc_t *sdmmc)
sdmmc->regs->errintstsen |= SDHCI_ERR_INT_ALL_EXCEPT_ADMA_BUSPWR;
sdmmc->regs->norintsts = sdmmc->regs->norintsts;
sdmmc->regs->errintsts = sdmmc->regs->errintsts;
sdmmc->error_sts = 0;
}
static void _sdmmc_mask_interrupts(sdmmc_t *sdmmc)
@@ -937,8 +913,9 @@ static u32 _sdmmc_check_mask_interrupt(sdmmc_t *sdmmc, u16 *pout, u16 mask)
if (norintsts & SDHCI_INT_ERROR)
{
#ifdef ERROR_EXTRA_PRINTING
EPRINTFARGS("SDMMC%d: norintsts %08X, errintsts %08X", sdmmc->id + 1, norintsts, errintsts);
EPRINTFARGS("SDMMC%d: intsts %08X, errintsts %08X", sdmmc->id + 1, norintsts, errintsts);
#endif
sdmmc->error_sts = errintsts;
sdmmc->regs->errintsts = errintsts;
return SDMMC_MASKINT_ERROR;
}
@@ -993,7 +970,7 @@ static int _sdmmc_stop_transmission_inner(sdmmc_t *sdmmc, u32 *rsp)
if (!result)
return 0;
_sdmmc_cache_rsp(sdmmc, rsp, 4, SDMMC_RSP_TYPE_1);
_sdmmc_cache_rsp(sdmmc, rsp, SDMMC_RSP_TYPE_1);
return _sdmmc_wait_card_busy(sdmmc);
}
@@ -1003,8 +980,8 @@ int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp)
if (!sdmmc->card_clock_enabled)
return 0;
// Recalibrate periodically for SDMMC1.
if (sdmmc->manual_cal && sdmmc->powersave_enabled)
// Recalibrate periodically if needed.
if (sdmmc->periodic_calibration && sdmmc->powersave_enabled)
_sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc));
bool should_disable_sd_clock = false;
@@ -1120,7 +1097,7 @@ static int _sdmmc_update_sdma(sdmmc_t *sdmmc)
static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out)
{
int has_req_or_check_busy = req || cmd->check_busy;
bool has_req_or_check_busy = req || cmd->check_busy;
if (!_sdmmc_wait_cmd_data_inhibit(sdmmc, has_req_or_check_busy))
return 0;
@@ -1158,13 +1135,13 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
EPRINTFARGS("SDMMC%d: Transfer error!", sdmmc->id + 1);
#endif
DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
sdmmc->regs->rspreg0, sdmmc->regs->rspreg1, sdmmc->regs->rspreg2, sdmmc->regs->rspreg3);
sdmmc->regs->rspreg[0], sdmmc->regs->rspreg[1], sdmmc->regs->rspreg[2], sdmmc->regs->rspreg[3]);
if (result)
{
if (cmd->rsp_type)
{
sdmmc->expected_rsp_type = cmd->rsp_type;
result = _sdmmc_cache_rsp(sdmmc, sdmmc->rsp, 0x10, cmd->rsp_type);
result = _sdmmc_cache_rsp(sdmmc, sdmmc->rsp, cmd->rsp_type);
#ifdef ERROR_EXTRA_PRINTING
if (!result)
EPRINTFARGS("SDMMC%d: Unknown response type!", sdmmc->id + 1);
@@ -1193,10 +1170,10 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
*blkcnt_out = blkcnt;
if (req->is_auto_stop_trn)
sdmmc->rsp3 = sdmmc->regs->rspreg3;
sdmmc->stop_trn_rsp = sdmmc->regs->rspreg[3];
}
if (cmd->check_busy || req)
if (has_req_or_check_busy)
{
result = _sdmmc_wait_card_busy(sdmmc);
#ifdef ERROR_EXTRA_PRINTING
@@ -1248,7 +1225,7 @@ static void _sdmmc_config_sdmmc1_pads(bool discharge)
u32 level = GPIO_LOW;
u32 output = GPIO_OUTPUT_DISABLE;
// Set values for dicharging.
// Set values for discharging.
if (discharge)
{
function = GPIO_MODE_GPIO;
@@ -1304,7 +1281,7 @@ static int _sdmmc_config_sdmmc1(bool t210b01)
// Enable SD card power. Powers LDO2 also.
PINMUX_AUX(PINMUX_AUX_DMIC3_CLK) = PINMUX_PULL_DOWN | 2;
gpio_direction_output(GPIO_PORT_E, GPIO_PIN_4, GPIO_HIGH);
usleep(10000);
usleep(10000); // Minimum 3 to 10 ms.
// Inform IO pads that voltage is gonna be 3.3V.
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_33V_SDMMC1;
@@ -1385,7 +1362,7 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type)
if (sdmmc->t210b01)
vref_sel = 0;
else
sdmmc->manual_cal = 1;
sdmmc->periodic_calibration = 1;
break;
case SDMMC_2:
@@ -1419,6 +1396,8 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type)
if (!_sdmmc_autocal_config_offset(sdmmc, power))
return 0;
_sdmmc_commit_changes(sdmmc);
// Calibrate pads.
_sdmmc_autocal_execute(sdmmc, power);
@@ -1506,8 +1485,8 @@ int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *b
if (!sdmmc->card_clock_enabled)
return 0;
// Recalibrate periodically for SDMMC1.
if (sdmmc->manual_cal && sdmmc->powersave_enabled)
// Recalibrate periodically if needed.
if (sdmmc->periodic_calibration && sdmmc->powersave_enabled)
_sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc));
int should_disable_sd_clock = 0;

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2023 CTCaer
* Copyright (c) 2018-2025 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,
@@ -101,6 +101,7 @@
#define SDHCI_CMD_TYPE_SUSPEND (1U << 6)
#define SDHCI_CMD_TYPE_RESUME (2U << 6)
#define SDHCI_CMD_TYPE_ABORT (3U << 6)
#define SDHCI_CMD_SPI_CS_LOW BIT(7)
#define SDHCI_CMD_IDX(cmd) ((cmd) << 8)
@@ -170,10 +171,10 @@
#define SDHCI_INT_ERROR BIT(15)
/*! 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)
#define SDHCI_ERR_INT_INDEX BIT(3)
#define SDHCI_ERR_INT_CMD_TIMEOUT BIT(0)
#define SDHCI_ERR_INT_CMD_CRC BIT(1)
#define SDHCI_ERR_INT_CMD_END_BIT BIT(2)
#define SDHCI_ERR_INT_CMD_INDEX BIT(3)
#define SDHCI_ERR_INT_DATA_TIMEOUT BIT(4)
#define SDHCI_ERR_INT_DATA_CRC BIT(5)
#define SDHCI_ERR_INT_DATA_END_BIT BIT(6)
@@ -190,8 +191,8 @@
#define SDHCI_ERR_INT_ALL_EXCEPT_ADMA_BUSPWR \
(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)
SDHCI_ERR_INT_CMD_INDEX | SDHCI_ERR_INT_CMD_END_BIT | \
SDHCI_ERR_INT_CMD_CRC | SDHCI_ERR_INT_CMD_TIMEOUT)
/*! Host Capability 1. 0x40. */
#define SDHCI_CAP_TM_CLK_FREQ_MASK 0x3F
@@ -285,14 +286,15 @@ typedef struct _sdmmc_t
u32 card_clock;
u32 clock_stopped;
int powersave_enabled;
int manual_cal;
int periodic_calibration;
int card_clock_enabled;
int venclkctl_set;
u32 venclkctl_tap;
u32 expected_rsp_type;
u32 dma_addr_next;
u32 rsp[4];
u32 rsp3;
u32 stop_trn_rsp;
u32 error_sts;
int t210b01;
} sdmmc_t;
@@ -323,7 +325,7 @@ 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_get_cached_rsp(sdmmc_t *sdmmc, u32 *rsp, 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();

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2023 CTCaer
* Copyright (c) 2018-2025 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -39,10 +39,7 @@ typedef struct _t210_sdmmc_t
/* 0x08 */ vu32 argument;
/* 0x0C */ vu16 trnmod;
/* 0x0E */ vu16 cmdreg;
/* 0x10 */ vu32 rspreg0;
/* 0x14 */ vu32 rspreg1;
/* 0x18 */ vu32 rspreg2;
/* 0x1C */ vu32 rspreg3;
/* 0x10 */ vu32 rspreg[4];
/* 0x20 */ vu32 bdata; // Buffer data port.
/* 0x24 */ vu32 prnsts;
/* 0x28 */ vu8 hostctl;

View File

@@ -99,7 +99,7 @@ typedef struct _usb_cfg_descr_t
u8 bConfigurationValue; // Value of this configuration (1 based).
u8 iConfiguration; // Index of String Descriptor describing the configuration.
u8 bmAttributes; // Configuration characteristics.
u8 bMaxPower; // Maximum power consumed by this configuration.
u8 bMaxPower; // Maximum power consumed by this configuration. In 2mA (usb2) or 8mA (usb3).
} __attribute__((packed)) usb_cfg_descr_t;
/* Interface descriptor structure */

View File

@@ -410,7 +410,7 @@ int usb_device_gadget_hid(usb_ctxt_t *usbs)
gadget_type = USB_GADGET_HID_TOUCHPAD;
}
usbs->set_text(usbs->label, "#C7EA46 状态:#开启USB");
usbs->set_text(usbs->label, "#C7EA46 状态:#USB1已开启");
if (usb_ops.usb_device_init())
{
@@ -418,18 +418,18 @@ int usb_device_gadget_hid(usb_ctxt_t *usbs)
return 1;
}
usbs->set_text(usbs->label, "#C7EA46 状态:#等待连接");
usbs->set_text(usbs->label, "#C7EA46 状态:#等待连接");
// Initialize Control Endpoint.
if (usb_ops.usb_device_enumerate(gadget_type))
goto error;
usbs->set_text(usbs->label, "#C7EA46 状态:#等待HID上报请求");
usbs->set_text(usbs->label, "#C7EA46 状态:#等待HID上报请求");
if (usb_ops.usb_device_class_send_hid_report())
goto error;
usbs->set_text(usbs->label, "#C7EA46 状态:#开始HID模拟");
usbs->set_text(usbs->label, "#C7EA46 状态:#HID模拟已开启");
u32 timer_sys = get_tmr_ms() + 5000;
while (true)
@@ -467,11 +467,11 @@ int usb_device_gadget_hid(usb_ctxt_t *usbs)
}
}
usbs->set_text(usbs->label, "#C7EA46 状态:#HID结束");
usbs->set_text(usbs->label, "#C7EA46 状态:#HID结束");
goto exit;
error:
usbs->set_text(usbs->label, "#FFDD00 错误:#超时或取消");
usbs->set_text(usbs->label, "#FFDD00 错误:#超时或取消");
res = 1;
exit:

View File

@@ -332,7 +332,7 @@ static void _transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32
_flush_endpoint(bulk_ctxt->bulk_in);
}
else if (bulk_ctxt->bulk_in_status == USB2_ERROR_XFER_NOT_ALIGNED)
ums->set_text(ums->label, "#FFDD00 错误:#EP IN缓冲区未对齐");
ums->set_text(ums->label, "#FFDD00 错误:#EP IN缓冲区未对齐");
if (sync_timeout)
bulk_ctxt->bulk_in_buf_state = BUF_STATE_EMPTY;
@@ -364,7 +364,7 @@ static void _transfer_out_big_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctx
if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR)
{
ums->set_text(ums->label, "#FFDD00 错误:#EP OUT传输");
ums->set_text(ums->label, "#FFDD00 错误:#EP OUT传输");
_flush_endpoint(bulk_ctxt->bulk_out);
}
@@ -463,7 +463,7 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
}
if (lba_offset >= ums->lun.num_sectors)
{
ums->set_text(ums->label, "#FF8000 警告:#读 - 超出范围!主机通知");
ums->set_text(ums->label, "#FF8000 警告:#读 - 超出范围!已通知主机。");
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
return UMS_RES_INVALID_ARG;
@@ -515,7 +515,7 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
// If an error occurred, report it and its position.
if (!amount)
{
ums->set_text(ums->label, "#FFDD00 错误:# SDMMC读");
ums->set_text(ums->label, "#FFDD00 错误:# SDMMC读");
ums->lun.sense_data = SS_UNRECOVERED_READ_ERROR;
ums->lun.sense_data_info = lba_offset;
ums->lun.info_valid = 1;
@@ -553,7 +553,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
if (ums->lun.ro)
{
ums->set_text(ums->label, "#FF8000 警告:#写 - 只读!主机通知");
ums->set_text(ums->label, "#FF8000 警告:#写 - 只读!已通知主机。");
ums->lun.sense_data = SS_WRITE_PROTECTED;
return UMS_RES_INVALID_ARG;
@@ -577,7 +577,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
// Check that starting LBA is not past the end sector offset.
if (lba_offset >= ums->lun.num_sectors)
{
ums->set_text(ums->label, "#FF8000 警告:#写 - 超出范围!主机通知");
ums->set_text(ums->label, "#FF8000 警告:#写 - 超出范围!已通知主机。");
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
return UMS_RES_INVALID_ARG;
@@ -599,7 +599,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
if (usb_lba_offset >= ums->lun.num_sectors)
{
ums->set_text(ums->label, "#FFDD00 错误:#写 - 超出最后扇区!");
ums->set_text(ums->label, "#FFDD00 错误:#写 - 超出最后扇区!");
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
ums->lun.sense_data_info = usb_lba_offset;
ums->lun.info_valid = 1;
@@ -627,7 +627,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
ums->lun.sense_data_info = lba_offset;
ums->lun.info_valid = 1;
s_printf(txt_buf, "#FFDD00 错误:#写 - 通讯失败 %d", bulk_ctxt->bulk_out_status);
s_printf(txt_buf, "#FFDD00 错误:#写 - 通讯失败 %d", bulk_ctxt->bulk_out_status);
ums->set_text(ums->label, txt_buf);
break;
}
@@ -665,7 +665,7 @@ DPRINTF("file write %X @ %X\n", amount, lba_offset);
// If an error occurred, report it and its position.
if (!amount)
{
ums->set_text(ums->label, "#FFDD00 错误:#SDMMC写");
ums->set_text(ums->label, "#FFDD00 错误:#SDMMC写");
ums->lun.sense_data = SS_WRITE_ERROR;
ums->lun.sense_data_info = lba_offset;
ums->lun.info_valid = 1;
@@ -676,7 +676,7 @@ DPRINTF("file write %X @ %X\n", amount, lba_offset);
// Did the host decide to stop early?
if (bulk_ctxt->bulk_out_length_actual < bulk_ctxt->bulk_out_length)
{
ums->set_text(ums->label, "#FFDD00 错误:#写空!");
ums->set_text(ums->label, "#FFDD00 错误:#空写入");
ums->short_packet_received = 1;
break;
}
@@ -692,7 +692,7 @@ static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
u32 lba_offset = get_array_be_to_le32(&ums->cmnd[2]);
if (lba_offset >= ums->lun.num_sectors)
{
ums->set_text(ums->label, "#FF8000 警告:#验 - 超出范围!主机通知");
ums->set_text(ums->label, "#FF8000 警告:#验 - 超出范围!已通知主机。");
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
return UMS_RES_INVALID_ARG;
@@ -1060,7 +1060,7 @@ static int _scsi_start_stop(usbd_gadget_ums_t *ums)
// Check if we are allowed to unload the media.
if (ums->lun.prevent_medium_removal)
{
ums->set_text(ums->label, "#C7EA46 状态:#卸载尝试被阻止");
ums->set_text(ums->label, "#C7EA46 状态:#卸载尝试被阻止");
ums->lun.sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
return UMS_RES_INVALID_ARG;
@@ -1468,7 +1468,7 @@ static int _finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{
_set_ep_stall(bulk_ctxt->bulk_out);
rc = _set_ep_stall(bulk_ctxt->bulk_in);
ums->set_text(ums->label, "#FFDD00 错误:#方向不明。两端EP都停了");
ums->set_text(ums->label, "#FFDD00 错误:#方向不明。两端EP已暂停");
} // Else do nothing.
break;
@@ -1489,7 +1489,7 @@ static int _finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{
_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_DATA);
rc = _set_ep_stall(bulk_ctxt->bulk_in);
ums->set_text(ums->label, "#FFDD00 错误:#数据残留。EP IN停止");
ums->set_text(ums->label, "#FFDD00 错误:#数据残留。EP IN停止!");
}
else
rc = _pad_with_zeros(ums, bulk_ctxt);
@@ -1633,7 +1633,7 @@ static int _received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{
_set_ep_stall(bulk_ctxt->bulk_out);
_set_ep_stall(bulk_ctxt->bulk_in);
ums->set_text(ums->label, "#FFDD00 错误:#CBW未知 - 两端EP都停了");
ums->set_text(ums->label, "#FFDD00 错误:#CBW未知 - 两端EP已停止");
}
return UMS_RES_INVALID_ARG;
@@ -1826,7 +1826,7 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
xusb_device_get_ops(&usb_ops);
}
usbs->set_text(usbs->label, "#C7EA46 状态:#开启USB");
usbs->set_text(usbs->label, "#C7EA46 状态:#USB已开启");
if (usb_ops.usb_device_init())
{
@@ -1857,7 +1857,7 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
ums.set_text = usbs->set_text;
ums.system_maintenance = usbs->system_maintenance;
ums.set_text(ums.label, "#C7EA46 状态:#挂载磁盘");
ums.set_text(ums.label, "#C7EA46 状态:#磁盘挂载中");
// Initialize sdmmc.
if (usbs->type == MMC_SD)
@@ -1888,18 +1888,18 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
ums.lun.storage = &emmc_storage;
}
ums.set_text(ums.label, "#C7EA46 状态:#等待连接");
ums.set_text(ums.label, "#C7EA46 状态:#连接等待中");
// Initialize Control Endpoint.
if (usb_ops.usb_device_enumerate(USB_GADGET_UMS))
goto usb_enum_error;
ums.set_text(ums.label, "#C7EA46 状态:#等待LUN");
ums.set_text(ums.label, "#C7EA46 状态:#LUN等待中");
if (usb_ops.usb_device_class_send_max_lun(0)) // One device for now.
goto usb_enum_error;
ums.set_text(ums.label, "#C7EA46 状态:#开启UMS");
ums.set_text(ums.label, "#C7EA46 状态:#UMS已开启");
// If partition sectors are not set get them from hardware.
if (!ums.lun.num_sectors)
@@ -1920,7 +1920,7 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
{
// Check if we are allowed to unload the media.
if (ums.lun.prevent_medium_removal)
ums.set_text(ums.label, "#C7EA46 状态:#卸载尝试被阻止");
ums.set_text(ums.label, "#C7EA46 状态:#卸载尝试被阻止");
else
break;
}
@@ -1952,13 +1952,13 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
} while (ums.state != UMS_STATE_TERMINATED);
if (ums.lun.prevent_medium_removal)
ums.set_text(ums.label, "#FFDD00 错误:#磁盘安全弹出");
ums.set_text(ums.label, "#FFDD00 错误:#磁盘已未安全弹出");
else
ums.set_text(ums.label, "#C7EA46 状态:#磁盘弹出");
ums.set_text(ums.label, "#C7EA46 状态:#磁盘弹出");
goto exit;
usb_enum_error:
ums.set_text(ums.label, "#FFDD00 错误:#超时或取消!");
ums.set_text(ums.label, "#FFDD00 错误:#超时或取消!");
res = 1;
exit:

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2024 CTCaer
* Copyright (c) 2018-2025 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,
@@ -82,12 +82,12 @@ dirlist_t *dirlist(const char *directory, const char *pattern, bool includeHidde
// Terminate name list.
dir_entries->name[k] = NULL;
// Reorder ini files by ASCII ordering.
// Reorder ini files Alphabetically.
for (u32 i = 0; i < k - 1 ; i++)
{
for (u32 j = i + 1; j < k; j++)
{
if (strcmp(dir_entries->name[i], dir_entries->name[j]) > 0)
if (strcasecmp(dir_entries->name[i], dir_entries->name[j]) > 0)
{
char *tmp = dir_entries->name[i];
dir_entries->name[i] = dir_entries->name[j];

View File

@@ -172,14 +172,14 @@ parse_padding_dec:
_s_putc(c);
break;
case 's':
_s_puts(va_arg(ap, char *), fill, fcnt);
break;
case 'd':
_s_putn(va_arg(ap, u32), 10, fill, fcnt);
break;
case 's':
_s_puts(va_arg(ap, char *), fill, fcnt);
break;
case 'p':
case 'P':
case 'x':
@@ -261,14 +261,14 @@ parse_padding_dec:
_s_putc(c);
break;
case 's':
_s_puts(va_arg(ap, char *), fill, fcnt);
break;
case 'd':
_s_putn(va_arg(ap, u32), 10, fill, fcnt);
break;
case 's':
_s_puts(va_arg(ap, char *), fill, fcnt);
break;
case 'p':
case 'P':
case 'x':

View File

@@ -1,19 +1,19 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2024 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2025 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
@@ -136,7 +136,7 @@ long strtol(const char *nptr, char **endptr, register int base)
} else if (c == '+')
c = *s++;
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
@@ -260,6 +260,21 @@ u32 crc32_calc(u32 crc, const u8 *buf, u32 len)
return ~crc;
}
int qsort_compare_int(const void *a, const void *b)
{
return (*(int *)a - *(int *)b);
}
int qsort_compare_char(const void *a, const void *b)
{
return strcmp(*(const char **)a, *(const char **)b);
}
int qsort_compare_char_case(const void *a, const void *b)
{
return strcasecmp(*(const char **)a, *(const char **)b);
}
void panic(u32 val)
{
// Set panic code.

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2024 CTCaer
* Copyright (c) 2018-2025 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,
@@ -97,6 +97,10 @@ void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops);
u16 crc16_calc(const u8 *buf, u32 len);
u32 crc32_calc(u32 crc, const u8 *buf, u32 len);
int qsort_compare_int(const void *a, const void *b);
int qsort_compare_char(const void *a, const void *b);
int qsort_compare_char_case(const void *a, const void *b);
void panic(u32 val);
void power_set_state(power_state_t state);
void power_set_state_ex(void *param);