sdmmc: Refactor again

- Refactor various variables and defines
- Removed Card/BGA and OEM ID info as they are static and useless
- Commented out bkops functions completely as not used
- Remove extra buf usage when there's already storage for storing that data
- Optimize various functions to save space
- Clean up useless or duplicate code
This commit is contained in:
CTCaer 2021-02-06 03:41:35 +02:00
parent a980eac647
commit 38f456a2ee
9 changed files with 228 additions and 215 deletions

View file

@ -84,6 +84,11 @@
#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */ #define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */ #define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */
#define MMC_VENDOR_60_CMD 60 /* Vendor Defined */
#define MMC_VENDOR_61_CMD 61 /* Vendor Defined */
#define MMC_VENDOR_62_CMD 62 /* Vendor Defined */
#define MMC_VENDOR_63_CMD 63 /* Vendor Defined */
/* class 11 */ /* class 11 */
#define MMC_QUE_TASK_PARAMS 44 /* ac [20:16] task id R1 */ #define MMC_QUE_TASK_PARAMS 44 /* ac [20:16] task id R1 */
#define MMC_QUE_TASK_ADDR 45 /* ac [31:0] data addr R1 */ #define MMC_QUE_TASK_ADDR 45 /* ac [31:0] data addr R1 */
@ -182,7 +187,10 @@ c : clear by read
/* /*
* OCR bits are mostly in host.h * OCR bits are mostly in host.h
*/ */
#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */ #define MMC_CARD_VDD_18 (1 << 7) /* Card VDD voltage 1.8 */
#define MMC_CARD_VDD_27_34 (0x7F << 15) /* Card VDD voltage 2.7 ~ 3.4 */
#define MMC_CARD_CCS (1 << 30) /* Card Capacity status bit */
#define MMC_CARD_BUSY (1 << 31) /* Card Power up status bit */
/* /*
* Card Command Classes (CCC) * Card Command Classes (CCC)
@ -244,6 +252,7 @@ c : clear by read
#define EXT_CSD_GP_SIZE_MULT 143 /* R/W */ #define EXT_CSD_GP_SIZE_MULT 143 /* R/W */
#define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */ #define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */
#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */ #define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */
#define EXT_CSD_MAX_ENH_SIZE_MULT 157 /* RO, 3 bytes */
#define EXT_CSD_PARTITION_SUPPORT 160 /* RO */ #define EXT_CSD_PARTITION_SUPPORT 160 /* RO */
#define EXT_CSD_HPI_MGMT 161 /* R/W */ #define EXT_CSD_HPI_MGMT 161 /* R/W */
#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */ #define EXT_CSD_RST_N_FUNCTION 162 /* R/W */

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2019 CTCaer * Copyright (c) 2018-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -45,6 +45,7 @@ extern FATFS sd_fs;
void sd_error_count_increment(u8 type); void sd_error_count_increment(u8 type);
u16 *sd_get_error_count(); u16 *sd_get_error_count();
bool sd_get_card_removed(); bool sd_get_card_removed();
bool sd_get_card_initialized();
u32 sd_get_mode(); u32 sd_get_mode();
int sd_init_retry(bool power_cycle); int sd_init_retry(bool power_cycle);
bool sd_initialize(bool power_cycle); bool sd_initialize(bool power_cycle);

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2005-2007 Pierre Ossman, All Rights Reserved. * Copyright (c) 2005-2007 Pierre Ossman, All Rights Reserved.
* Copyright (c) 2018 CTCaer * Copyright (c) 2018-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,60 +14,79 @@
/* SD commands type argument response */ /* SD commands type argument response */
/* class 0 */ /* class 0 */
/* This is basically the same command as for MMC with some quirks. */ /* This is basically the same command as for MMC with some quirks. */
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */ #define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */ #define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */
#define SD_SWITCH_VOLTAGE 11 /* ac R1 */ #define SD_SWITCH_VOLTAGE 11 /* ac R1 */
/* class 10 */ /* class 10 */
#define SD_SWITCH 6 /* adtc [31:0] See below R1 */ #define SD_SWITCH 6 /* adtc [31:0] See below R1 */
/* class 5 */ /* class 5 */
#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */ #define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */
#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */ #define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */
/* Application commands */ /* Application commands */
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */ #define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
#define SD_APP_SD_STATUS 13 /* adtc R1 */ #define SD_APP_SD_STATUS 13 /* adtc R1 */
#define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */ #define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */
#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */ #define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */
#define SD_APP_SET_CLR_CARD_DETECT 42 #define SD_APP_SET_CLR_CARD_DETECT 42 /* adtc R1 */
#define SD_APP_SEND_SCR 51 /* adtc R1 */ #define SD_APP_SEND_SCR 51 /* adtc R1 */
/* Application secure commands */
#define SD_APP_SECURE_READ_MULTI_BLOCK 18 /* adtc R1 */
#define SD_APP_SECURE_WRITE_MULTI_BLOCK 25 /* adtc R1 */
#define SD_APP_SECURE_WRITE_MKB 26 /* adtc R1 */
#define SD_APP_SECURE_ERASE 38 /* adtc R1b */
#define SD_APP_GET_MKB 43 /* adtc [31:0] See below R1 */
#define SD_APP_GET_MID 44 /* adtc R1 */
#define SD_APP_SET_CER_RN1 45 /* adtc R1 */
#define SD_APP_GET_CER_RN2 46 /* adtc R1 */
#define SD_APP_SET_CER_RES2 47 /* adtc R1 */
#define SD_APP_GET_CER_RES1 48 /* adtc R1 */
#define SD_APP_CHANGE_SECURE_AREA 49 /* adtc R1b */
/* OCR bit definitions */ /* OCR bit definitions */
#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */ #define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */
#define SD_OCR_XPC (1 << 28) /* SDXC power control */ #define SD_VHD_27_36 (1 << 8) /* VDD voltage 2.7 ~ 3.6 */
#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_VDD_27_34 (0x7F << 15) /* VDD voltage 2.7 ~ 3.4 */ #define SD_OCR_VDD_27_34 (0x7F << 15) /* VDD voltage 2.7 ~ 3.4 */
#define SD_OCR_VDD_32_33 (1 << 20) /* VDD voltage 3.2 ~ 3.3 */ #define SD_OCR_VDD_32_33 (1 << 20) /* VDD voltage 3.2 ~ 3.3 */
#define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */ #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_VHD_27_36 (1 << 8) /* VDD voltage 2.7 ~ 3.6 */ #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 */
/* /*
* SD_SWITCH argument format: * SD_SWITCH argument format:
* *
* [31] Check (0) or switch (1) * [31] Check (0) or switch (1)
* [30:24] Reserved (0) * [30:24] Reserved (0)
* [23:20] Function group 6 * [23:20] Function group 6
* [19:16] Function group 5 * [19:16] Function group 5
* [15:12] Function group 4 * [15:12] Function group 4
* [11:8] Function group 3 * [11:8] Function group 3
* [7:4] Function group 2 * [7:4] Function group 2
* [3:0] Function group 1 * [3:0] Function group 1
*/ */
/* /*
* SD_SEND_IF_COND argument format: * SD_SEND_IF_COND argument format:
* *
* [31:12] Reserved (0) * [31:12] Reserved (0)
* [11:8] Host Voltage Supply Flags * [11:8] Host Voltage Supply Flags
* [7:0] Check Pattern (0xAA) * [7:0] Check Pattern (0xAA)
*/ */
/* /*
* SCR field definitions * SD_APP_GET_MKB argument format:
*/ *
* [31:24] Number of blocks to read (512 block size)
* [23:16] MKB ID
* [15:0] Block offset
*/
/*
* SCR field definitions
*/
#define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */ #define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */
#define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */ #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 SCR_SPEC_VER_2 2 /* Implements system specification 2.00-3.0X */
@ -75,14 +94,14 @@
#define SD_SCR_BUS_WIDTH_4 (1<<2) #define SD_SCR_BUS_WIDTH_4 (1<<2)
/* /*
* SD bus widths * SD bus widths
*/ */
#define SD_BUS_WIDTH_1 0 #define SD_BUS_WIDTH_1 0
#define SD_BUS_WIDTH_4 2 #define SD_BUS_WIDTH_4 2
/* /*
* SD bus speeds * SD bus speeds
*/ */
#define UHS_SDR12_BUS_SPEED 0 #define UHS_SDR12_BUS_SPEED 0
#define HIGH_SPEED_BUS_SPEED 1 #define HIGH_SPEED_BUS_SPEED 1
#define UHS_SDR25_BUS_SPEED 1 #define UHS_SDR25_BUS_SPEED 1
@ -112,19 +131,19 @@
#define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800) #define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800)
/* /*
* SD_SWITCH mode * SD_SWITCH mode
*/ */
#define SD_SWITCH_CHECK 0 #define SD_SWITCH_CHECK 0
#define SD_SWITCH_SET 1 #define SD_SWITCH_SET 1
/* /*
* SD_SWITCH function groups * SD_SWITCH function groups
*/ */
#define SD_SWITCH_GRP_ACCESS 0 #define SD_SWITCH_GRP_ACCESS 0
/* /*
* SD_SWITCH access modes * SD_SWITCH access modes
*/ */
#define SD_SWITCH_ACCESS_DEF 0 #define SD_SWITCH_ACCESS_DEF 0
#define SD_SWITCH_ACCESS_HS 1 #define SD_SWITCH_ACCESS_HS 1

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -42,8 +42,8 @@ static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size)
} }
/* /*
* Common functions for SD and MMC. * Common functions for SD and MMC.
*/ */
static int _sdmmc_storage_check_card_status(u32 res) static int _sdmmc_storage_check_card_status(u32 res)
{ {
@ -88,20 +88,20 @@ static int _sdmmc_storage_execute_cmd_type1(sdmmc_storage_t *storage, u32 cmd, u
static int _sdmmc_storage_go_idle_state(sdmmc_storage_t *storage) static int _sdmmc_storage_go_idle_state(sdmmc_storage_t *storage)
{ {
sdmmc_cmd_t cmd; sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmd, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0); sdmmc_init_cmd(&cmdbuf, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0);
return sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL); return sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL);
} }
static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage, void *buf) static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage)
{ {
sdmmc_cmd_t cmd; sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmd, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0); sdmmc_init_cmd(&cmdbuf, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0; return 0;
sdmmc_get_rsp(storage->sdmmc, buf, 16, SDMMC_RSP_TYPE_2); sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_cid, 16, SDMMC_RSP_TYPE_2);
return 1; return 1;
} }
@ -111,14 +111,14 @@ static int _sdmmc_storage_select_card(sdmmc_storage_t *storage)
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SELECT_CARD, storage->rca << 16, 1, R1_SKIP_STATE_CHECK); return _sdmmc_storage_execute_cmd_type1(storage, MMC_SELECT_CARD, storage->rca << 16, 1, R1_SKIP_STATE_CHECK);
} }
static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage, void *buf) static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage)
{ {
sdmmc_cmd_t cmdbuf; sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0); sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0; return 0;
sdmmc_get_rsp(storage->sdmmc, buf, 16, SDMMC_RSP_TYPE_2); sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_csd, 16, SDMMC_RSP_TYPE_2);
return 1; return 1;
} }
@ -152,7 +152,7 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
reqbuf.blksize = 512; reqbuf.blksize = 512;
reqbuf.is_write = is_write; reqbuf.is_write = is_write;
reqbuf.is_multi_block = 1; reqbuf.is_multi_block = 1;
reqbuf.is_auto_cmd12 = 1; reqbuf.is_auto_stop_trn = 1;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, blkcnt_out)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, blkcnt_out))
{ {
@ -288,25 +288,25 @@ int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, v
static int _mmc_storage_get_op_cond_inner(sdmmc_storage_t *storage, u32 *pout, u32 power) static int _mmc_storage_get_op_cond_inner(sdmmc_storage_t *storage, u32 *pout, u32 power)
{ {
sdmmc_cmd_t cmd; sdmmc_cmd_t cmdbuf;
u32 arg = 0; u32 arg = 0;
switch (power) switch (power)
{ {
case SDMMC_POWER_1_8: case SDMMC_POWER_1_8:
arg = SD_OCR_CCS | SD_OCR_VDD_18; arg = MMC_CARD_CCS | MMC_CARD_VDD_18;
break; break;
case SDMMC_POWER_3_3: case SDMMC_POWER_3_3:
arg = SD_OCR_CCS | SD_OCR_VDD_27_34; arg = MMC_CARD_CCS | MMC_CARD_VDD_27_34;
break; break;
default: default:
return 0; return 0;
} }
sdmmc_init_cmd(&cmd, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0); sdmmc_init_cmd(&cmdbuf, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0; return 0;
return sdmmc_get_rsp(storage->sdmmc, pout, 4, SDMMC_RSP_TYPE_3); return sdmmc_get_rsp(storage->sdmmc, pout, 4, SDMMC_RSP_TYPE_3);
@ -316,15 +316,17 @@ static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power)
{ {
u32 timeout = get_tmr_ms() + 1500; u32 timeout = get_tmr_ms() + 1500;
while (1) while (true)
{ {
u32 cond = 0; u32 cond = 0;
if (!_mmc_storage_get_op_cond_inner(storage, &cond, power)) if (!_mmc_storage_get_op_cond_inner(storage, &cond, power))
break; break;
// Check if power up is done.
if (cond & MMC_CARD_BUSY) if (cond & MMC_CARD_BUSY)
{ {
if (cond & SD_OCR_CCS) // Check if card is high capacity.
if (cond & MMC_CARD_CCS)
storage->has_sector_access = 1; storage->has_sector_access = 1;
return 1; return 1;
@ -362,7 +364,6 @@ static void _mmc_storage_parse_cid(sdmmc_storage_t *storage)
case 3: /* MMC v3.1 - v3.3 */ case 3: /* MMC v3.1 - v3.3 */
case 4: /* MMC v4 */ case 4: /* MMC v4 */
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8); storage->cid.manfid = unstuff_bits(raw_cid, 120, 8);
storage->cid.card_bga = unstuff_bits(raw_cid, 112, 2);
storage->cid.oemid = unstuff_bits(raw_cid, 104, 8); storage->cid.oemid = unstuff_bits(raw_cid, 104, 8);
storage->cid.prv = unstuff_bits(raw_cid, 48, 8); storage->cid.prv = unstuff_bits(raw_cid, 48, 8);
storage->cid.serial = unstuff_bits(raw_cid, 16, 32); storage->cid.serial = unstuff_bits(raw_cid, 16, 32);
@ -390,13 +391,14 @@ static void _mmc_storage_parse_cid(sdmmc_storage_t *storage)
static void _mmc_storage_parse_csd(sdmmc_storage_t *storage) static void _mmc_storage_parse_csd(sdmmc_storage_t *storage)
{ {
u32 *raw_csd = (u32 *)&(storage->raw_csd); u32 *raw_csd = (u32 *)storage->raw_csd;
storage->csd.mmca_vsn = unstuff_bits(raw_csd, 122, 4); storage->csd.mmca_vsn = unstuff_bits(raw_csd, 122, 4);
storage->csd.structure = unstuff_bits(raw_csd, 126, 2); storage->csd.structure = unstuff_bits(raw_csd, 126, 2);
storage->csd.cmdclass = unstuff_bits(raw_csd, 84, 12); storage->csd.cmdclass = unstuff_bits(raw_csd, 84, 12);
storage->csd.read_blkbits = unstuff_bits(raw_csd, 80, 4); 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->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) static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
@ -407,16 +409,15 @@ static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
storage->ext_csd.dev_version = *(u16 *)&buf[EXT_CSD_DEVICE_VERSION]; storage->ext_csd.dev_version = *(u16 *)&buf[EXT_CSD_DEVICE_VERSION];
storage->ext_csd.boot_mult = buf[EXT_CSD_BOOT_MULT]; storage->ext_csd.boot_mult = buf[EXT_CSD_BOOT_MULT];
storage->ext_csd.rpmb_mult = buf[EXT_CSD_RPMB_MULT]; storage->ext_csd.rpmb_mult = buf[EXT_CSD_RPMB_MULT];
storage->ext_csd.sectors = *(u32 *)&buf[EXT_CSD_SEC_CNT]; //storage->ext_csd.bkops = buf[EXT_CSD_BKOPS_SUPPORT];
storage->ext_csd.bkops = buf[EXT_CSD_BKOPS_SUPPORT]; //storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN];
storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN]; //storage->ext_csd.bkops_status = buf[EXT_CSD_BKOPS_STATUS];
storage->ext_csd.bkops_status = buf[EXT_CSD_BKOPS_STATUS];
storage->ext_csd.pre_eol_info = buf[EXT_CSD_PRE_EOL_INFO]; storage->ext_csd.pre_eol_info = buf[EXT_CSD_PRE_EOL_INFO];
storage->ext_csd.dev_life_est_a = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A]; storage->ext_csd.dev_life_est_a = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A];
storage->ext_csd.dev_life_est_b = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B]; storage->ext_csd.dev_life_est_b = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B];
storage->sec_cnt = *(u32 *)&buf[EXT_CSD_SEC_CNT]; storage->sec_cnt = *(u32 *)&buf[EXT_CSD_SEC_CNT];
} }
static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf) static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
@ -430,7 +431,7 @@ static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
reqbuf.num_sectors = 1; reqbuf.num_sectors = 1;
reqbuf.is_write = 0; reqbuf.is_write = 0;
reqbuf.is_multi_block = 0; reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0; reqbuf.is_auto_stop_trn = 0;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
return 0; return 0;
@ -559,19 +560,21 @@ out:
return 1; return 1;
} }
/*
static int _mmc_storage_enable_bkops(sdmmc_storage_t *storage) static int _mmc_storage_enable_bkops(sdmmc_storage_t *storage)
{ {
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_BKOPS_LEVEL_2))) if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_AUTO_BKOPS_MASK)))
return 0; return 0;
return _sdmmc_storage_check_status(storage); return _sdmmc_storage_check_status(storage);
} }
*/
int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type) int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
{ {
memset(storage, 0, sizeof(sdmmc_storage_t)); memset(storage, 0, sizeof(sdmmc_storage_t));
storage->sdmmc = sdmmc; storage->sdmmc = sdmmc;
storage->rca = 2; //TODO: this could be a config item. storage->rca = 2; // Set default device address. This could be a config item.
if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_MMC_ID, SDMMC_POWER_SAVE_DISABLE)) if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_MMC_ID, SDMMC_POWER_SAVE_DISABLE))
return 0; return 0;
@ -587,7 +590,7 @@ DPRINTF("[MMC] went to idle state\n");
return 0; return 0;
DPRINTF("[MMC] got op cond\n"); DPRINTF("[MMC] got op cond\n");
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid)) if (!_sdmmc_storage_get_cid(storage))
return 0; return 0;
DPRINTF("[MMC] got cid\n"); DPRINTF("[MMC] got cid\n");
@ -595,7 +598,7 @@ DPRINTF("[MMC] got cid\n");
return 0; return 0;
DPRINTF("[MMC] set relative addr\n"); DPRINTF("[MMC] set relative addr\n");
if (!_sdmmc_storage_get_csd(storage, storage->raw_csd)) if (!_sdmmc_storage_get_csd(storage))
return 0; return 0;
DPRINTF("[MMC] got csd\n"); DPRINTF("[MMC] got csd\n");
_mmc_storage_parse_csd(storage); _mmc_storage_parse_csd(storage);
@ -612,13 +615,9 @@ DPRINTF("[MMC] card selected\n");
return 0; return 0;
DPRINTF("[MMC] set blocklen to 512\n"); DPRINTF("[MMC] set blocklen to 512\n");
u32 *csd = (u32 *)storage->raw_csd; // Check system specification version, only version 4.0 and later support below features.
//Check system specification version, only version 4.0 and later support below features. if (storage->csd.mmca_vsn < CSD_SPEC_VER_4)
if (unstuff_bits(csd, 122, 4) < CSD_SPEC_VER_4)
{
storage->sec_cnt = (1 + unstuff_bits(csd, 62, 12)) << (unstuff_bits(csd, 47, 3) + 2);
return 1; return 1;
}
if (!_mmc_storage_switch_buswidth(storage, bus_width)) if (!_mmc_storage_switch_buswidth(storage, bus_width))
return 0; return 0;
@ -628,21 +627,20 @@ DPRINTF("[MMC] switched buswidth\n");
return 0; 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 _mmc_storage_parse_cid(storage); // This needs to be after csd and ext_csd.
//gfx_hexdump(0, ext_csd, 512); //gfx_hexdump(0, ext_csd, 512);
/* When auto BKOPS is enabled the mmc device should be powered all the time until we disable this and check status. /*
Disable it for now until BKOPS disable added to power down sequence at sdmmc_storage_end(). if (storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_AUTO_BKOPS_MASK))
Additionally this works only when we put the device in idle mode which we don't after enabling it. */
if (0 && storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_BKOPS_LEVEL_2))
{ {
_mmc_storage_enable_bkops(storage); _mmc_storage_enable_bkops(storage);
DPRINTF("[MMC] BKOPS enabled\n"); DPRINTF("[MMC] BKOPS enabled\n");
} }
*/
if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type)) if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type))
return 0; return 0;
DPRINTF("[MMC] succesfully switched to HS mode\n"); DPRINTF("[MMC] successfully switched to HS mode\n");
sdmmc_card_clock_powersave(storage->sdmmc, SDMMC_POWER_SAVE_ENABLE); sdmmc_card_clock_powersave(storage->sdmmc, SDMMC_POWER_SAVE_ENABLE);
@ -665,16 +663,16 @@ int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition)
} }
/* /*
* SD specific functions. * SD specific functions.
*/ */
static int _sd_storage_execute_app_cmd(sdmmc_storage_t *storage, u32 expected_state, u32 mask, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out) static int _sd_storage_execute_app_cmd(sdmmc_storage_t *storage, u32 expected_state, u32 mask, sdmmc_cmd_t *cmdbuf, sdmmc_req_t *req, u32 *blkcnt_out)
{ {
u32 tmp; u32 tmp;
if (!_sdmmc_storage_execute_cmd_type1_ex(storage, &tmp, MMC_APP_CMD, storage->rca << 16, 0, expected_state, mask)) if (!_sdmmc_storage_execute_cmd_type1_ex(storage, &tmp, MMC_APP_CMD, storage->rca << 16, 0, expected_state, mask))
return 0; return 0;
return sdmmc_execute_cmd(storage->sdmmc, cmd, req, blkcnt_out); return sdmmc_execute_cmd(storage->sdmmc, cmdbuf, req, blkcnt_out);
} }
static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp, u32 cmd, u32 arg, u32 check_busy, u32 expected_state) static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp, u32 cmd, u32 arg, u32 check_busy, u32 expected_state)
@ -728,24 +726,26 @@ static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, i
{ {
u32 timeout = get_tmr_ms() + 1500; u32 timeout = get_tmr_ms() + 1500;
while (1) while (true)
{ {
u32 cond = 0; u32 cond = 0;
if (!_sd_storage_get_op_cond_once(storage, &cond, is_version_1, bus_uhs_support)) if (!_sd_storage_get_op_cond_once(storage, &cond, is_version_1, bus_uhs_support))
break; break;
if (cond & MMC_CARD_BUSY)
// 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) if (cond & SD_OCR_CCS)
storage->has_sector_access = 1; storage->has_sector_access = 1;
// Check if card supports 1.8V signaling. // Check if card supports 1.8V signaling.
if (cond & SD_ROCR_S18A && bus_uhs_support) if (cond & SD_ROCR_S18A && bus_uhs_support)
{ {
//The low voltage regulator configuration is valid for SDMMC1 only. // Switch to 1.8V signaling.
if (storage->sdmmc->id == SDMMC_1 && if (_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
{ {
if (!sdmmc_enable_low_voltage(storage->sdmmc)) if (!sdmmc_enable_low_voltage(storage->sdmmc))
return 0; return 0;
@ -776,7 +776,7 @@ static int _sd_storage_get_rca(sdmmc_storage_t *storage)
u32 timeout = get_tmr_ms() + 1500; u32 timeout = get_tmr_ms() + 1500;
while (1) while (true)
{ {
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
break; break;
@ -809,8 +809,9 @@ static void _sd_storage_parse_scr(sdmmc_storage_t *storage)
storage->scr.sda_vsn = unstuff_bits(resp, 56, 4); storage->scr.sda_vsn = unstuff_bits(resp, 56, 4);
storage->scr.bus_widths = unstuff_bits(resp, 48, 4); storage->scr.bus_widths = unstuff_bits(resp, 48, 4);
/* If v2.0 is supported, check if Physical Layer Spec v3.0 is supported */
if (storage->scr.sda_vsn == SCR_SPEC_VER_2) if (storage->scr.sda_vsn == SCR_SPEC_VER_2)
/* Check if Physical Layer Spec v3.0 is supported */
storage->scr.sda_spec3 = unstuff_bits(resp, 47, 1); storage->scr.sda_spec3 = unstuff_bits(resp, 47, 1);
if (storage->scr.sda_spec3) if (storage->scr.sda_spec3)
storage->scr.cmds = unstuff_bits(resp, 32, 2); storage->scr.cmds = unstuff_bits(resp, 32, 2);
@ -827,7 +828,7 @@ int _sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf)
reqbuf.num_sectors = 1; reqbuf.num_sectors = 1;
reqbuf.is_write = 0; reqbuf.is_write = 0;
reqbuf.is_multi_block = 0; reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0; reqbuf.is_auto_stop_trn = 0;
if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, NULL)) if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, NULL))
return 0; return 0;
@ -859,7 +860,7 @@ int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf)
reqbuf.num_sectors = 1; reqbuf.num_sectors = 1;
reqbuf.is_write = 0; reqbuf.is_write = 0;
reqbuf.is_multi_block = 0; reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0; reqbuf.is_auto_stop_trn = 0;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
return 0; return 0;
@ -883,7 +884,7 @@ int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group,
reqbuf.num_sectors = 1; reqbuf.num_sectors = 1;
reqbuf.is_write = 0; reqbuf.is_write = 0;
reqbuf.is_multi_block = 0; reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0; reqbuf.is_auto_stop_trn = 0;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
return 0; return 0;
@ -1064,7 +1065,7 @@ int _sd_storage_enable_hs_high_volt(sdmmc_storage_t *storage, u8 *buf)
return sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_HS25); return sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_HS25);
} }
u32 sd_storage_ssr_get_au(sdmmc_storage_t *storage) u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage)
{ {
u32 au_size = storage->ssr.uhs_au_size; u32 au_size = storage->ssr.uhs_au_size;
@ -1104,39 +1105,24 @@ u32 sd_storage_ssr_get_au(sdmmc_storage_t *storage)
static void _sd_storage_parse_ssr(sdmmc_storage_t *storage) static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
{ {
// unstuff_bits supports only 4 u32 so break into 2 x 16byte groups // unstuff_bits supports only 4 u32 so break into 2 x u32x4 groups.
u32 raw_ssr1[4]; u32 raw_ssr1[4];
u32 raw_ssr2[4]; u32 raw_ssr2[4];
raw_ssr1[3] = *(u32 *)&storage->raw_ssr[12]; memcpy(raw_ssr1, &storage->raw_ssr[0], 16);
raw_ssr1[2] = *(u32 *)&storage->raw_ssr[8]; memcpy(raw_ssr2, &storage->raw_ssr[16], 16);
raw_ssr1[1] = *(u32 *)&storage->raw_ssr[4];
raw_ssr1[0] = *(u32 *)&storage->raw_ssr[0];
raw_ssr2[3] = *(u32 *)&storage->raw_ssr[28];
raw_ssr2[2] = *(u32 *)&storage->raw_ssr[24];
raw_ssr2[1] = *(u32 *)&storage->raw_ssr[20];
raw_ssr2[0] = *(u32 *)&storage->raw_ssr[16];
storage->ssr.bus_width = (unstuff_bits(raw_ssr1, 510 - 384, 2) & SD_BUS_WIDTH_4) ? 4 : 1; 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.protected_size = unstuff_bits(raw_ssr1, 448 - 384, 32);
switch(unstuff_bits(raw_ssr1, 440 - 384, 8)) u32 speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8);
switch(speed_class)
{ {
case 0: case 0:
storage->ssr.speed_class = 0;
break;
case 1: case 1:
storage->ssr.speed_class = 2;
break;
case 2: case 2:
storage->ssr.speed_class = 4;
break;
case 3: case 3:
storage->ssr.speed_class = 6; storage->ssr.speed_class = speed_class << 1;
break; break;
case 4: case 4:
@ -1144,19 +1130,18 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
break; break;
default: default:
storage->ssr.speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8); storage->ssr.speed_class = speed_class;
break; break;
} }
storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4); storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4);
storage->ssr.video_class = unstuff_bits(raw_ssr1, 384 - 384, 8); storage->ssr.video_class = unstuff_bits(raw_ssr1, 384 - 384, 8);
storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4);
storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4); storage->ssr.au_size = unstuff_bits(raw_ssr1, 428 - 384, 4);
storage->ssr.au_size = unstuff_bits(raw_ssr1, 428 - 384, 4);
storage->ssr.uhs_au_size = unstuff_bits(raw_ssr1, 392 - 384, 4); storage->ssr.uhs_au_size = unstuff_bits(raw_ssr1, 392 - 384, 4);
} }
static int _sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf) int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
{ {
sdmmc_cmd_t cmdbuf; sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, SD_APP_SD_STATUS, 0, SDMMC_RSP_TYPE_1, 0); sdmmc_init_cmd(&cmdbuf, SD_APP_SD_STATUS, 0, SDMMC_RSP_TYPE_1, 0);
@ -1167,11 +1152,11 @@ static int _sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
reqbuf.num_sectors = 1; reqbuf.num_sectors = 1;
reqbuf.is_write = 0; reqbuf.is_write = 0;
reqbuf.is_multi_block = 0; reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0; reqbuf.is_auto_stop_trn = 0;
if (!(storage->csd.cmdclass & CCC_APP_SPEC)) if (!(storage->csd.cmdclass & CCC_APP_SPEC))
{ {
DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n"); DPRINTF("[SD] ssr: Not supported\n");
return 0; return 0;
} }
@ -1180,14 +1165,16 @@ DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n");
u32 tmp = 0; u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
//Prepare buffer for unstuff_bits
for (int i = 0; i < 64; i+=4) // Convert buffer to LE.
for (int i = 0; i < 64; i += 4)
{ {
storage->raw_ssr[i + 3] = buf[i]; storage->raw_ssr[i + 3] = buf[i];
storage->raw_ssr[i + 2] = buf[i + 1]; storage->raw_ssr[i + 2] = buf[i + 1];
storage->raw_ssr[i + 1] = buf[i + 2]; storage->raw_ssr[i + 1] = buf[i + 2];
storage->raw_ssr[i] = buf[i + 3]; storage->raw_ssr[i] = buf[i + 3];
} }
_sd_storage_parse_ssr(storage); _sd_storage_parse_ssr(storage);
//gfx_hexdump(0, storage->raw_ssr, 64); //gfx_hexdump(0, storage->raw_ssr, 64);
@ -1198,18 +1185,18 @@ static void _sd_storage_parse_cid(sdmmc_storage_t *storage)
{ {
u32 *raw_cid = (u32 *)&(storage->raw_cid); u32 *raw_cid = (u32 *)&(storage->raw_cid);
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8); storage->cid.manfid = unstuff_bits(raw_cid, 120, 8);
storage->cid.oemid = unstuff_bits(raw_cid, 104, 16); storage->cid.oemid = unstuff_bits(raw_cid, 104, 16);
storage->cid.prod_name[0] = unstuff_bits(raw_cid, 96, 8); storage->cid.prod_name[0] = unstuff_bits(raw_cid, 96, 8);
storage->cid.prod_name[1] = unstuff_bits(raw_cid, 88, 8); storage->cid.prod_name[1] = unstuff_bits(raw_cid, 88, 8);
storage->cid.prod_name[2] = unstuff_bits(raw_cid, 80, 8); storage->cid.prod_name[2] = unstuff_bits(raw_cid, 80, 8);
storage->cid.prod_name[3] = unstuff_bits(raw_cid, 72, 8); storage->cid.prod_name[3] = unstuff_bits(raw_cid, 72, 8);
storage->cid.prod_name[4] = unstuff_bits(raw_cid, 64, 8); storage->cid.prod_name[4] = unstuff_bits(raw_cid, 64, 8);
storage->cid.hwrev = unstuff_bits(raw_cid, 60, 4); storage->cid.hwrev = unstuff_bits(raw_cid, 60, 4);
storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4); storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4);
storage->cid.serial = unstuff_bits(raw_cid, 24, 32); storage->cid.serial = unstuff_bits(raw_cid, 24, 32);
storage->cid.month = unstuff_bits(raw_cid, 8, 4); storage->cid.year = unstuff_bits(raw_cid, 12, 8) + 2000;
storage->cid.year = unstuff_bits(raw_cid, 12, 8) + 2000; storage->cid.month = unstuff_bits(raw_cid, 8, 4);
} }
static void _sd_storage_parse_csd(sdmmc_storage_t *storage) static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
@ -1231,7 +1218,13 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
storage->csd.capacity = storage->csd.c_size << 10; storage->csd.capacity = storage->csd.c_size << 10;
storage->csd.read_blkbits = 9; storage->csd.read_blkbits = 9;
break; break;
default:
DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure);
break;
} }
storage->sec_cnt = storage->csd.capacity;
} }
static bool _sdmmc_storage_get_bus_uhs_support(u32 bus_width, u32 type) static bool _sdmmc_storage_get_bus_uhs_support(u32 bus_width, u32 type)
@ -1261,8 +1254,10 @@ void sdmmc_storage_init_wait_sd()
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type) int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
{ {
u32 tmp = 0;
int is_version_1 = 0; int is_version_1 = 0;
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER; 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);
@ -1287,13 +1282,11 @@ DPRINTF("[SD] went to idle state\n");
return 0; return 0;
DPRINTF("[SD] after send if cond\n"); DPRINTF("[SD] after send if cond\n");
bool bus_uhs_support = _sdmmc_storage_get_bus_uhs_support(bus_width, type);
if (!_sd_storage_get_op_cond(storage, is_version_1, bus_uhs_support)) if (!_sd_storage_get_op_cond(storage, is_version_1, bus_uhs_support))
return 0; return 0;
DPRINTF("[SD] got op cond\n"); DPRINTF("[SD] got op cond\n");
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid)) if (!_sdmmc_storage_get_cid(storage))
return 0; return 0;
DPRINTF("[SD] got cid\n"); DPRINTF("[SD] got cid\n");
_sd_storage_parse_cid(storage); _sd_storage_parse_cid(storage);
@ -1302,30 +1295,16 @@ DPRINTF("[SD] got cid\n");
return 0; return 0;
DPRINTF("[SD] got rca (= %04X)\n", storage->rca); DPRINTF("[SD] got rca (= %04X)\n", storage->rca);
if (!_sdmmc_storage_get_csd(storage, storage->raw_csd)) if (!_sdmmc_storage_get_csd(storage))
return 0; return 0;
DPRINTF("[SD] got csd\n"); DPRINTF("[SD] got csd\n");
//Parse CSD.
_sd_storage_parse_csd(storage); _sd_storage_parse_csd(storage);
switch (storage->csd.structure)
{
case 0:
storage->sec_cnt = storage->csd.capacity;
break;
case 1:
storage->sec_cnt = storage->csd.c_size << 10;
break;
default:
DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure);
break;
}
if (!storage->is_low_voltage) if (!storage->is_low_voltage)
{ {
if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_DS12)) if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_DS12))
return 0; return 0;
DPRINTF("[SD] after setup clock\n"); DPRINTF("[SD] after setup default clock\n");
} }
if (!_sdmmc_storage_select_card(storage)) if (!_sdmmc_storage_select_card(storage))
@ -1336,19 +1315,17 @@ DPRINTF("[SD] card selected\n");
return 0; return 0;
DPRINTF("[SD] set blocklen to 512\n"); DPRINTF("[SD] set blocklen to 512\n");
u32 tmp = 0; // Disconnect Card Detect resistor from DAT3.
if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_CLR_CARD_DETECT, 0, 0, R1_STATE_TRAN)) if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_CLR_CARD_DETECT, 0, 0, R1_STATE_TRAN))
return 0; return 0;
DPRINTF("[SD] cleared card detect\n"); DPRINTF("[SD] cleared card detect\n");
if (!_sd_storage_get_scr(storage, buf)) if (!_sd_storage_get_scr(storage, buf))
return 0; return 0;
//gfx_hexdump(0, storage->raw_scr, 8);
DPRINTF("[SD] got scr\n"); DPRINTF("[SD] got scr\n");
// Check if card supports a wider bus and if it's not SD Version 1.X // 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 & 4) && (storage->scr.sda_vsn & 0xF)) if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & BIT(SD_BUS_WIDTH_4)) && storage->scr.sda_vsn)
{ {
if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_BUS_WIDTH, SD_BUS_WIDTH_4, 0, R1_STATE_TRAN)) if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_BUS_WIDTH, SD_BUS_WIDTH_4, 0, R1_STATE_TRAN))
return 0; return 0;
@ -1370,7 +1347,7 @@ DPRINTF("[SD] enabled UHS\n");
sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE); sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE);
} }
else if (type != SDHCI_TIMING_SD_DS12 && (storage->scr.sda_vsn & 0xF)) // Not default speed and not SD Version 1.x 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)) if (!_sd_storage_enable_hs_high_volt(storage, buf))
return 0; return 0;
@ -1389,7 +1366,7 @@ DPRINTF("[SD] enabled HS\n");
} }
// Parse additional card info from sd status. // Parse additional card info from sd status.
if (_sd_storage_get_ssr(storage, buf)) if (sd_storage_get_ssr(storage, buf))
{ {
DPRINTF("[SD] got sd status\n"); DPRINTF("[SD] got sd status\n");
} }
@ -1400,14 +1377,14 @@ DPRINTF("[SD] got sd status\n");
} }
/* /*
* Gamecard specific functions. * Gamecard specific functions.
*/ */
int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf) int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
{ {
u32 resp; u32 resp;
sdmmc_cmd_t cmdbuf; sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, 60, 0, SDMMC_RSP_TYPE_1, 1); sdmmc_init_cmd(&cmdbuf, MMC_VENDOR_60_CMD, 0, SDMMC_RSP_TYPE_1, 1);
sdmmc_req_t reqbuf; sdmmc_req_t reqbuf;
reqbuf.buf = buf; reqbuf.buf = buf;
@ -1415,7 +1392,7 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
reqbuf.num_sectors = 1; reqbuf.num_sectors = 1;
reqbuf.is_write = 1; reqbuf.is_write = 1;
reqbuf.is_multi_block = 0; reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0; reqbuf.is_auto_stop_trn = 0;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
{ {

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -30,18 +30,18 @@ typedef enum _sdmmc_type
EMMC_GPP = 0, EMMC_GPP = 0,
EMMC_BOOT0 = 1, EMMC_BOOT0 = 1,
EMMC_BOOT1 = 2 EMMC_BOOT1 = 2,
EMMC_RPMB = 3
} sdmmc_type; } sdmmc_type;
typedef struct _mmc_cid typedef struct _mmc_cid
{ {
u32 manfid; u32 manfid;
u8 prod_name[8]; u8 prod_name[8];
u8 card_bga;
u8 prv;
u32 serial; u32 serial;
u16 oemid; u16 oemid;
u16 year; u16 year;
u8 prv;
u8 hwrev; u8 hwrev;
u8 fwrev; u8 fwrev;
u8 month; u8 month;
@ -65,19 +65,20 @@ typedef struct _mmc_csd
typedef struct _mmc_ext_csd typedef struct _mmc_ext_csd
{ {
u32 sectors; //u8 bkops; /* background support bit */
int bkops; /* background support bit */ //u8 bkops_en; /* manual bkops enable bit */
int bkops_en; /* manual bkops enable bit */ //u8 bkops_status; /* 246 */
u8 rev; u8 rev;
u8 ext_struct; /* 194 */ u8 ext_struct; /* 194 */
u8 card_type; /* 196 */ u8 card_type; /* 196 */
u8 bkops_status; /* 246 */
u8 pre_eol_info; u8 pre_eol_info;
u8 dev_life_est_a; u8 dev_life_est_a;
u8 dev_life_est_b; u8 dev_life_est_b;
u8 boot_mult; u8 boot_mult;
u8 rpmb_mult; u8 rpmb_mult;
u16 dev_version; u16 dev_version;
u32 cache_size;
u32 max_enh_mult;
} mmc_ext_csd_t; } mmc_ext_csd_t;
typedef struct _sd_scr typedef struct _sd_scr
@ -90,13 +91,13 @@ typedef struct _sd_scr
typedef struct _sd_ssr typedef struct _sd_ssr
{ {
u8 bus_width; u8 bus_width;
u8 speed_class; u8 speed_class;
u8 uhs_grade; u8 uhs_grade;
u8 video_class; u8 video_class;
u8 app_class; u8 app_class;
u8 au_size; u8 au_size;
u8 uhs_au_size; u8 uhs_au_size;
u32 protected_size; u32 protected_size;
} sd_ssr_t; } sd_ssr_t;
@ -130,6 +131,7 @@ void sdmmc_storage_init_wait_sd();
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type); int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type);
int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc); int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc);
u32 sd_storage_ssr_get_au(sdmmc_storage_t *storage); int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf);
u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage);
#endif #endif

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -934,12 +934,20 @@ static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req)
*blkcnt_out = blkcnt; *blkcnt_out = blkcnt;
u32 trnmode = SDHCI_TRNS_DMA; u32 trnmode = SDHCI_TRNS_DMA;
// Set mulitblock request.
if (req->is_multi_block) if (req->is_multi_block)
trnmode = SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_DMA; trnmode = SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_DMA;
// Set request direction.
if (!req->is_write) if (!req->is_write)
trnmode |= SDHCI_TRNS_READ; trnmode |= SDHCI_TRNS_READ;
if (req->is_auto_cmd12)
trnmode = (trnmode & ~(SDHCI_TRNS_AUTO_CMD12 | SDHCI_TRNS_AUTO_CMD23)) | SDHCI_TRNS_AUTO_CMD12; // Automatic send of stop transmission or set block count cmd.
if (req->is_auto_stop_trn)
trnmode |= SDHCI_TRNS_AUTO_CMD12;
//else if (req->is_auto_set_blkcnt)
// trnmode |= SDHCI_TRNS_AUTO_CMD23;
sdmmc->regs->trnmod = trnmode; sdmmc->regs->trnmod = trnmode;
@ -1070,7 +1078,7 @@ DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
if (blkcnt_out) if (blkcnt_out)
*blkcnt_out = blkcnt; *blkcnt_out = blkcnt;
if (req->is_auto_cmd12) if (req->is_auto_stop_trn)
sdmmc->rsp3 = sdmmc->regs->rspreg3; sdmmc->rsp3 = sdmmc->regs->rspreg3;
} }

View file

@ -242,7 +242,7 @@ typedef struct _sdmmc_req_t
u32 num_sectors; u32 num_sectors;
int is_write; int is_write;
int is_multi_block; int is_multi_block;
int is_auto_cmd12; int is_auto_stop_trn;
} sdmmc_req_t; } sdmmc_req_t;
int sdmmc_get_io_power(sdmmc_t *sdmmc); int sdmmc_get_io_power(sdmmc_t *sdmmc);

View file

@ -149,13 +149,12 @@ void print_mmc_info()
case 4: /* MMC v4 */ case 4: /* MMC v4 */
gfx_printf( gfx_printf(
" Vendor ID: %X\n" " Vendor ID: %X\n"
" Card/BGA: %X\n"
" OEM ID: %02X\n" " OEM ID: %02X\n"
" Model: %c%c%c%c%c%c\n" " Model: %c%c%c%c%c%c\n"
" Prd Rev: %X\n" " Prd Rev: %X\n"
" S/N: %04X\n" " S/N: %04X\n"
" Month/Year: %02d/%04d\n\n", " Month/Year: %02d/%04d\n\n",
emmc_storage.cid.manfid, emmc_storage.cid.card_bga, emmc_storage.cid.oemid, emmc_storage.cid.manfid, emmc_storage.cid.oemid,
emmc_storage.cid.prod_name[0], emmc_storage.cid.prod_name[1], emmc_storage.cid.prod_name[2], emmc_storage.cid.prod_name[0], emmc_storage.cid.prod_name[1], emmc_storage.cid.prod_name[2],
emmc_storage.cid.prod_name[3], emmc_storage.cid.prod_name[4], emmc_storage.cid.prod_name[5], emmc_storage.cid.prod_name[3], emmc_storage.cid.prod_name[4], emmc_storage.cid.prod_name[5],
emmc_storage.cid.prv, emmc_storage.cid.serial, emmc_storage.cid.month, emmc_storage.cid.year); emmc_storage.cid.prv, emmc_storage.cid.serial, emmc_storage.cid.month, emmc_storage.cid.year);

View file

@ -1389,8 +1389,8 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
break; break;
} }
s_printf(txt_buf + strlen(txt_buf), "(%02X)\n%X\n%02X\n%c%c%c%c%c%c\n%X\n%04X\n%02d/%04d\n\n", s_printf(txt_buf + strlen(txt_buf), "(%02X)\n%c%c%c%c%c%c\n%X\n%04X\n%02d/%04d\n\n",
storage.cid.manfid, storage.cid.card_bga, storage.cid.oemid, storage.cid.manfid,
storage.cid.prod_name[0], storage.cid.prod_name[1], storage.cid.prod_name[2], storage.cid.prod_name[0], storage.cid.prod_name[1], storage.cid.prod_name[2],
storage.cid.prod_name[3], storage.cid.prod_name[4], storage.cid.prod_name[5], storage.cid.prod_name[3], storage.cid.prod_name[4], storage.cid.prod_name[5],
storage.cid.prv, storage.cid.serial, storage.cid.month, storage.cid.year); storage.cid.prv, storage.cid.serial, storage.cid.month, storage.cid.year);
@ -1464,8 +1464,6 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
lv_label_set_static_text(lb_desc, lv_label_set_static_text(lb_desc,
"#00DDFF CID:#\n" "#00DDFF CID:#\n"
"Vendor ID:\n" "Vendor ID:\n"
"Card/BGA:\n"
"OEM ID:\n"
"Model:\n" "Model:\n"
"Prd Rev:\n" "Prd Rev:\n"
"S/N:\n" "S/N:\n"
@ -1705,7 +1703,7 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
} }
bool uhs_au_mb = false; bool uhs_au_mb = false;
u32 uhs_au_size = sd_storage_ssr_get_au(&sd_storage); u32 uhs_au_size = sd_storage_get_ssr_au(&sd_storage);
if (uhs_au_size >= 1024) if (uhs_au_size >= 1024)
{ {
uhs_au_mb = true; uhs_au_mb = true;