* [PATCH v5 0/9] enhance MMC
@ 2016-11-13 6:47 Haojian Zhuang
2016-11-13 6:47 ` [PATCH v5 1/9] MmcDxe: wait OCR busy bit free Haojian Zhuang
` (9 more replies)
0 siblings, 10 replies; 16+ messages in thread
From: Haojian Zhuang @ 2016-11-13 6:47 UTC (permalink / raw)
To: ryan.harkin, edk2-devel, leif.lindholm, ard.biesheuvel; +Cc: Haojian Zhuang
v5:
* Remove patch on MediaId.
* Squash two PL180 patches together.
v4:
* Fix PL180 hang in some cases. Since the proper variable length
isn't set for CMD6 & ACMD51.
v3:
* Fix PL180 hang because of CMD6 & ACMD51 not supported.
v2:
* Fix print error with missing parameter.
* Change CMD51 to ACMD51.
* Add the protection after CMD55 for SD. If there's no
response of CMD55, skip to send ACMD51.
v1:
* Wait OCR busy bit free according to eMMC spec.
* Define ECSD structure.
* Add interface to set IO bus width and speed.
* Support to access multiple blocks.
Haojian Zhuang (9):
MmcDxe: wait OCR busy bit free
MmcDxe: move ECSD into CardInfo structure
MmcDxe: declare ECSD structure
MmcDxe: add SPEC_VERS field in CSD structure
MmcDxe: add interface to change io width and speed
MmcDxe: set io bus width before reading EXTCSD
MmcDxe: set iospeed and bus width in SD stack
MmcDxe: expand to support multiple blocks
PL180: update for indentifying SD
ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c | 29 +-
EmbeddedPkg/Include/Protocol/MmcHost.h | 29 ++
EmbeddedPkg/Universal/MmcDxe/Mmc.h | 176 +++++++++++-
EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c | 177 ++++++++----
EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c | 347 +++++++++++++++++++++--
5 files changed, 664 insertions(+), 94 deletions(-)
--
2.7.4
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v5 1/9] MmcDxe: wait OCR busy bit free
2016-11-13 6:47 [PATCH v5 0/9] enhance MMC Haojian Zhuang
@ 2016-11-13 6:47 ` Haojian Zhuang
2016-11-13 6:47 ` [PATCH v5 2/9] MmcDxe: move ECSD into CardInfo structure Haojian Zhuang
` (8 subsequent siblings)
9 siblings, 0 replies; 16+ messages in thread
From: Haojian Zhuang @ 2016-11-13 6:47 UTC (permalink / raw)
To: ryan.harkin, edk2-devel, leif.lindholm, ard.biesheuvel; +Cc: Haojian Zhuang
According to eMMC spec, OCR.PowerUp bit is also busy bit. If the busy
bit is '0', CMD1 should be sent and OCR should be fetched again. And add
a timeout counter on the repeated steps.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Tested-by: Ryan Harkin <ryan.harkin@linaro.org>
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
---
EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
index 2d8038f..3f72b7f 100644
--- a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
+++ b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
@@ -222,14 +222,19 @@ MmcIdentificationMode (
// Send CMD1 to get OCR (MMC)
// This command only valid for MMC and eMMC
- Status = MmcHost->SendCommand (MmcHost, MMC_CMD1, EMMC_CMD1_CAPACITY_GREATER_THAN_2GB);
- if (Status == EFI_SUCCESS) {
+ Timeout = MAX_RETRY_COUNT;
+ do {
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD1, EMMC_CMD1_CAPACITY_GREATER_THAN_2GB);
+ if (EFI_ERROR (Status))
+ break;
Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_OCR, (UINT32 *)&OcrResponse);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Failed to receive OCR, Status=%r.\n", Status));
return Status;
}
-
+ Timeout--;
+ } while (!OcrResponse.Ocr.PowerUp && (Timeout > 0));
+ if (Status == EFI_SUCCESS) {
if (!OcrResponse.Ocr.PowerUp) {
DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD1): Card initialisation failure, Status=%r.\n", Status));
return EFI_DEVICE_ERROR;
--
2.7.4
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v5 2/9] MmcDxe: move ECSD into CardInfo structure
2016-11-13 6:47 [PATCH v5 0/9] enhance MMC Haojian Zhuang
2016-11-13 6:47 ` [PATCH v5 1/9] MmcDxe: wait OCR busy bit free Haojian Zhuang
@ 2016-11-13 6:47 ` Haojian Zhuang
2016-11-13 6:47 ` [PATCH v5 3/9] MmcDxe: declare ECSD structure Haojian Zhuang
` (7 subsequent siblings)
9 siblings, 0 replies; 16+ messages in thread
From: Haojian Zhuang @ 2016-11-13 6:47 UTC (permalink / raw)
To: ryan.harkin, edk2-devel, leif.lindholm, ard.biesheuvel; +Cc: Haojian Zhuang
Since ECSD also describes the information of card, move it into
structure CardInfo.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Tested-by: Ryan Harkin <ryan.harkin@linaro.org>
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
---
EmbeddedPkg/Universal/MmcDxe/Mmc.h | 1 +
EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c | 5 ++---
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/EmbeddedPkg/Universal/MmcDxe/Mmc.h b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
index 46a156c..4f132c6 100644
--- a/EmbeddedPkg/Universal/MmcDxe/Mmc.h
+++ b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
@@ -138,6 +138,7 @@ typedef struct {
OCR OCRData;
CID CIDData;
CSD CSDData;
+ UINT32 ECSD[128]; // MMC V4 extended card specific
} CARD_INFO;
typedef struct _MMC_HOST_INSTANCE {
diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
index 3f72b7f..578fcb6 100644
--- a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
+++ b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
@@ -39,7 +39,6 @@ EmmcIdentificationMode (
EFI_BLOCK_IO_MEDIA *Media;
EFI_STATUS Status;
UINT32 RCA;
- UINT32 ECSD[128];
Host = MmcHostInstance->MmcHost;
Media = MmcHostInstance->BlockIo.Media;
@@ -91,7 +90,7 @@ EmmcIdentificationMode (
DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD fetch error, Status=%r.\n", Status));
}
- Status = Host->ReadBlockData (Host, 0, 512, ECSD);
+ Status = Host->ReadBlockData (Host, 0, 512, (UINT32 *)&(MmcHostInstance->CardInfo.ECSD));
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD read error, Status=%r.\n", Status));
return Status;
@@ -104,7 +103,7 @@ EmmcIdentificationMode (
Media->LogicalBlocksPerPhysicalBlock = 1;
Media->IoAlign = 4;
// Compute last block using bits [215:212] of the ECSD
- Media->LastBlock = ECSD[EMMC_ECSD_SIZE_OFFSET] - 1; // eMMC isn't supposed to report this for
+ Media->LastBlock = MmcHostInstance->CardInfo.ECSD[EMMC_ECSD_SIZE_OFFSET] - 1; // eMMC isn't supposed to report this for
// Cards <2GB in size, but the model does.
// Setup card type
--
2.7.4
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v5 3/9] MmcDxe: declare ECSD structure
2016-11-13 6:47 [PATCH v5 0/9] enhance MMC Haojian Zhuang
2016-11-13 6:47 ` [PATCH v5 1/9] MmcDxe: wait OCR busy bit free Haojian Zhuang
2016-11-13 6:47 ` [PATCH v5 2/9] MmcDxe: move ECSD into CardInfo structure Haojian Zhuang
@ 2016-11-13 6:47 ` Haojian Zhuang
2016-11-13 6:47 ` [PATCH v5 4/9] MmcDxe: add SPEC_VERS field in CSD structure Haojian Zhuang
` (6 subsequent siblings)
9 siblings, 0 replies; 16+ messages in thread
From: Haojian Zhuang @ 2016-11-13 6:47 UTC (permalink / raw)
To: ryan.harkin, edk2-devel, leif.lindholm, ard.biesheuvel; +Cc: Haojian Zhuang
Declare fields in ECSD structure. And drop the original 128 words
arrary.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Tested-by: Ryan Harkin <ryan.harkin@linaro.org>
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
---
EmbeddedPkg/Universal/MmcDxe/Mmc.h | 157 ++++++++++++++++++++++-
EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c | 4 +-
2 files changed, 158 insertions(+), 3 deletions(-)
diff --git a/EmbeddedPkg/Universal/MmcDxe/Mmc.h b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
index 4f132c6..25c69ae 100644
--- a/EmbeddedPkg/Universal/MmcDxe/Mmc.h
+++ b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
@@ -132,13 +132,168 @@ typedef struct {
UINT8 CSD_STRUCTURE: 2; // CSD structure [127:126]
} CSD;
+typedef struct {
+ UINT8 RESERVED_1[16]; // Reserved [15:0]
+ UINT8 SECURE_REMOVAL_TYPE; // Secure Removal Type [16:16]
+ UINT8 PRODUCT_STATE_AWARENESS_ENABLEMENT; // Product state awareness enablement [17:17]
+ UINT8 MAX_PRE_LOADING_DATA_SIZE[4]; // MAX pre loading data size [21:18]
+ UINT8 PRE_LOADING_DATA_SIZE[4]; // Pre loading data size [25:22]
+ UINT8 FFU_STATUS; // FFU Status [26:26]
+ UINT8 RESERVED_2[2]; // Reserved [28:27]
+ UINT8 MODE_OPERATION_CODES; // Mode operation codes [29:29]
+ UINT8 MODE_CONFIG; // Mode config [30:30]
+ UINT8 RESERVED_3; // Reserved [31:31]
+ UINT8 FLUSH_CACHE; // Flushing of the cache [32:32]
+ UINT8 CACHE_CTRL; // Control to turn the cache ON/OFF [33:33]
+ UINT8 POWER_OFF_NOTIFICATION; // Power Off Notification [34:34]
+ UINT8 PACKED_FAILURE_INDEX; // Packed command failure index [35:35]
+ UINT8 PACKED_COMMAND_STATUS; // Packed command status [36:36]
+ UINT8 CONTEXT_CONF[15]; // Context configuration [51:37]
+ UINT8 EXT_PARTITIONS_ATTRIBUTE[2]; // Extended partitions attribute [53:52]
+ UINT8 EXCEPTION_EVENTS_STATUS[2]; // Exception events status [55:54]
+ UINT8 EXCEPTION_EVENTS_CTRL[2]; // Exception events control [57:56]
+ UINT8 DYNCAP_NEEDED; // Number of addressed group to be released [58:58]
+ UINT8 CLASS_6_CTRL; // Class 6 commands control [59:59]
+ UINT8 INI_TIMEOUT_EMU; // 1st initialization after disabling sector size emulation [60:60]
+ UINT8 DATA_SECTOR_SIZE; // Sector size [61:61]
+ UINT8 USE_NATIVE_SECTOR; // Sector size emulation [62:62]
+ UINT8 NATIVE_SECTOR_SIZE; // Native sector size [63:63]
+ UINT8 VENDOR_SPECIFIC_FIELD[64]; // Vendor specific fields [127:64]
+ UINT8 RESERVED_4[2]; // Reserved [129:128]
+ UINT8 PROGRAM_CID_CSD_DDR_SUPPORT; // Program CID/CSD in DDR mode support [130:130]
+ UINT8 PERIODIC_WAKEUP; // Periodic wake-up [131:131]
+ UINT8 TCASE_SUPPORT; // Package case temperature is controlled [132:132]
+ UINT8 PRODUCTION_STATE_AWARENESS; // Production state awareness [133:133]
+ UINT8 SECTOR_BAD_BLK_MGMNT; // Bad block management mode [134:134]
+ UINT8 RESERVED_5; // Reserved [135:135]
+ UINT8 ENH_START_ADDR[4]; // Enhanced user data start address [139:136]
+ UINT8 ENH_SIZE_MULT[3]; // Enhanced user data area size [142:140]
+ UINT8 GP_SIZE_MULT[12]; // General purpose partition size [154:143]
+ UINT8 PARTITION_SETTING_COMPLETED; // Partitioning setting [155:155]
+ UINT8 PARTITIONS_ATTRIBUTE; // Partitions attribute [156:156]
+ UINT8 MAX_ENH_SIZE_MULT[3]; // Max enhanced area size [159:157]
+ UINT8 PARTITIONING_SUPPORT; // Partitioning [160:160]
+ UINT8 HPI_MGMT; // HPI management [161:161]
+ UINT8 RST_N_FUNCTION; // H/W reset function [162:162]
+ UINT8 BKOPS_EN; // Enable background operations handshake [163:163]
+ UINT8 BKOPS_START; // Manually start background operations [164:164]
+ UINT8 SANITIZE_START; // Start sanitize operation [165:165]
+ UINT8 WR_REL_PARAM; // Write reliability parameter register [166:166]
+ UINT8 WR_REL_SET; // Write reliability setting register [167:167]
+ UINT8 RPMB_SIZE_MULT; // RPMB size [168:168]
+ UINT8 FW_CONFIG; // FW configuration [169:169]
+ UINT8 RESERVED_6; // Reserved [170:170]
+ UINT8 USER_WP; // User area write protection register [171:171]
+ UINT8 RESERVED_7; // Reserved [172:172]
+ UINT8 BOOT_WP; // Boot area write protection register [173:173]
+ UINT8 BOOT_WP_STATUS; // Boot write protection register [174:174]
+ UINT8 ERASE_GROUP_DEF; // High-density erase group definition [175:175]
+ UINT8 RESERVED_8; // Reserved [176:176]
+ UINT8 BOOT_BUS_CONDITIONS; // Boot bus conditions [177:177]
+ UINT8 BOOT_CONFIG_PROT; // Boot config protection [178:178]
+ UINT8 PARTITION_CONFIG; // Partition config [179:179]
+ UINT8 RESERVED_9; // Reserved [180:180]
+ UINT8 ERASED_MEM_CONT; // Erased memory content [181:181]
+ UINT8 RESERVED_10; // Reserved [182:182]
+ UINT8 BUS_WIDTH; // Bus width mode [183:183]
+ UINT8 RESERVED_11; // Reserved [184:184]
+ UINT8 HS_TIMING; // High-speed interface timing [185:185]
+ UINT8 RESERVED_12; // Reserved [186:186]
+ UINT8 POWER_CLASS; // Power class [187:187]
+ UINT8 RESERVED_13; // Reserved [188:188]
+ UINT8 CMD_SET_REV; // Command set revision [189:189]
+ UINT8 RESERVED_14; // Reserved [190:190]
+ UINT8 CMD_SET; // Command set [191:191]
+ UINT8 EXT_CSD_REV; // Extended CSD revision [192:192]
+ UINT8 RESERVED_15; // Reserved [193:193]
+ UINT8 CSD_STRUCTURE; // CSD Structure [194:194]
+ UINT8 RESERVED_16; // Reserved [195:195]
+ UINT8 DEVICE_TYPE; // Device type [196:196]
+ UINT8 DRIVER_STRENGTH; // I/O Driver strength [197:197]
+ UINT8 OUT_OF_INTERRUPT_TIME; // Out-of-interrupt busy timing [198:198]
+ UINT8 PARTITION_SWITCH_TIME; // Partition switching timing [199:199]
+ UINT8 PWR_CL_52_195; // Power class for 52MHz at 1.95V 1 R [200:200]
+ UINT8 PWR_CL_26_195; // Power class for 26MHz at 1.95V 1 R [201:201]
+ UINT8 PWR_CL_52_360; // Power class for 52MHz at 3.6V 1 R [202:202]
+ UINT8 PWR_CL_26_360; // Power class for 26MHz at 3.6V 1 R [203:203]
+ UINT8 RESERVED_17; // Reserved [204:204]
+ UINT8 MIN_PERF_R_4_26; // Minimum read performance for 4bit at 26MHz [205:205]
+ UINT8 MIN_PERF_W_4_26; // Minimum write performance for 4bit at 26MHz [206:206]
+ UINT8 MIN_PERF_R_8_26_4_52; // Minimum read performance for 8bit at 26MHz, for 4bit at 52MHz [207:207]
+ UINT8 MIN_PERF_W_8_26_4_52; // Minimum write performance for 8bit at 26MHz, for 4bit at 52MHz [208:208]
+ UINT8 MIN_PERF_R_8_52; // Minimum read performance for 8bit at 52MHz [209:209]
+ UINT8 MIN_PERF_W_8_52; // Minimum write performance for 8bit at 52MHz [210:210]
+ UINT8 RESERVED_18; // Reserved [211:211]
+ UINT32 SECTOR_COUNT; // Sector count [215:212]
+ UINT8 SLEEP_NOTIFICATION_TIME; // Sleep notification timout [216:216]
+ UINT8 S_A_TIMEOUT; // Sleep/awake timeout [217:217]
+ UINT8 PRODUCTION_STATE_AWARENESS_TIMEOUT; // Production state awareness timeout [218:218]
+ UINT8 S_C_VCCQ; // Sleep current (VCCQ) [219:219]
+ UINT8 S_C_VCC; // Sleep current (VCC) [220:220]
+ UINT8 HC_WP_GRP_SIZE; // High-capacity write protect group size [221:221]
+ UINT8 REL_WR_SECTOR_C; // Reliable write sector count [222:222]
+ UINT8 ERASE_TIMEOUT_MULT; // High-capacity erase timeout [223:223]
+ UINT8 HC_ERASE_GRP_SIZE; // High-capacity erase unit size [224:224]
+ UINT8 ACC_SIZE; // Access size [225:225]
+ UINT8 BOOT_SIZE_MULTI; // Boot partition size [226:226]
+ UINT8 RESERVED_19; // Reserved [227:227]
+ UINT8 BOOT_INFO; // Boot information [228:228]
+ UINT8 SECURE_TRIM_MULT; // Secure TRIM Multiplier [229:229]
+ UINT8 SECURE_ERASE_MULT; // Secure Erase Multiplier [230:230]
+ UINT8 SECURE_FEATURE_SUPPORT; // Secure Feature Support [231:231]
+ UINT8 TRIM_MULT; // TRIM Multiplier [232:232]
+ UINT8 RESERVED_20; // Reserved [233:233]
+ UINT8 MIN_PREF_DDR_R_8_52; // Minimum read performance for 8bit at 52MHz in DDR mode [234:234]
+ UINT8 MIN_PREF_DDR_W_8_52; // Minimum write performance for 8bit at 52MHz in DDR mode [235:235]
+ UINT8 PWR_CL_200_130; // Power class for 200MHz at VCCQ=1.3V, VCC=3.6V [236:236]
+ UINT8 PWR_CL_200_195; // Power class for 200MHz at VCCQ=1.95V, VCC=3.6V [237:237]
+ UINT8 PWR_CL_DDR_52_195; // Power class for 52MHz, DDR at 1.95V [238:238]
+ UINT8 PWR_CL_DDR_52_360; // Power class for 52Mhz, DDR at 3.6V [239:239]
+ UINT8 RESERVED_21; // Reserved [240:240]
+ UINT8 INI_TIMEOUT_AP; // 1st initialization time after partitioning [241:241]
+ UINT8 CORRECTLY_PRG_SECTORS_NUM[4]; // Number of correctly programmed sectors [245:242]
+ UINT8 BKOPS_STATUS; // Background operations status [246:246]
+ UINT8 POWER_OFF_LONG_TIME; // Power off notification (long) timeout [247:247]
+ UINT8 GENERIC_CMD6_TIME; // Generic CMD6 timeout [248:248]
+ UINT8 CACHE_SIZE[4]; // Cache size [252:249]
+ UINT8 PWR_CL_DDR_200_360; // Power class for 200MHz, DDR at VCC=3.6V [253:253]
+ UINT8 FIRMWARE_VERSION[8]; // Firmware version [261:254]
+ UINT8 DEVICE_VERSION[2]; // Device version [263:262]
+ UINT8 OPTIMAL_TRIM_UNIT_SIZE; // Optimal trim unit size [264:264]
+ UINT8 OPTIMAL_WRITE_SIZE; // Optimal write size [265:265]
+ UINT8 OPTIMAL_READ_SIZE; // Optimal read size [266:266]
+ UINT8 PRE_EOL_INFO; // Pre EOL information [267:267]
+ UINT8 DEVICE_LIFE_TIME_EST_TYP_A; // Device life time estimation type A [268:268]
+ UINT8 DEVICE_LIFE_TIME_EST_TYP_B; // Device life time estimation type B [269:269]
+ UINT8 VENDOR_PROPRIETARY_HEALTH_REPORT[32]; // Vendor proprietary health report [301:270]
+ UINT8 NUMBER_OF_FW_SECTORS_CORRECTLY_PROGRAMMED[4]; // Number of FW sectors correctly programmed [305:302]
+ UINT8 RESERVED_22[181]; // Reserved [486:306]
+ UINT8 FFU_ARG[4]; // FFU argument [490:487]
+ UINT8 OPERATION_CODE_TIMEOUT; // Operation codes timeout [491:491]
+ UINT8 FFU_FEATURES; // FFU features [492:492]
+ UINT8 SUPPORTED_MODES; // Supported modes [493:493]
+ UINT8 EXT_SUPPORT; // Extended partitions attribute support [494:494]
+ UINT8 LARGE_UNIT_SIZE_M1; // Large unit size [495:495]
+ UINT8 CONTEXT_CAPABILITIES; // Context management capabilities [496:496]
+ UINT8 TAG_RES_SIZE; // Tag resource size [497:497]
+ UINT8 TAG_UNIT_SIZE; // Tag unit size [498:498]
+ UINT8 DATA_TAG_SUPPORT; // Data tag support [499:499]
+ UINT8 MAX_PACKED_WRITES; // Max packed write commands [500:500]
+ UINT8 MAX_PACKED_READS; // Max packed read commands [501:501]
+ UINT8 BKOPS_SUPPORT; // Background operations support [502:502]
+ UINT8 HPI_FEATURES; // HPI features [503:503]
+ UINT8 S_CMD_SET; // Supported command sets [504:504]
+ UINT8 EXT_SECURITY_ERR; // Extended security commands error [505:505]
+ UINT8 RESERVED_23[6]; // Reserved [511:506]
+} ECSD;
+
typedef struct {
UINT16 RCA;
CARD_TYPE CardType;
OCR OCRData;
CID CIDData;
CSD CSDData;
- UINT32 ECSD[128]; // MMC V4 extended card specific
+ ECSD ECSDData; // MMC V4 extended card specific
} CARD_INFO;
typedef struct _MMC_HOST_INSTANCE {
diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
index 578fcb6..378e438 100644
--- a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
+++ b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
@@ -90,7 +90,7 @@ EmmcIdentificationMode (
DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD fetch error, Status=%r.\n", Status));
}
- Status = Host->ReadBlockData (Host, 0, 512, (UINT32 *)&(MmcHostInstance->CardInfo.ECSD));
+ Status = Host->ReadBlockData (Host, 0, 512, (UINT32 *)&(MmcHostInstance->CardInfo.ECSDData));
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD read error, Status=%r.\n", Status));
return Status;
@@ -103,7 +103,7 @@ EmmcIdentificationMode (
Media->LogicalBlocksPerPhysicalBlock = 1;
Media->IoAlign = 4;
// Compute last block using bits [215:212] of the ECSD
- Media->LastBlock = MmcHostInstance->CardInfo.ECSD[EMMC_ECSD_SIZE_OFFSET] - 1; // eMMC isn't supposed to report this for
+ Media->LastBlock = MmcHostInstance->CardInfo.ECSDData.SECTOR_COUNT - 1; // eMMC isn't supposed to report this for
// Cards <2GB in size, but the model does.
// Setup card type
--
2.7.4
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v5 4/9] MmcDxe: add SPEC_VERS field in CSD structure
2016-11-13 6:47 [PATCH v5 0/9] enhance MMC Haojian Zhuang
` (2 preceding siblings ...)
2016-11-13 6:47 ` [PATCH v5 3/9] MmcDxe: declare ECSD structure Haojian Zhuang
@ 2016-11-13 6:47 ` Haojian Zhuang
2016-11-13 6:47 ` [PATCH v5 5/9] MmcDxe: add interface to change io width and speed Haojian Zhuang
` (5 subsequent siblings)
9 siblings, 0 replies; 16+ messages in thread
From: Haojian Zhuang @ 2016-11-13 6:47 UTC (permalink / raw)
To: ryan.harkin, edk2-devel, leif.lindholm, ard.biesheuvel; +Cc: Haojian Zhuang
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Tested-by: Ryan Harkin <ryan.harkin@linaro.org>
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
---
EmbeddedPkg/Universal/MmcDxe/Mmc.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/EmbeddedPkg/Universal/MmcDxe/Mmc.h b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
index 25c69ae..67f449c 100644
--- a/EmbeddedPkg/Universal/MmcDxe/Mmc.h
+++ b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
@@ -128,7 +128,8 @@ typedef struct {
UINT8 NSAC ; // Data read access-time 2 in CLK cycles (NSAC*100) [111:104]
UINT8 TAAC ; // Data read access-time 1 [119:112]
- UINT8 RESERVED_5: 6; // Reserved [125:120]
+ UINT8 RESERVED_5: 2; // Reserved [121:120]
+ UINT8 SPEC_VERS: 4; // System specification version [125:122]
UINT8 CSD_STRUCTURE: 2; // CSD structure [127:126]
} CSD;
--
2.7.4
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v5 5/9] MmcDxe: add interface to change io width and speed
2016-11-13 6:47 [PATCH v5 0/9] enhance MMC Haojian Zhuang
` (3 preceding siblings ...)
2016-11-13 6:47 ` [PATCH v5 4/9] MmcDxe: add SPEC_VERS field in CSD structure Haojian Zhuang
@ 2016-11-13 6:47 ` Haojian Zhuang
2016-11-14 16:12 ` Leif Lindholm
2016-11-13 6:47 ` [PATCH v5 6/9] MmcDxe: set io bus width before reading EXTCSD Haojian Zhuang
` (4 subsequent siblings)
9 siblings, 1 reply; 16+ messages in thread
From: Haojian Zhuang @ 2016-11-13 6:47 UTC (permalink / raw)
To: ryan.harkin, edk2-devel, leif.lindholm, ard.biesheuvel; +Cc: Haojian Zhuang
By default, MMC is initialized with 1-bit mode and less than 400KHz bus
clock. It causes MMC working inefficiently.
Add the interface to change the bus width and speed.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Tested-by: Ryan Harkin <ryan.harkin@linaro.org>
---
EmbeddedPkg/Include/Protocol/MmcHost.h | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/EmbeddedPkg/Include/Protocol/MmcHost.h b/EmbeddedPkg/Include/Protocol/MmcHost.h
index 89f2e80..a242291 100644
--- a/EmbeddedPkg/Include/Protocol/MmcHost.h
+++ b/EmbeddedPkg/Include/Protocol/MmcHost.h
@@ -131,6 +131,12 @@ typedef EFI_STATUS (EFIAPI *MMC_WRITEBLOCKDATA) (
IN UINT32 *Buffer
);
+typedef EFI_STATUS (EFIAPI *MMC_SETIOS) (
+ IN EFI_MMC_HOST_PROTOCOL *This,
+ IN UINT32 BusClockRate,
+ IN UINT32 BusWidth
+ );
+
struct _EFI_MMC_HOST_PROTOCOL {
@@ -147,6 +153,8 @@ struct _EFI_MMC_HOST_PROTOCOL {
MMC_READBLOCKDATA ReadBlockData;
MMC_WRITEBLOCKDATA WriteBlockData;
+ MMC_SETIOS SetIos;
+
};
#define MMC_HOST_PROTOCOL_REVISION 0x00010001 // 1.1
--
2.7.4
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v5 6/9] MmcDxe: set io bus width before reading EXTCSD
2016-11-13 6:47 [PATCH v5 0/9] enhance MMC Haojian Zhuang
` (4 preceding siblings ...)
2016-11-13 6:47 ` [PATCH v5 5/9] MmcDxe: add interface to change io width and speed Haojian Zhuang
@ 2016-11-13 6:47 ` Haojian Zhuang
2016-11-14 16:36 ` Leif Lindholm
2016-11-13 6:47 ` [PATCH v5 7/9] MmcDxe: set iospeed and bus width in SD stack Haojian Zhuang
` (3 subsequent siblings)
9 siblings, 1 reply; 16+ messages in thread
From: Haojian Zhuang @ 2016-11-13 6:47 UTC (permalink / raw)
To: ryan.harkin, edk2-devel, leif.lindholm, ard.biesheuvel; +Cc: Haojian Zhuang
Set io bus width on both MMC controller and EXTCSD. Otherwise, it may
cause unmatched failure case. And support more timing mode, high speed,
HS200 & HS400 mode.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Tested-by: Ryan Harkin <ryan.harkin@linaro.org>
---
EmbeddedPkg/Include/Protocol/MmcHost.h | 16 +-
EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c | 229 ++++++++++++++++++++---
2 files changed, 221 insertions(+), 24 deletions(-)
diff --git a/EmbeddedPkg/Include/Protocol/MmcHost.h b/EmbeddedPkg/Include/Protocol/MmcHost.h
index a242291..01c0bf4 100644
--- a/EmbeddedPkg/Include/Protocol/MmcHost.h
+++ b/EmbeddedPkg/Include/Protocol/MmcHost.h
@@ -49,6 +49,7 @@ typedef UINT32 MMC_CMD;
#define MMC_CMD2 (MMC_INDX(2) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_LONG_RESPONSE)
#define MMC_CMD3 (MMC_INDX(3) | MMC_CMD_WAIT_RESPONSE)
#define MMC_CMD5 (MMC_INDX(5) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_NO_CRC_RESPONSE)
+#define MMC_CMD6 (MMC_INDX(6) | MMC_CMD_WAIT_RESPONSE)
#define MMC_CMD7 (MMC_INDX(7) | MMC_CMD_WAIT_RESPONSE)
#define MMC_CMD8 (MMC_INDX(8) | MMC_CMD_WAIT_RESPONSE)
#define MMC_CMD9 (MMC_INDX(9) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_LONG_RESPONSE)
@@ -82,6 +83,16 @@ typedef enum _MMC_STATE {
MmcDisconnectState,
} MMC_STATE;
+#define EMMCBACKWARD (0)
+#define EMMCHS26 (1 << 0) // High-Speed @26MHz at rated device voltages
+#define EMMCHS52 (1 << 1) // High-Speed @52MHz at rated device voltages
+#define EMMCHS52DDR1V8 (1 << 2) // High-Speed Dual Data Rate @52MHz 1.8V or 3V I/O
+#define EMMCHS52DDR1V2 (1 << 3) // High-Speed Dual Data Rate @52MHz 1.2V I/O
+#define EMMCHS200SDR1V8 (1 << 4) // HS200 Single Data Rate @200MHz 1.8V I/O
+#define EMMCHS200SDR1V2 (1 << 5) // HS200 Single Data Rate @200MHz 1.2V I/O
+#define EMMCHS400DDR1V8 (1 << 6) // HS400 Dual Data Rate @400MHz 1.8V I/O
+#define EMMCHS400DDR1V2 (1 << 7) // HS400 Dual Data Rate @400MHz 1.2V I/O
+
///
/// Forward declaration for EFI_MMC_HOST_PROTOCOL
///
@@ -133,8 +144,9 @@ typedef EFI_STATUS (EFIAPI *MMC_WRITEBLOCKDATA) (
typedef EFI_STATUS (EFIAPI *MMC_SETIOS) (
IN EFI_MMC_HOST_PROTOCOL *This,
- IN UINT32 BusClockRate,
- IN UINT32 BusWidth
+ IN UINT32 BusClockFreq,
+ IN UINT32 BusWidth,
+ IN UINT32 TimingMode
);
diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
index 378e438..9a79767 100644
--- a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
+++ b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
@@ -25,11 +25,109 @@ typedef union {
#define EMMC_CARD_SIZE 512
#define EMMC_ECSD_SIZE_OFFSET 53
+#define EXTCSD_BUS_WIDTH 183
+#define EXTCSD_HS_TIMING 185
+
+#define EMMC_TIMING_BACKWARD 0
+#define EMMC_TIMING_HS 1
+#define EMMC_TIMING_HS200 2
+#define EMMC_TIMING_HS400 3
+
+#define EMMC_BUS_WIDTH_1BIT 0
+#define EMMC_BUS_WIDTH_4BIT 1
+#define EMMC_BUS_WIDTH_8BIT 2
+#define EMMC_BUS_WIDTH_DDR_4BIT 5
+#define EMMC_BUS_WIDTH_DDR_8BIT 6
+
+#define EMMC_SWITCH_ERROR (1 << 7)
+
+#define DEVICE_STATE(x) (((x) >> 9) & 0xf)
+typedef enum _EMMC_DEVICE_STATE {
+ EMMC_IDLE_STATE = 0,
+ EMMC_READY_STATE,
+ EMMC_IDENT_STATE,
+ EMMC_STBY_STATE,
+ EMMC_TRAN_STATE,
+ EMMC_DATA_STATE,
+ EMMC_RCV_STATE,
+ EMMC_PRG_STATE,
+ EMMC_DIS_STATE,
+ EMMC_BTST_STATE,
+ EMMC_SLP_STATE
+} EMMC_DEVICE_STATE;
+
UINT32 mEmmcRcaCount = 0;
STATIC
EFI_STATUS
EFIAPI
+EmmcGetDeviceState (
+ IN MMC_HOST_INSTANCE *MmcHostInstance,
+ OUT EMMC_DEVICE_STATE *State
+ )
+{
+ EFI_MMC_HOST_PROTOCOL *Host;
+ EFI_STATUS Status;
+ UINT32 Data, RCA;
+
+ if (State == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ Host = MmcHostInstance->MmcHost;
+ RCA = MmcHostInstance->CardInfo.RCA << RCA_SHIFT_OFFSET;
+ Status = Host->SendCommand (Host, MMC_CMD13, RCA);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to get card status, Status=%r.\n", Status));
+ return Status;
+ }
+ Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R1, &Data);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to get response of CMD13, Status=%r.\n", Status));
+ return Status;
+ }
+ if (Data & EMMC_SWITCH_ERROR) {
+ DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to switch expected mode, Status=%r.\n", Status));
+ return EFI_DEVICE_ERROR;
+ }
+ *State = DEVICE_STATE(Data);
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+EmmcSetEXTCSD (
+ IN MMC_HOST_INSTANCE *MmcHostInstance,
+ UINT32 ExtCmdIndex,
+ UINT32 Value
+ )
+{
+ EFI_MMC_HOST_PROTOCOL *Host;
+ EMMC_DEVICE_STATE State;
+ EFI_STATUS Status;
+ UINT32 Argument;
+
+ Host = MmcHostInstance->MmcHost;
+ Argument = (3 << 24) | ((ExtCmdIndex & 0xff) << 16) | ((Value & 0xff) << 8) | 1;
+ Status = Host->SendCommand (Host, MMC_CMD6, Argument);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EmmcSetEXTCSD(): Failed to send CMD6, Status=%r.\n", Status));
+ return Status;
+ }
+ // Make sure device exiting prog mode
+ do {
+ Status = EmmcGetDeviceState (MmcHostInstance, &State);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EmmcSetEXTCSD(): Failed to get device state, Status=%r.\n", Status));
+ return Status;
+ }
+ } while (State == EMMC_PRG_STATE);
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
EmmcIdentificationMode (
IN MMC_HOST_INSTANCE *MmcHostInstance,
IN OCR_RESPONSE Response
@@ -37,6 +135,7 @@ EmmcIdentificationMode (
{
EFI_MMC_HOST_PROTOCOL *Host;
EFI_BLOCK_IO_MEDIA *Media;
+ EMMC_DEVICE_STATE State;
EFI_STATUS Status;
UINT32 RCA;
@@ -84,35 +183,117 @@ EmmcIdentificationMode (
DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Card selection error, Status=%r.\n", Status));
}
- // Fetch ECSD
- Status = Host->SendCommand (Host, MMC_CMD8, RCA);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD fetch error, Status=%r.\n", Status));
- }
-
- Status = Host->ReadBlockData (Host, 0, 512, (UINT32 *)&(MmcHostInstance->CardInfo.ECSDData));
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD read error, Status=%r.\n", Status));
- return Status;
- }
-
+ // MMC v4 specific
+ if (MmcHostInstance->CardInfo.CSDData.SPEC_VERS == 4) {
+ if (Host->SetIos) {
+ // Set 1-bit bus width
+ Status = Host->SetIos (Host, 0, 1, EMMCBACKWARD);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Set 1-bit bus width error, Status=%r.\n", Status));
+ return Status;
+ }
+
+ // Set 1-bit bus width for EXTCSD
+ Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_BUS_WIDTH, EMMC_BUS_WIDTH_1BIT);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Set extcsd bus width error, Status=%r.\n", Status));
+ return Status;
+ }
+ }
+
+ // Fetch ECSD
+ Status = Host->SendCommand (Host, MMC_CMD8, RCA);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD fetch error, Status=%r.\n", Status));
+ }
+ Status = Host->ReadBlockData (Host, 0, 512, (UINT32 *)&(MmcHostInstance->CardInfo.ECSDData));
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD read error, Status=%r.\n", Status));
+ return Status;
+ }
+
+ // Make sure device exiting data mode
+ do {
+ Status = EmmcGetDeviceState (MmcHostInstance, &State);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Failed to get device state, Status=%r.\n", Status));
+ return Status;
+ }
+ } while (State == EMMC_DATA_STATE);
+
+ // Compute last block using bits [215:212] of the ECSD
+ Media->LastBlock = MmcHostInstance->CardInfo.ECSDData.SECTOR_COUNT - 1; // eMMC isn't supposed to report this for
+ // Cards <2GB in size, but the model does.
+
+ // Setup card type
+ MmcHostInstance->CardInfo.CardType = EMMC_CARD;
+ }
// Set up media
Media->BlockSize = EMMC_CARD_SIZE; // 512-byte support is mandatory for eMMC cards
Media->MediaId = MmcHostInstance->CardInfo.CIDData.PSN;
Media->ReadOnly = MmcHostInstance->CardInfo.CSDData.PERM_WRITE_PROTECT;
Media->LogicalBlocksPerPhysicalBlock = 1;
Media->IoAlign = 4;
- // Compute last block using bits [215:212] of the ECSD
- Media->LastBlock = MmcHostInstance->CardInfo.ECSDData.SECTOR_COUNT - 1; // eMMC isn't supposed to report this for
- // Cards <2GB in size, but the model does.
-
- // Setup card type
- MmcHostInstance->CardInfo.CardType = EMMC_CARD;
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
+InitializeEmmcDevice (
+ IN MMC_HOST_INSTANCE *MmcHostInstance
+ )
+{
+ EFI_MMC_HOST_PROTOCOL *Host;
+ EFI_STATUS Status = EFI_SUCCESS;
+ ECSD *ECSDData;
+ BOOLEAN Found = FALSE;
+ UINT32 BusClockFreq, Idx;
+ UINT32 TimingMode[4] = {EMMCHS52DDR1V2, EMMCHS52DDR1V8, EMMCHS52, EMMCHS26};
+
+ Host = MmcHostInstance->MmcHost;
+ if (MmcHostInstance->CardInfo.CSDData.SPEC_VERS < 4)
+ return EFI_SUCCESS;
+ ECSDData = &MmcHostInstance->CardInfo.ECSDData;
+ if (ECSDData->DEVICE_TYPE == EMMCBACKWARD)
+ return EFI_SUCCESS;
+
+ if (Host->SetIos) {
+ Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_HS_TIMING, EMMC_TIMING_HS);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "InitializeEmmcDevice(): Failed to switch high speed mode, Status:%r.\n", Status));
+ return Status;
+ }
+
+ for (Idx = 0; Idx < 4; Idx++) {
+ switch (TimingMode[Idx]) {
+ case EMMCHS52DDR1V2:
+ case EMMCHS52DDR1V8:
+ case EMMCHS52:
+ BusClockFreq = 52000000;
+ break;
+ case EMMCHS26:
+ BusClockFreq = 26000000;
+ break;
+ default:
+ return EFI_UNSUPPORTED;
+ }
+ Status = Host->SetIos (Host, BusClockFreq, 8, TimingMode[Idx]);
+ if (!EFI_ERROR (Status)) {
+ Found = TRUE;
+ break;
+ }
+ }
+ if (Found) {
+ Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_BUS_WIDTH, EMMC_BUS_WIDTH_DDR_8BIT);
+ if (EFI_ERROR (Status))
+ DEBUG ((DEBUG_ERROR, "InitializeEmmcDevice(): Failed to set EXTCSD bus width, Status:%r\n", Status));
+ }
+ }
+ return Status;
+}
+
+STATIC
+EFI_STATUS
InitializeSdMmcDevice (
IN MMC_HOST_INSTANCE *MmcHostInstance
)
@@ -429,11 +610,15 @@ InitializeMmcDevice (
return Status;
}
- if (MmcHostInstance->CardInfo.CardType != EMMC_CARD) {
- Status = InitializeSdMmcDevice (MmcHostInstance);
- if (EFI_ERROR (Status)) {
- return Status;
+ if (MmcHostInstance->CardInfo.CardType == EMMC_CARD) {
+ if (MmcHost->SetIos) {
+ Status = InitializeEmmcDevice (MmcHostInstance);
}
+ } else {
+ Status = InitializeSdMmcDevice (MmcHostInstance);
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
}
// Set Block Length
--
2.7.4
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v5 7/9] MmcDxe: set iospeed and bus width in SD stack
2016-11-13 6:47 [PATCH v5 0/9] enhance MMC Haojian Zhuang
` (5 preceding siblings ...)
2016-11-13 6:47 ` [PATCH v5 6/9] MmcDxe: set io bus width before reading EXTCSD Haojian Zhuang
@ 2016-11-13 6:47 ` Haojian Zhuang
2016-11-14 17:08 ` Leif Lindholm
2016-11-13 6:47 ` [PATCH v5 8/9] MmcDxe: expand to support multiple blocks Haojian Zhuang
` (2 subsequent siblings)
9 siblings, 1 reply; 16+ messages in thread
From: Haojian Zhuang @ 2016-11-13 6:47 UTC (permalink / raw)
To: ryan.harkin, edk2-devel, leif.lindholm, ard.biesheuvel; +Cc: Haojian Zhuang
Add more SD commands to support 4-bit bus width & iospeed. It's not
formal code. And it needs to be updated later.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Tested-by: Ryan Harkin <ryan.harkin@linaro.org>
---
EmbeddedPkg/Include/Protocol/MmcHost.h | 3 +
EmbeddedPkg/Universal/MmcDxe/Mmc.h | 17 +++
EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c | 138 ++++++++++++++++++++---
3 files changed, 142 insertions(+), 16 deletions(-)
diff --git a/EmbeddedPkg/Include/Protocol/MmcHost.h b/EmbeddedPkg/Include/Protocol/MmcHost.h
index 01c0bf4..5028045 100644
--- a/EmbeddedPkg/Include/Protocol/MmcHost.h
+++ b/EmbeddedPkg/Include/Protocol/MmcHost.h
@@ -64,11 +64,14 @@ typedef UINT32 MMC_CMD;
#define MMC_CMD24 (MMC_INDX(24) | MMC_CMD_WAIT_RESPONSE)
#define MMC_CMD55 (MMC_INDX(55) | MMC_CMD_WAIT_RESPONSE)
#define MMC_ACMD41 (MMC_INDX(41) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_NO_CRC_RESPONSE)
+#define MMC_ACMD51 (MMC_INDX(51) | MMC_CMD_WAIT_RESPONSE)
// Valid responses for CMD1 in eMMC
#define EMMC_CMD1_CAPACITY_LESS_THAN_2GB 0x00FF8080 // Capacity <= 2GB, byte addressing used
#define EMMC_CMD1_CAPACITY_GREATER_THAN_2GB 0x40FF8080 // Capacity > 2GB, 512-byte sector addressing used
+#define MMC_STATUS_APP_CMD (1 << 5)
+
typedef enum _MMC_STATE {
MmcInvalidState = 0,
MmcHwInitializationState,
diff --git a/EmbeddedPkg/Universal/MmcDxe/Mmc.h b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
index 67f449c..f054bb2 100644
--- a/EmbeddedPkg/Universal/MmcDxe/Mmc.h
+++ b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
@@ -75,6 +75,23 @@ typedef struct {
UINT32 PowerUp: 1; // This bit is set to LOW if the card has not finished the power up routine
} OCR;
+/* For little endian CPU */
+typedef struct {
+ UINT8 SD_SPEC: 4; // SD Memory Card - Spec. Version [59:56]
+ UINT8 SCR_STRUCTURE: 4; // SCR Structure [63:60]
+ UINT8 SD_BUS_WIDTHS: 4; // DAT Bus widths supported [51:48]
+ UINT8 DATA_STAT_AFTER_ERASE: 1; // Data Status after erases [55]
+ UINT8 SD_SECURITY: 3; // CPRM Security Support [54:52]
+ UINT8 EX_SECURITY_1: 1; // Extended Security Support [43]
+ UINT8 SD_SPEC4: 1; // Spec. Version 4.00 or higher [42]
+ UINT8 RESERVED_1: 2; // Reserved [41:40]
+ UINT8 SD_SPEC3: 1; // Spec. Version 3.00 or higher [47]
+ UINT8 EX_SECURITY_2: 3; // Extended Security Support [46:44]
+ UINT8 CMD_SUPPORT: 4; // Command Support bits [35:32]
+ UINT8 RESERVED_2: 4; // Reserved [39:36]
+ UINT32 RESERVED_3; // Manufacturer Usage [31:0]
+} SCR;
+
typedef struct {
UINT32 NOT_USED; // 1 [0:0]
UINT32 CRC; // CRC7 checksum [7:1]
diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
index 9a79767..c469dda 100644
--- a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
+++ b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
@@ -12,6 +12,9 @@
*
**/
+#include <Library/BaseMemoryLib.h>
+#include <Library/TimerLib.h>
+
#include "Mmc.h"
typedef union {
@@ -41,6 +44,11 @@ typedef union {
#define EMMC_SWITCH_ERROR (1 << 7)
+#define SD_BUS_WIDTH_1BIT (1 << 0)
+#define SD_BUS_WIDTH_4BIT (1 << 2)
+
+#define SD_CCC_SWITCH (1 << 10)
+
#define DEVICE_STATE(x) (((x) >> 9) & 0xf)
typedef enum _EMMC_DEVICE_STATE {
EMMC_IDLE_STATE = 0,
@@ -68,28 +76,30 @@ EmmcGetDeviceState (
{
EFI_MMC_HOST_PROTOCOL *Host;
EFI_STATUS Status;
- UINT32 Data, RCA;
+ UINT32 Rsp[4], RCA;
if (State == NULL)
return EFI_INVALID_PARAMETER;
Host = MmcHostInstance->MmcHost;
RCA = MmcHostInstance->CardInfo.RCA << RCA_SHIFT_OFFSET;
- Status = Host->SendCommand (Host, MMC_CMD13, RCA);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to get card status, Status=%r.\n", Status));
- return Status;
- }
- Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R1, &Data);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to get response of CMD13, Status=%r.\n", Status));
- return Status;
- }
- if (Data & EMMC_SWITCH_ERROR) {
- DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to switch expected mode, Status=%r.\n", Status));
- return EFI_DEVICE_ERROR;
- }
- *State = DEVICE_STATE(Data);
+ do {
+ Status = Host->SendCommand (Host, MMC_CMD13, RCA);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to get card status, Status=%r.\n", Status));
+ return Status;
+ }
+ Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R1, Rsp);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to get response of CMD13, Status=%r.\n", Status));
+ return Status;
+ }
+ if (Rsp[0] & EMMC_SWITCH_ERROR) {
+ DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to switch expected mode, Status=%r.\n", Status));
+ return EFI_DEVICE_ERROR;
+ }
+ } while (!(Rsp[0] & MMC_R0_READY_FOR_DATA));
+ *State = MMC_R0_CURRENTSTATE(Rsp);
return EFI_SUCCESS;
}
@@ -300,9 +310,12 @@ InitializeSdMmcDevice (
{
UINT32 CmdArg;
UINT32 Response[4];
+ UINT32 Buffer[128];
UINTN BlockSize;
UINTN CardSize;
UINTN NumBlocks;
+ BOOLEAN CccSwitch;
+ SCR Scr;
EFI_STATUS Status;
EFI_MMC_HOST_PROTOCOL *MmcHost;
@@ -323,6 +336,10 @@ InitializeSdMmcDevice (
return Status;
}
PrintCSD (Response);
+ if (MMC_CSD_GET_CCC(Response) & SD_CCC_SWITCH)
+ CccSwitch = TRUE;
+ else
+ CccSwitch = FALSE;
if (MmcHostInstance->CardInfo.CardType == SD_CARD_2_HIGH) {
CardSize = HC_MMC_CSD_GET_DEVICESIZE (Response);
@@ -353,6 +370,95 @@ InitializeSdMmcDevice (
return Status;
}
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, CmdArg);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a(MMC_CMD55): Error and Status = %r\n", Status));
+ return Status;
+ }
+ Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a(MMC_CMD55): Error and Status = %r\n", Status));
+ return Status;
+ }
+ if ((Response[0] & MMC_STATUS_APP_CMD) == 0)
+ return EFI_SUCCESS;
+
+ /* SCR */
+ Status = MmcHost->SendCommand (MmcHost, MMC_ACMD51, 0);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a(MMC_ACMD51): Error and Status = %r\n", __func__, Status));
+ return Status;
+ } else {
+ Status = MmcHost->ReadBlockData (MmcHost, 0, 8, Buffer);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a(MMC_ACMD51): ReadBlockData Error and Status = %r\n", __func__, Status));
+ return Status;
+ }
+ CopyMem (&Scr, Buffer, 8);
+ if (Scr.SD_SPEC == 2) {
+ if (Scr.SD_SPEC3 == 1) {
+ if (Scr.SD_SPEC4 == 1) {
+ DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 4.xx\n"));
+ } else {
+ DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 3.0x\n"));
+ }
+ } else {
+ if (Scr.SD_SPEC4 == 0) {
+ DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 2.0\n"));
+ } else {
+ DEBUG ((EFI_D_ERROR, "Found invalid SD Card\n"));
+ }
+ }
+ } else {
+ if ((Scr.SD_SPEC3 == 0) && (Scr.SD_SPEC4 == 0)) {
+ if (Scr.SD_SPEC == 1) {
+ DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 1.10\n"));
+ } else {
+ DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 1.0\n"));
+ }
+ } else {
+ DEBUG ((EFI_D_ERROR, "Found invalid SD Card\n"));
+ }
+ }
+ }
+ if (CccSwitch) {
+ /* SD Switch, Mode:1, Group:0, Value:1 */
+ CmdArg = 1 << 31 | 0x00FFFFFF;
+ CmdArg &= ~(0xF << (0 * 4));
+ CmdArg |= 1 << (0 * 4);
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, CmdArg);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a(MMC_CMD6): Error and Status = %r\n", Status));
+ return Status;
+ } else {
+ Status = MmcHost->ReadBlockData (MmcHost, 0, 64, Buffer);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a(MMC_CMD6): ReadBlockData Error and Status = %r\n", Status));
+ return Status;
+ }
+ }
+ }
+ if (Scr.SD_BUS_WIDTHS & SD_BUS_WIDTH_4BIT) {
+ CmdArg = MmcHostInstance->CardInfo.RCA << 16;
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, CmdArg);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a(MMC_CMD55): Error and Status = %r\n", Status));
+ return Status;
+ }
+ /* Width: 4 */
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, 2);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a(MMC_CMD6): Error and Status = %r\n", Status));
+ return Status;
+ }
+ }
+ if (MmcHost->SetIos) {
+ Status = MmcHost->SetIos (MmcHost, 24 * 1000 * 1000, 4, EMMCBACKWARD);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a(SetIos): Error and Status = %r\n", Status));
+ return Status;
+ }
+ }
return EFI_SUCCESS;
}
--
2.7.4
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v5 8/9] MmcDxe: expand to support multiple blocks
2016-11-13 6:47 [PATCH v5 0/9] enhance MMC Haojian Zhuang
` (6 preceding siblings ...)
2016-11-13 6:47 ` [PATCH v5 7/9] MmcDxe: set iospeed and bus width in SD stack Haojian Zhuang
@ 2016-11-13 6:47 ` Haojian Zhuang
2016-11-14 17:15 ` Leif Lindholm
2016-11-13 6:47 ` [PATCH v5 9/9] PL180: update for indentifying SD Haojian Zhuang
2016-11-14 15:53 ` [PATCH v5 0/9] enhance MMC Leif Lindholm
9 siblings, 1 reply; 16+ messages in thread
From: Haojian Zhuang @ 2016-11-13 6:47 UTC (permalink / raw)
To: ryan.harkin, edk2-devel, leif.lindholm, ard.biesheuvel; +Cc: Haojian Zhuang
Make use of DMA to transfer multiple blocks at one time. It could
improve the performance on MMC/SD driver.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Tested-by: Ryan Harkin <ryan.harkin@linaro.org>
---
EmbeddedPkg/Include/Protocol/MmcHost.h | 6 +
EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c | 177 ++++++++++++++++++++----------
2 files changed, 123 insertions(+), 60 deletions(-)
diff --git a/EmbeddedPkg/Include/Protocol/MmcHost.h b/EmbeddedPkg/Include/Protocol/MmcHost.h
index 5028045..cd5335a 100644
--- a/EmbeddedPkg/Include/Protocol/MmcHost.h
+++ b/EmbeddedPkg/Include/Protocol/MmcHost.h
@@ -62,6 +62,7 @@ typedef UINT32 MMC_CMD;
#define MMC_CMD20 (MMC_INDX(20) | MMC_CMD_WAIT_RESPONSE)
#define MMC_CMD23 (MMC_INDX(23) | MMC_CMD_WAIT_RESPONSE)
#define MMC_CMD24 (MMC_INDX(24) | MMC_CMD_WAIT_RESPONSE)
+#define MMC_CMD25 (MMC_INDX(25) | MMC_CMD_WAIT_RESPONSE)
#define MMC_CMD55 (MMC_INDX(55) | MMC_CMD_WAIT_RESPONSE)
#define MMC_ACMD41 (MMC_INDX(41) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_NO_CRC_RESPONSE)
#define MMC_ACMD51 (MMC_INDX(51) | MMC_CMD_WAIT_RESPONSE)
@@ -152,6 +153,10 @@ typedef EFI_STATUS (EFIAPI *MMC_SETIOS) (
IN UINT32 TimingMode
);
+typedef BOOLEAN (EFIAPI *MMC_ISMULTIBLOCK) (
+ IN EFI_MMC_HOST_PROTOCOL *This
+ );
+
struct _EFI_MMC_HOST_PROTOCOL {
@@ -169,6 +174,7 @@ struct _EFI_MMC_HOST_PROTOCOL {
MMC_WRITEBLOCKDATA WriteBlockData;
MMC_SETIOS SetIos;
+ MMC_ISMULTIBLOCK IsMultiBlock;
};
diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c b/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c
index 0e1ef57..1fcb3b5 100644
--- a/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c
+++ b/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c
@@ -126,6 +126,95 @@ MmcStopTransmission (
#define MMCI0_BLOCKLEN 512
#define MMCI0_TIMEOUT 10000
+STATIC EFI_STATUS
+MmcTransferBlock (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINTN Cmd,
+ IN UINTN Transfer,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN CmdArg;
+ INTN Timeout;
+ UINT32 Response[4];
+ MMC_HOST_INSTANCE *MmcHostInstance;
+ EFI_MMC_HOST_PROTOCOL *MmcHost;
+
+ MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS (This);
+ MmcHost = MmcHostInstance->MmcHost;
+
+ //Set command argument based on the card access mode (Byte mode or Block mode)
+ if (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1) {
+ CmdArg = Lba;
+ } else {
+ CmdArg = Lba * This->Media->BlockSize;
+ }
+
+ Status = MmcHost->SendCommand (MmcHost, Cmd, CmdArg);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a(MMC_CMD%d): Error %r\n", __func__, Cmd, Status));
+ return Status;
+ }
+
+ if (Transfer == MMC_IOBLOCKS_READ) {
+ // Read Data
+ Status = MmcHost->ReadBlockData (MmcHost, Lba, BufferSize, Buffer);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_BLKIO, "%a(): Error Read Block Data and Status = %r\n", __func__, Status));
+ MmcStopTransmission (MmcHost);
+ return Status;
+ }
+ Status = MmcNotifyState (MmcHostInstance, MmcProgrammingState);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a() : Error MmcProgrammingState\n", __func__));
+ return Status;
+ }
+ } else {
+ // Write Data
+ Status = MmcHost->WriteBlockData (MmcHost, Lba, BufferSize, Buffer);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_BLKIO, "%a(): Error Write Block Data and Status = %r\n", __func__, Status));
+ MmcStopTransmission (MmcHost);
+ return Status;
+ }
+ }
+
+ // Command 13 - Read status and wait for programming to complete (return to tran)
+ Timeout = MMCI0_TIMEOUT;
+ CmdArg = MmcHostInstance->CardInfo.RCA << 16;
+ Response[0] = 0;
+ while(!(Response[0] & MMC_R0_READY_FOR_DATA)
+ && (MMC_R0_CURRENTSTATE (Response) != MMC_R0_STATE_TRAN)
+ && Timeout--) {
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD13, CmdArg);
+ if (!EFI_ERROR (Status)) {
+ MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);
+ if (Response[0] & MMC_R0_READY_FOR_DATA) {
+ break; // Prevents delay once finished
+ }
+ }
+ gBS->Stall (1);
+ }
+
+ if (BufferSize > This->Media->BlockSize) {
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD12, 0);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_BLKIO, "%a(): Error and Status:%r\n", __func__, Status));
+ }
+ }
+
+ Status = MmcNotifyState (MmcHostInstance, MmcTransferState);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MmcIoBlocks() : Error MmcTransferState\n"));
+ return Status;
+ }
+ return Status;
+}
+
EFI_STATUS
MmcIoBlocks (
IN EFI_BLOCK_IO_PROTOCOL *This,
@@ -145,6 +234,7 @@ MmcIoBlocks (
EFI_MMC_HOST_PROTOCOL *MmcHost;
UINTN BytesRemainingToBeTransfered;
UINTN BlockCount;
+ UINTN ConsumeSize;
BlockCount = 1;
MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS (This);
@@ -165,6 +255,10 @@ MmcIoBlocks (
return EFI_NO_MEDIA;
}
+ if (MmcHost->IsMultiBlock && MmcHost->IsMultiBlock(MmcHost)) {
+ BlockCount = (BufferSize + This->Media->BlockSize - 1) / This->Media->BlockSize;
+ }
+
// All blocks must be within the device
if ((Lba + (BufferSize / This->Media->BlockSize)) > (This->Media->LastBlock + 1)) {
return EFI_INVALID_PARAMETER;
@@ -196,7 +290,7 @@ MmcIoBlocks (
CmdArg = MmcHostInstance->CardInfo.RCA << 16;
Response[0] = 0;
Timeout = 20;
- while( (!(Response[0] & MMC_R0_READY_FOR_DATA))
+ while(!(Response[0] & MMC_R0_READY_FOR_DATA)
&& (MMC_R0_CURRENTSTATE (Response) != MMC_R0_STATE_TRAN)
&& Timeout--) {
Status = MmcHost->SendCommand (MmcHost, MMC_CMD13, CmdArg);
@@ -210,75 +304,38 @@ MmcIoBlocks (
return EFI_NOT_READY;
}
- //Set command argument based on the card access mode (Byte mode or Block mode)
- if (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1) {
- CmdArg = Lba;
- } else {
- CmdArg = Lba * This->Media->BlockSize;
- }
-
if (Transfer == MMC_IOBLOCKS_READ) {
- // Read a single block
- Cmd = MMC_CMD17;
- } else {
- // Write a single block
- Cmd = MMC_CMD24;
- }
- Status = MmcHost->SendCommand (MmcHost, Cmd, CmdArg);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "MmcIoBlocks(MMC_CMD%d): Error %r\n", Cmd, Status));
- return Status;
- }
-
- if (Transfer == MMC_IOBLOCKS_READ) {
- // Read one block of Data
- Status = MmcHost->ReadBlockData (MmcHost, Lba, This->Media->BlockSize, Buffer);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_BLKIO, "MmcIoBlocks(): Error Read Block Data and Status = %r\n", Status));
- MmcStopTransmission (MmcHost);
- return Status;
- }
- Status = MmcNotifyState (MmcHostInstance, MmcProgrammingState);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "MmcIoBlocks() : Error MmcProgrammingState\n"));
- return Status;
+ if (BlockCount == 1) {
+ // Read a single block
+ Cmd = MMC_CMD17;
+ } else {
+ // Read multiple blocks
+ Cmd = MMC_CMD18;
}
} else {
- // Write one block of Data
- Status = MmcHost->WriteBlockData (MmcHost, Lba, This->Media->BlockSize, Buffer);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_BLKIO, "MmcIoBlocks(): Error Write Block Data and Status = %r\n", Status));
- MmcStopTransmission (MmcHost);
- return Status;
+ if (BlockCount == 1) {
+ // Write a single block
+ Cmd = MMC_CMD24;
+ } else {
+ // Write multiple blocks
+ Cmd = MMC_CMD25;
}
}
- // Command 13 - Read status and wait for programming to complete (return to tran)
- Timeout = MMCI0_TIMEOUT;
- CmdArg = MmcHostInstance->CardInfo.RCA << 16;
- Response[0] = 0;
- while( (!(Response[0] & MMC_R0_READY_FOR_DATA))
- && (MMC_R0_CURRENTSTATE (Response) != MMC_R0_STATE_TRAN)
- && Timeout--) {
- Status = MmcHost->SendCommand (MmcHost, MMC_CMD13, CmdArg);
- if (!EFI_ERROR (Status)) {
- MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);
- if ((Response[0] & MMC_R0_READY_FOR_DATA)) {
- break; // Prevents delay once finished
- }
- }
- gBS->Stall (1);
+ ConsumeSize = BlockCount * This->Media->BlockSize;
+ if (BytesRemainingToBeTransfered < ConsumeSize) {
+ ConsumeSize = BytesRemainingToBeTransfered;
}
-
- Status = MmcNotifyState (MmcHostInstance, MmcTransferState);
+ Status = MmcTransferBlock (This, Cmd, Transfer, MediaId, Lba, ConsumeSize, Buffer);
if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "MmcIoBlocks() : Error MmcTransferState\n"));
- return Status;
+ DEBUG ((EFI_D_ERROR, "%a(): Failed to transfer block and Status:%r\n", __func__, Status));
}
- BytesRemainingToBeTransfered -= This->Media->BlockSize;
- Lba += BlockCount;
- Buffer = (UINT8 *)Buffer + This->Media->BlockSize;
+ BytesRemainingToBeTransfered -= ConsumeSize;
+ if (BytesRemainingToBeTransfered > 0) {
+ Lba += BlockCount;
+ Buffer = (UINT8 *)Buffer + ConsumeSize;
+ }
}
return EFI_SUCCESS;
--
2.7.4
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v5 9/9] PL180: update for indentifying SD
2016-11-13 6:47 [PATCH v5 0/9] enhance MMC Haojian Zhuang
` (7 preceding siblings ...)
2016-11-13 6:47 ` [PATCH v5 8/9] MmcDxe: expand to support multiple blocks Haojian Zhuang
@ 2016-11-13 6:47 ` Haojian Zhuang
2016-11-14 17:27 ` Leif Lindholm
2016-11-14 15:53 ` [PATCH v5 0/9] enhance MMC Leif Lindholm
9 siblings, 1 reply; 16+ messages in thread
From: Haojian Zhuang @ 2016-11-13 6:47 UTC (permalink / raw)
To: ryan.harkin, edk2-devel, leif.lindholm, ard.biesheuvel; +Cc: Haojian Zhuang
When CMD6 & ACMD51 are added into indentifying SD process, PL180
should also support CMD6 & ACMD51. Otherwise, it'll hang when
system tries to read expected data.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Tested-by: Ryan Harkin <ryan.harkin@linaro.org>
---
ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c | 29 ++++++++++++++++++++-------
1 file changed, 22 insertions(+), 7 deletions(-)
diff --git a/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c b/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
index 5526aac..b2ba4c0 100644
--- a/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
+++ b/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
@@ -63,11 +63,6 @@ MciIsReadOnly (
return (MmioRead32 (FixedPcdGet32 (PcdPL180SysMciRegAddress)) & SYS_MCI_WPROT);
}
-#if 0
-//Note: This function has been commented out because it is not used yet.
-// This function could be used to remove the hardcoded BlockLen used
-// in MciPrepareDataPath
-
// Convert block size to 2^n
STATIC
UINT32
@@ -87,7 +82,6 @@ GetPow2BlockLen (
return Pow2BlockLen;
}
-#endif
VOID
MciPrepareDataPath (
@@ -126,6 +120,23 @@ MciSendCommand (
MciPrepareDataPath (MCI_DATACTL_CARD_TO_CONT);
} else if ((MmcCmd == MMC_CMD24) || (MmcCmd == MMC_CMD20)) {
MciPrepareDataPath (MCI_DATACTL_CONT_TO_CARD);
+ } else if (MmcCmd == MMC_CMD6) {
+ MmioWrite32 (MCI_DATA_TIMER_REG, 0xFFFFFFF);
+ MmioWrite32 (MCI_DATA_LENGTH_REG, 64);
+#ifndef USE_STREAM
+ MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_CARD_TO_CONT | GetPow2BlockLen (64));
+#else
+ MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_CARD_TO_CONT | MCI_DATACTL_STREAM_TRANS);
+#endif
+ } else if (MmcCmd == MMC_ACMD51) {
+ MmioWrite32 (MCI_DATA_TIMER_REG, 0xFFFFFFF);
+ /* SCR register is 8 bytes long. */
+ MmioWrite32 (MCI_DATA_LENGTH_REG, 8);
+#ifndef USE_STREAM
+ MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_CARD_TO_CONT | GetPow2BlockLen (8));
+#else
+ MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_CARD_TO_CONT | MCI_DATACTL_STREAM_TRANS);
+#endif
}
// Create Command for PL180
@@ -223,7 +234,11 @@ MciReadBlockData (
// Read data from the RX FIFO
Loop = 0;
- Finish = MMCI0_BLOCKLEN / 4;
+ if (Length < MMCI0_BLOCKLEN) {
+ Finish = Length / 4;
+ } else {
+ Finish = MMCI0_BLOCKLEN / 4;
+ }
// Raise the TPL at the highest level to disable Interrupts.
Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
--
2.7.4
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH v5 0/9] enhance MMC
2016-11-13 6:47 [PATCH v5 0/9] enhance MMC Haojian Zhuang
` (8 preceding siblings ...)
2016-11-13 6:47 ` [PATCH v5 9/9] PL180: update for indentifying SD Haojian Zhuang
@ 2016-11-14 15:53 ` Leif Lindholm
9 siblings, 0 replies; 16+ messages in thread
From: Leif Lindholm @ 2016-11-14 15:53 UTC (permalink / raw)
To: Haojian Zhuang; +Cc: ryan.harkin, edk2-devel, ard.biesheuvel
Thanks Haojian,
I've started by pushing 1-4, which all had Tested-by and Reviewed-by
already, to edk2/master as 3201075..653bde5.
Continuing with review of 5-9.
Regards,
Leif
On Sun, Nov 13, 2016 at 02:47:49PM +0800, Haojian Zhuang wrote:
> v5:
> * Remove patch on MediaId.
> * Squash two PL180 patches together.
>
> v4:
> * Fix PL180 hang in some cases. Since the proper variable length
> isn't set for CMD6 & ACMD51.
>
> v3:
> * Fix PL180 hang because of CMD6 & ACMD51 not supported.
>
> v2:
> * Fix print error with missing parameter.
> * Change CMD51 to ACMD51.
> * Add the protection after CMD55 for SD. If there's no
> response of CMD55, skip to send ACMD51.
>
> v1:
> * Wait OCR busy bit free according to eMMC spec.
> * Define ECSD structure.
> * Add interface to set IO bus width and speed.
> * Support to access multiple blocks.
>
> Haojian Zhuang (9):
> MmcDxe: wait OCR busy bit free
> MmcDxe: move ECSD into CardInfo structure
> MmcDxe: declare ECSD structure
> MmcDxe: add SPEC_VERS field in CSD structure
> MmcDxe: add interface to change io width and speed
> MmcDxe: set io bus width before reading EXTCSD
> MmcDxe: set iospeed and bus width in SD stack
> MmcDxe: expand to support multiple blocks
> PL180: update for indentifying SD
>
> ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c | 29 +-
> EmbeddedPkg/Include/Protocol/MmcHost.h | 29 ++
> EmbeddedPkg/Universal/MmcDxe/Mmc.h | 176 +++++++++++-
> EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c | 177 ++++++++----
> EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c | 347 +++++++++++++++++++++--
> 5 files changed, 664 insertions(+), 94 deletions(-)
>
> --
> 2.7.4
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v5 5/9] MmcDxe: add interface to change io width and speed
2016-11-13 6:47 ` [PATCH v5 5/9] MmcDxe: add interface to change io width and speed Haojian Zhuang
@ 2016-11-14 16:12 ` Leif Lindholm
0 siblings, 0 replies; 16+ messages in thread
From: Leif Lindholm @ 2016-11-14 16:12 UTC (permalink / raw)
To: Haojian Zhuang; +Cc: ryan.harkin, edk2-devel, ard.biesheuvel
On Sun, Nov 13, 2016 at 02:47:54PM +0800, Haojian Zhuang wrote:
> By default, MMC is initialized with 1-bit mode and less than 400KHz bus
> clock. It causes MMC working inefficiently.
>
> Add the interface to change the bus width and speed.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> Tested-by: Ryan Harkin <ryan.harkin@linaro.org>
So, I have no objections to this one, but on its own it provides no
new functionality, and the definition it introduces is changed in the
next patch. Can you squash this into 6/9 and add a line to the commit
message please?
/
Leif
> ---
> EmbeddedPkg/Include/Protocol/MmcHost.h | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/EmbeddedPkg/Include/Protocol/MmcHost.h b/EmbeddedPkg/Include/Protocol/MmcHost.h
> index 89f2e80..a242291 100644
> --- a/EmbeddedPkg/Include/Protocol/MmcHost.h
> +++ b/EmbeddedPkg/Include/Protocol/MmcHost.h
> @@ -131,6 +131,12 @@ typedef EFI_STATUS (EFIAPI *MMC_WRITEBLOCKDATA) (
> IN UINT32 *Buffer
> );
>
> +typedef EFI_STATUS (EFIAPI *MMC_SETIOS) (
> + IN EFI_MMC_HOST_PROTOCOL *This,
> + IN UINT32 BusClockRate,
> + IN UINT32 BusWidth
> + );
> +
>
> struct _EFI_MMC_HOST_PROTOCOL {
>
> @@ -147,6 +153,8 @@ struct _EFI_MMC_HOST_PROTOCOL {
> MMC_READBLOCKDATA ReadBlockData;
> MMC_WRITEBLOCKDATA WriteBlockData;
>
> + MMC_SETIOS SetIos;
> +
> };
>
> #define MMC_HOST_PROTOCOL_REVISION 0x00010001 // 1.1
> --
> 2.7.4
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v5 6/9] MmcDxe: set io bus width before reading EXTCSD
2016-11-13 6:47 ` [PATCH v5 6/9] MmcDxe: set io bus width before reading EXTCSD Haojian Zhuang
@ 2016-11-14 16:36 ` Leif Lindholm
0 siblings, 0 replies; 16+ messages in thread
From: Leif Lindholm @ 2016-11-14 16:36 UTC (permalink / raw)
To: Haojian Zhuang; +Cc: ryan.harkin, edk2-devel, ard.biesheuvel
On Sun, Nov 13, 2016 at 02:47:55PM +0800, Haojian Zhuang wrote:
> Set io bus width on both MMC controller and EXTCSD. Otherwise, it may
> cause unmatched failure case. And support more timing mode, high speed,
> HS200 & HS400 mode.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> Tested-by: Ryan Harkin <ryan.harkin@linaro.org>
> ---
> EmbeddedPkg/Include/Protocol/MmcHost.h | 16 +-
> EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c | 229 ++++++++++++++++++++---
> 2 files changed, 221 insertions(+), 24 deletions(-)
>
> diff --git a/EmbeddedPkg/Include/Protocol/MmcHost.h b/EmbeddedPkg/Include/Protocol/MmcHost.h
> index a242291..01c0bf4 100644
> --- a/EmbeddedPkg/Include/Protocol/MmcHost.h
> +++ b/EmbeddedPkg/Include/Protocol/MmcHost.h
> @@ -49,6 +49,7 @@ typedef UINT32 MMC_CMD;
> #define MMC_CMD2 (MMC_INDX(2) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_LONG_RESPONSE)
> #define MMC_CMD3 (MMC_INDX(3) | MMC_CMD_WAIT_RESPONSE)
> #define MMC_CMD5 (MMC_INDX(5) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_NO_CRC_RESPONSE)
> +#define MMC_CMD6 (MMC_INDX(6) | MMC_CMD_WAIT_RESPONSE)
> #define MMC_CMD7 (MMC_INDX(7) | MMC_CMD_WAIT_RESPONSE)
> #define MMC_CMD8 (MMC_INDX(8) | MMC_CMD_WAIT_RESPONSE)
> #define MMC_CMD9 (MMC_INDX(9) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_LONG_RESPONSE)
> @@ -82,6 +83,16 @@ typedef enum _MMC_STATE {
> MmcDisconnectState,
> } MMC_STATE;
>
> +#define EMMCBACKWARD (0)
> +#define EMMCHS26 (1 << 0) // High-Speed @26MHz at rated device voltages
> +#define EMMCHS52 (1 << 1) // High-Speed @52MHz at rated device voltages
> +#define EMMCHS52DDR1V8 (1 << 2) // High-Speed Dual Data Rate @52MHz 1.8V or 3V I/O
> +#define EMMCHS52DDR1V2 (1 << 3) // High-Speed Dual Data Rate @52MHz 1.2V I/O
> +#define EMMCHS200SDR1V8 (1 << 4) // HS200 Single Data Rate @200MHz 1.8V I/O
> +#define EMMCHS200SDR1V2 (1 << 5) // HS200 Single Data Rate @200MHz 1.2V I/O
> +#define EMMCHS400DDR1V8 (1 << 6) // HS400 Dual Data Rate @400MHz 1.8V I/O
> +#define EMMCHS400DDR1V2 (1 << 7) // HS400 Dual Data Rate @400MHz 1.2V I/O
> +
> ///
> /// Forward declaration for EFI_MMC_HOST_PROTOCOL
> ///
> @@ -133,8 +144,9 @@ typedef EFI_STATUS (EFIAPI *MMC_WRITEBLOCKDATA) (
>
> typedef EFI_STATUS (EFIAPI *MMC_SETIOS) (
> IN EFI_MMC_HOST_PROTOCOL *This,
> - IN UINT32 BusClockRate,
> - IN UINT32 BusWidth
> + IN UINT32 BusClockFreq,
> + IN UINT32 BusWidth,
> + IN UINT32 TimingMode
> );
>
>
> diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
> index 378e438..9a79767 100644
> --- a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
> +++ b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
> @@ -25,11 +25,109 @@ typedef union {
> #define EMMC_CARD_SIZE 512
> #define EMMC_ECSD_SIZE_OFFSET 53
>
> +#define EXTCSD_BUS_WIDTH 183
> +#define EXTCSD_HS_TIMING 185
> +
> +#define EMMC_TIMING_BACKWARD 0
> +#define EMMC_TIMING_HS 1
> +#define EMMC_TIMING_HS200 2
> +#define EMMC_TIMING_HS400 3
> +
> +#define EMMC_BUS_WIDTH_1BIT 0
> +#define EMMC_BUS_WIDTH_4BIT 1
> +#define EMMC_BUS_WIDTH_8BIT 2
> +#define EMMC_BUS_WIDTH_DDR_4BIT 5
> +#define EMMC_BUS_WIDTH_DDR_8BIT 6
> +
> +#define EMMC_SWITCH_ERROR (1 << 7)
> +
> +#define DEVICE_STATE(x) (((x) >> 9) & 0xf)
> +typedef enum _EMMC_DEVICE_STATE {
> + EMMC_IDLE_STATE = 0,
> + EMMC_READY_STATE,
> + EMMC_IDENT_STATE,
> + EMMC_STBY_STATE,
> + EMMC_TRAN_STATE,
> + EMMC_DATA_STATE,
> + EMMC_RCV_STATE,
> + EMMC_PRG_STATE,
> + EMMC_DIS_STATE,
> + EMMC_BTST_STATE,
> + EMMC_SLP_STATE
> +} EMMC_DEVICE_STATE;
> +
> UINT32 mEmmcRcaCount = 0;
>
> STATIC
> EFI_STATUS
> EFIAPI
> +EmmcGetDeviceState (
> + IN MMC_HOST_INSTANCE *MmcHostInstance,
> + OUT EMMC_DEVICE_STATE *State
> + )
> +{
> + EFI_MMC_HOST_PROTOCOL *Host;
> + EFI_STATUS Status;
> + UINT32 Data, RCA;
> +
> + if (State == NULL)
> + return EFI_INVALID_PARAMETER;
Always { and }.
> +
> + Host = MmcHostInstance->MmcHost;
Double space.
> + RCA = MmcHostInstance->CardInfo.RCA << RCA_SHIFT_OFFSET;
> + Status = Host->SendCommand (Host, MMC_CMD13, RCA);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to get card status, Status=%r.\n", Status));
> + return Status;
> + }
> + Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R1, &Data);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to get response of CMD13, Status=%r.\n", Status));
> + return Status;
> + }
> + if (Data & EMMC_SWITCH_ERROR) {
> + DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to switch expected mode, Status=%r.\n", Status));
> + return EFI_DEVICE_ERROR;
> + }
> + *State = DEVICE_STATE(Data);
> + return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +EmmcSetEXTCSD (
> + IN MMC_HOST_INSTANCE *MmcHostInstance,
> + UINT32 ExtCmdIndex,
> + UINT32 Value
> + )
> +{
> + EFI_MMC_HOST_PROTOCOL *Host;
> + EMMC_DEVICE_STATE State;
> + EFI_STATUS Status;
> + UINT32 Argument;
> +
> + Host = MmcHostInstance->MmcHost;
> + Argument = (3 << 24) | ((ExtCmdIndex & 0xff) << 16) | ((Value & 0xff) << 8) | 1;
Can these magic number operations be cleaned up with some #defines?
> + Status = Host->SendCommand (Host, MMC_CMD6, Argument);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "EmmcSetEXTCSD(): Failed to send CMD6, Status=%r.\n", Status));
> + return Status;
> + }
> + // Make sure device exiting prog mode
> + do {
> + Status = EmmcGetDeviceState (MmcHostInstance, &State);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "EmmcSetEXTCSD(): Failed to get device state, Status=%r.\n", Status));
> + return Status;
> + }
> + } while (State == EMMC_PRG_STATE);
> + return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> EmmcIdentificationMode (
> IN MMC_HOST_INSTANCE *MmcHostInstance,
> IN OCR_RESPONSE Response
> @@ -37,6 +135,7 @@ EmmcIdentificationMode (
> {
> EFI_MMC_HOST_PROTOCOL *Host;
> EFI_BLOCK_IO_MEDIA *Media;
> + EMMC_DEVICE_STATE State;
> EFI_STATUS Status;
> UINT32 RCA;
>
> @@ -84,35 +183,117 @@ EmmcIdentificationMode (
> DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Card selection error, Status=%r.\n", Status));
> }
>
> - // Fetch ECSD
> - Status = Host->SendCommand (Host, MMC_CMD8, RCA);
> - if (EFI_ERROR (Status)) {
> - DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD fetch error, Status=%r.\n", Status));
> - }
> -
> - Status = Host->ReadBlockData (Host, 0, 512, (UINT32 *)&(MmcHostInstance->CardInfo.ECSDData));
> - if (EFI_ERROR (Status)) {
> - DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD read error, Status=%r.\n", Status));
> - return Status;
> - }
> -
> + // MMC v4 specific
Does this mean this code was previously unsafe for pre-MMC v4?
If so, that would be good to point out in commit message.
Or is it the case that all eMMC devices are MMCv4+?
> + if (MmcHostInstance->CardInfo.CSDData.SPEC_VERS == 4) {
> + if (Host->SetIos) {
> + // Set 1-bit bus width
> + Status = Host->SetIos (Host, 0, 1, EMMCBACKWARD);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Set 1-bit bus width error, Status=%r.\n", Status));
> + return Status;
> + }
> +
> + // Set 1-bit bus width for EXTCSD
> + Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_BUS_WIDTH, EMMC_BUS_WIDTH_1BIT);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Set extcsd bus width error, Status=%r.\n", Status));
> + return Status;
> + }
> + }
> +
> + // Fetch ECSD
> + Status = Host->SendCommand (Host, MMC_CMD8, RCA);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD fetch error, Status=%r.\n", Status));
> + }
> + Status = Host->ReadBlockData (Host, 0, 512, (UINT32 *)&(MmcHostInstance->CardInfo.ECSDData));
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD read error, Status=%r.\n", Status));
> + return Status;
> + }
> +
> + // Make sure device exiting data mode
> + do {
> + Status = EmmcGetDeviceState (MmcHostInstance, &State);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Failed to get device state, Status=%r.\n", Status));
> + return Status;
> + }
> + } while (State == EMMC_DATA_STATE);
> +
> + // Compute last block using bits [215:212] of the ECSD
> + Media->LastBlock = MmcHostInstance->CardInfo.ECSDData.SECTOR_COUNT - 1; // eMMC isn't supposed to report this for
> + // Cards <2GB in size, but the model does.
> +
> + // Setup card type
> + MmcHostInstance->CardInfo.CardType = EMMC_CARD;
> + }
> // Set up media
> Media->BlockSize = EMMC_CARD_SIZE; // 512-byte support is mandatory for eMMC cards
> Media->MediaId = MmcHostInstance->CardInfo.CIDData.PSN;
> Media->ReadOnly = MmcHostInstance->CardInfo.CSDData.PERM_WRITE_PROTECT;
> Media->LogicalBlocksPerPhysicalBlock = 1;
> Media->IoAlign = 4;
> - // Compute last block using bits [215:212] of the ECSD
> - Media->LastBlock = MmcHostInstance->CardInfo.ECSDData.SECTOR_COUNT - 1; // eMMC isn't supposed to report this for
> - // Cards <2GB in size, but the model does.
> -
> - // Setup card type
> - MmcHostInstance->CardInfo.CardType = EMMC_CARD;
Does this need to be initialised to something else if not EMMC?
> return EFI_SUCCESS;
> }
>
> STATIC
> EFI_STATUS
> +InitializeEmmcDevice (
> + IN MMC_HOST_INSTANCE *MmcHostInstance
> + )
> +{
> + EFI_MMC_HOST_PROTOCOL *Host;
> + EFI_STATUS Status = EFI_SUCCESS;
> + ECSD *ECSDData;
> + BOOLEAN Found = FALSE;
> + UINT32 BusClockFreq, Idx;
> + UINT32 TimingMode[4] = {EMMCHS52DDR1V2, EMMCHS52DDR1V8, EMMCHS52, EMMCHS26};
> +
> + Host = MmcHostInstance->MmcHost;
> + if (MmcHostInstance->CardInfo.CSDData.SPEC_VERS < 4)
> + return EFI_SUCCESS;
> + ECSDData = &MmcHostInstance->CardInfo.ECSDData;
> + if (ECSDData->DEVICE_TYPE == EMMCBACKWARD)
> + return EFI_SUCCESS;
Always { and } (2X).
> +
> + if (Host->SetIos) {
How about
If (!Host->SetIos) {
return EFI_SUCCESS;
}
?
And then we can lose a level of indentation in the rest of the function.
> + Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_HS_TIMING, EMMC_TIMING_HS);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "InitializeEmmcDevice(): Failed to switch high speed mode, Status:%r.\n", Status));
> + return Status;
> + }
> +
> + for (Idx = 0; Idx < 4; Idx++) {
> + switch (TimingMode[Idx]) {
> + case EMMCHS52DDR1V2:
> + case EMMCHS52DDR1V8:
> + case EMMCHS52:
> + BusClockFreq = 52000000;
> + break;
> + case EMMCHS26:
> + BusClockFreq = 26000000;
> + break;
> + default:
> + return EFI_UNSUPPORTED;
> + }
> + Status = Host->SetIos (Host, BusClockFreq, 8, TimingMode[Idx]);
> + if (!EFI_ERROR (Status)) {
> + Found = TRUE;
> + break;
> + }
> + }
> + if (Found) {
> + Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_BUS_WIDTH, EMMC_BUS_WIDTH_DDR_8BIT);
> + if (EFI_ERROR (Status))
> + DEBUG ((DEBUG_ERROR, "InitializeEmmcDevice(): Failed to set EXTCSD bus width, Status:%r\n", Status));
{ and }
But also, just inserting this code in the "if (!EFI_ERROR (Status)) {"
statement and dropping the Found flag completely would be cleaner.
> + }
> + }
> + return Status;
> +}
> +
> +STATIC
> +EFI_STATUS
> InitializeSdMmcDevice (
> IN MMC_HOST_INSTANCE *MmcHostInstance
> )
> @@ -429,11 +610,15 @@ InitializeMmcDevice (
> return Status;
> }
>
> - if (MmcHostInstance->CardInfo.CardType != EMMC_CARD) {
> - Status = InitializeSdMmcDevice (MmcHostInstance);
> - if (EFI_ERROR (Status)) {
> - return Status;
> + if (MmcHostInstance->CardInfo.CardType == EMMC_CARD) {
Flipping the comparison logic here makes the diff look a lot more
invasive than it is. While I'm not opposed to the change, could you
break it out as a separat patch if you want to keep it in?
> + if (MmcHost->SetIos) {
This is being checked also in SetIos, so this added check can be
dropped.
> + Status = InitializeEmmcDevice (MmcHostInstance);
> }
> + } else {
> + Status = InitializeSdMmcDevice (MmcHostInstance);
> + }
> + if (EFI_ERROR (Status)) {
> + return Status;
> }
>
> // Set Block Length
> --
> 2.7.4
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v5 7/9] MmcDxe: set iospeed and bus width in SD stack
2016-11-13 6:47 ` [PATCH v5 7/9] MmcDxe: set iospeed and bus width in SD stack Haojian Zhuang
@ 2016-11-14 17:08 ` Leif Lindholm
0 siblings, 0 replies; 16+ messages in thread
From: Leif Lindholm @ 2016-11-14 17:08 UTC (permalink / raw)
To: Haojian Zhuang; +Cc: ryan.harkin, edk2-devel, ard.biesheuvel
On Sun, Nov 13, 2016 at 02:47:56PM +0800, Haojian Zhuang wrote:
> Add more SD commands to support 4-bit bus width & iospeed. It's not
> formal code. And it needs to be updated later.
Little bit concerned about this statement. Is it outdated information?
If so, can you update commit message.
If not, can you specify which bits are missing?
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> Tested-by: Ryan Harkin <ryan.harkin@linaro.org>
> ---
> EmbeddedPkg/Include/Protocol/MmcHost.h | 3 +
> EmbeddedPkg/Universal/MmcDxe/Mmc.h | 17 +++
> EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c | 138 ++++++++++++++++++++---
> 3 files changed, 142 insertions(+), 16 deletions(-)
>
> diff --git a/EmbeddedPkg/Include/Protocol/MmcHost.h b/EmbeddedPkg/Include/Protocol/MmcHost.h
> index 01c0bf4..5028045 100644
> --- a/EmbeddedPkg/Include/Protocol/MmcHost.h
> +++ b/EmbeddedPkg/Include/Protocol/MmcHost.h
> @@ -64,11 +64,14 @@ typedef UINT32 MMC_CMD;
> #define MMC_CMD24 (MMC_INDX(24) | MMC_CMD_WAIT_RESPONSE)
> #define MMC_CMD55 (MMC_INDX(55) | MMC_CMD_WAIT_RESPONSE)
> #define MMC_ACMD41 (MMC_INDX(41) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_NO_CRC_RESPONSE)
> +#define MMC_ACMD51 (MMC_INDX(51) | MMC_CMD_WAIT_RESPONSE)
>
> // Valid responses for CMD1 in eMMC
> #define EMMC_CMD1_CAPACITY_LESS_THAN_2GB 0x00FF8080 // Capacity <= 2GB, byte addressing used
> #define EMMC_CMD1_CAPACITY_GREATER_THAN_2GB 0x40FF8080 // Capacity > 2GB, 512-byte sector addressing used
>
> +#define MMC_STATUS_APP_CMD (1 << 5)
> +
> typedef enum _MMC_STATE {
> MmcInvalidState = 0,
> MmcHwInitializationState,
> diff --git a/EmbeddedPkg/Universal/MmcDxe/Mmc.h b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
> index 67f449c..f054bb2 100644
> --- a/EmbeddedPkg/Universal/MmcDxe/Mmc.h
> +++ b/EmbeddedPkg/Universal/MmcDxe/Mmc.h
> @@ -75,6 +75,23 @@ typedef struct {
> UINT32 PowerUp: 1; // This bit is set to LOW if the card has not finished the power up routine
> } OCR;
>
> +/* For little endian CPU */
All formally supported architectures are little-endian, so I guess
this is OK for now. Don't know if we have a good portable macro to
use for detection anyway.
> +typedef struct {
> + UINT8 SD_SPEC: 4; // SD Memory Card - Spec. Version [59:56]
> + UINT8 SCR_STRUCTURE: 4; // SCR Structure [63:60]
> + UINT8 SD_BUS_WIDTHS: 4; // DAT Bus widths supported [51:48]
> + UINT8 DATA_STAT_AFTER_ERASE: 1; // Data Status after erases [55]
> + UINT8 SD_SECURITY: 3; // CPRM Security Support [54:52]
> + UINT8 EX_SECURITY_1: 1; // Extended Security Support [43]
> + UINT8 SD_SPEC4: 1; // Spec. Version 4.00 or higher [42]
> + UINT8 RESERVED_1: 2; // Reserved [41:40]
> + UINT8 SD_SPEC3: 1; // Spec. Version 3.00 or higher [47]
> + UINT8 EX_SECURITY_2: 3; // Extended Security Support [46:44]
> + UINT8 CMD_SUPPORT: 4; // Command Support bits [35:32]
> + UINT8 RESERVED_2: 4; // Reserved [39:36]
> + UINT32 RESERVED_3; // Manufacturer Usage [31:0]
> +} SCR;
> +
> typedef struct {
> UINT32 NOT_USED; // 1 [0:0]
> UINT32 CRC; // CRC7 checksum [7:1]
> diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
> index 9a79767..c469dda 100644
> --- a/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
> +++ b/EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
> @@ -12,6 +12,9 @@
> *
> **/
>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/TimerLib.h>
> +
> #include "Mmc.h"
>
> typedef union {
> @@ -41,6 +44,11 @@ typedef union {
>
> #define EMMC_SWITCH_ERROR (1 << 7)
>
> +#define SD_BUS_WIDTH_1BIT (1 << 0)
> +#define SD_BUS_WIDTH_4BIT (1 << 2)
> +
> +#define SD_CCC_SWITCH (1 << 10)
> +
> #define DEVICE_STATE(x) (((x) >> 9) & 0xf)
> typedef enum _EMMC_DEVICE_STATE {
> EMMC_IDLE_STATE = 0,
> @@ -68,28 +76,30 @@ EmmcGetDeviceState (
> {
> EFI_MMC_HOST_PROTOCOL *Host;
> EFI_STATUS Status;
> - UINT32 Data, RCA;
> + UINT32 Rsp[4], RCA;
>
> if (State == NULL)
> return EFI_INVALID_PARAMETER;
>
> Host = MmcHostInstance->MmcHost;
> RCA = MmcHostInstance->CardInfo.RCA << RCA_SHIFT_OFFSET;
> - Status = Host->SendCommand (Host, MMC_CMD13, RCA);
> - if (EFI_ERROR (Status)) {
> - DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to get card status, Status=%r.\n", Status));
> - return Status;
> - }
> - Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R1, &Data);
> - if (EFI_ERROR (Status)) {
> - DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to get response of CMD13, Status=%r.\n", Status));
> - return Status;
> - }
> - if (Data & EMMC_SWITCH_ERROR) {
> - DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to switch expected mode, Status=%r.\n", Status));
> - return EFI_DEVICE_ERROR;
> - }
> - *State = DEVICE_STATE(Data);
> + do {
> + Status = Host->SendCommand (Host, MMC_CMD13, RCA);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to get card status, Status=%r.\n", Status));
> + return Status;
> + }
> + Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R1, Rsp);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to get response of CMD13, Status=%r.\n", Status));
> + return Status;
> + }
> + if (Rsp[0] & EMMC_SWITCH_ERROR) {
> + DEBUG ((EFI_D_ERROR, "EmmcGetDeviceState(): Failed to switch expected mode, Status=%r.\n", Status));
> + return EFI_DEVICE_ERROR;
> + }
> + } while (!(Rsp[0] & MMC_R0_READY_FOR_DATA));
> + *State = MMC_R0_CURRENTSTATE(Rsp);
These changes do not look directly related to the stated purpose of
the patch? Should it be a separate one?
> return EFI_SUCCESS;
> }
>
> @@ -300,9 +310,12 @@ InitializeSdMmcDevice (
> {
> UINT32 CmdArg;
> UINT32 Response[4];
> + UINT32 Buffer[128];
> UINTN BlockSize;
> UINTN CardSize;
> UINTN NumBlocks;
> + BOOLEAN CccSwitch;
> + SCR Scr;
> EFI_STATUS Status;
> EFI_MMC_HOST_PROTOCOL *MmcHost;
>
> @@ -323,6 +336,10 @@ InitializeSdMmcDevice (
> return Status;
> }
> PrintCSD (Response);
> + if (MMC_CSD_GET_CCC(Response) & SD_CCC_SWITCH)
> + CccSwitch = TRUE;
> + else
> + CccSwitch = FALSE;
>
> if (MmcHostInstance->CardInfo.CardType == SD_CARD_2_HIGH) {
> CardSize = HC_MMC_CSD_GET_DEVICESIZE (Response);
> @@ -353,6 +370,95 @@ InitializeSdMmcDevice (
> return Status;
> }
>
> + Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, CmdArg);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "%a(MMC_CMD55): Error and Status = %r\n", Status));
> + return Status;
> + }
> + Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "%a(MMC_CMD55): Error and Status = %r\n", Status));
> + return Status;
> + }
> + if ((Response[0] & MMC_STATUS_APP_CMD) == 0)
> + return EFI_SUCCESS;
> +
> + /* SCR */
> + Status = MmcHost->SendCommand (MmcHost, MMC_ACMD51, 0);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "%a(MMC_ACMD51): Error and Status = %r\n", __func__, Status));
> + return Status;
> + } else {
> + Status = MmcHost->ReadBlockData (MmcHost, 0, 8, Buffer);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "%a(MMC_ACMD51): ReadBlockData Error and Status = %r\n", __func__, Status));
> + return Status;
> + }
> + CopyMem (&Scr, Buffer, 8);
> + if (Scr.SD_SPEC == 2) {
> + if (Scr.SD_SPEC3 == 1) {
> + if (Scr.SD_SPEC4 == 1) {
> + DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 4.xx\n"));
> + } else {
> + DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 3.0x\n"));
> + }
> + } else {
> + if (Scr.SD_SPEC4 == 0) {
> + DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 2.0\n"));
> + } else {
> + DEBUG ((EFI_D_ERROR, "Found invalid SD Card\n"));
> + }
> + }
> + } else {
> + if ((Scr.SD_SPEC3 == 0) && (Scr.SD_SPEC4 == 0)) {
> + if (Scr.SD_SPEC == 1) {
> + DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 1.10\n"));
> + } else {
> + DEBUG ((EFI_D_INFO, "Found SD Card for Spec Version 1.0\n"));
> + }
> + } else {
> + DEBUG ((EFI_D_ERROR, "Found invalid SD Card\n"));
> + }
> + }
> + }
> + if (CccSwitch) {
> + /* SD Switch, Mode:1, Group:0, Value:1 */
> + CmdArg = 1 << 31 | 0x00FFFFFF;
> + CmdArg &= ~(0xF << (0 * 4));
> + CmdArg |= 1 << (0 * 4);
Can we have some defines to clean the above up?
> + Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, CmdArg);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "%a(MMC_CMD6): Error and Status = %r\n", Status));
> + return Status;
> + } else {
> + Status = MmcHost->ReadBlockData (MmcHost, 0, 64, Buffer);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "%a(MMC_CMD6): ReadBlockData Error and Status = %r\n", Status));
> + return Status;
> + }
> + }
> + }
> + if (Scr.SD_BUS_WIDTHS & SD_BUS_WIDTH_4BIT) {
> + CmdArg = MmcHostInstance->CardInfo.RCA << 16;
> + Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, CmdArg);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "%a(MMC_CMD55): Error and Status = %r\n", Status));
> + return Status;
> + }
> + /* Width: 4 */
> + Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, 2);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "%a(MMC_CMD6): Error and Status = %r\n", Status));
> + return Status;
> + }
> + }
> + if (MmcHost->SetIos) {
> + Status = MmcHost->SetIos (MmcHost, 24 * 1000 * 1000, 4, EMMCBACKWARD);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "%a(SetIos): Error and Status = %r\n", Status));
> + return Status;
> + }
> + }
> return EFI_SUCCESS;
> }
>
> --
> 2.7.4
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v5 8/9] MmcDxe: expand to support multiple blocks
2016-11-13 6:47 ` [PATCH v5 8/9] MmcDxe: expand to support multiple blocks Haojian Zhuang
@ 2016-11-14 17:15 ` Leif Lindholm
0 siblings, 0 replies; 16+ messages in thread
From: Leif Lindholm @ 2016-11-14 17:15 UTC (permalink / raw)
To: Haojian Zhuang; +Cc: ryan.harkin, edk2-devel, ard.biesheuvel
On Sun, Nov 13, 2016 at 02:47:57PM +0800, Haojian Zhuang wrote:
> Make use of DMA to transfer multiple blocks at one time. It could
> improve the performance on MMC/SD driver.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> Tested-by: Ryan Harkin <ryan.harkin@linaro.org>
> ---
> EmbeddedPkg/Include/Protocol/MmcHost.h | 6 +
> EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c | 177 ++++++++++++++++++++----------
> 2 files changed, 123 insertions(+), 60 deletions(-)
>
> diff --git a/EmbeddedPkg/Include/Protocol/MmcHost.h b/EmbeddedPkg/Include/Protocol/MmcHost.h
> index 5028045..cd5335a 100644
> --- a/EmbeddedPkg/Include/Protocol/MmcHost.h
> +++ b/EmbeddedPkg/Include/Protocol/MmcHost.h
> @@ -62,6 +62,7 @@ typedef UINT32 MMC_CMD;
> #define MMC_CMD20 (MMC_INDX(20) | MMC_CMD_WAIT_RESPONSE)
> #define MMC_CMD23 (MMC_INDX(23) | MMC_CMD_WAIT_RESPONSE)
> #define MMC_CMD24 (MMC_INDX(24) | MMC_CMD_WAIT_RESPONSE)
> +#define MMC_CMD25 (MMC_INDX(25) | MMC_CMD_WAIT_RESPONSE)
> #define MMC_CMD55 (MMC_INDX(55) | MMC_CMD_WAIT_RESPONSE)
> #define MMC_ACMD41 (MMC_INDX(41) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_NO_CRC_RESPONSE)
> #define MMC_ACMD51 (MMC_INDX(51) | MMC_CMD_WAIT_RESPONSE)
> @@ -152,6 +153,10 @@ typedef EFI_STATUS (EFIAPI *MMC_SETIOS) (
> IN UINT32 TimingMode
> );
>
> +typedef BOOLEAN (EFIAPI *MMC_ISMULTIBLOCK) (
> + IN EFI_MMC_HOST_PROTOCOL *This
> + );
> +
>
> struct _EFI_MMC_HOST_PROTOCOL {
>
> @@ -169,6 +174,7 @@ struct _EFI_MMC_HOST_PROTOCOL {
> MMC_WRITEBLOCKDATA WriteBlockData;
>
> MMC_SETIOS SetIos;
> + MMC_ISMULTIBLOCK IsMultiBlock;
>
> };
>
> diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c b/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c
> index 0e1ef57..1fcb3b5 100644
> --- a/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c
> +++ b/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c
> @@ -126,6 +126,95 @@ MmcStopTransmission (
> #define MMCI0_BLOCKLEN 512
> #define MMCI0_TIMEOUT 10000
>
> +STATIC EFI_STATUS
STATIC
EFI_STATUS
> +MmcTransferBlock (
> + IN EFI_BLOCK_IO_PROTOCOL *This,
> + IN UINTN Cmd,
> + IN UINTN Transfer,
> + IN UINT32 MediaId,
> + IN EFI_LBA Lba,
> + IN UINTN BufferSize,
> + OUT VOID *Buffer
> + )
> +{
> + EFI_STATUS Status;
> + UINTN CmdArg;
> + INTN Timeout;
> + UINT32 Response[4];
> + MMC_HOST_INSTANCE *MmcHostInstance;
> + EFI_MMC_HOST_PROTOCOL *MmcHost;
> +
> + MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS (This);
> + MmcHost = MmcHostInstance->MmcHost;
> +
> + //Set command argument based on the card access mode (Byte mode or Block mode)
> + if (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1) {
The code would be more readable if instead of BIT1 there was a
symbolic name of the flag we're testing for.
(OK, I see the code has been moved from elsewhere in this form, but it
would be good to make the code more clear.)
> + CmdArg = Lba;
> + } else {
> + CmdArg = Lba * This->Media->BlockSize;
> + }
> +
> + Status = MmcHost->SendCommand (MmcHost, Cmd, CmdArg);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "%a(MMC_CMD%d): Error %r\n", __func__, Cmd, Status));
> + return Status;
> + }
> +
> + if (Transfer == MMC_IOBLOCKS_READ) {
> + // Read Data
> + Status = MmcHost->ReadBlockData (MmcHost, Lba, BufferSize, Buffer);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_BLKIO, "%a(): Error Read Block Data and Status = %r\n", __func__, Status));
> + MmcStopTransmission (MmcHost);
> + return Status;
> + }
> + Status = MmcNotifyState (MmcHostInstance, MmcProgrammingState);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "%a() : Error MmcProgrammingState\n", __func__));
> + return Status;
> + }
> + } else {
> + // Write Data
> + Status = MmcHost->WriteBlockData (MmcHost, Lba, BufferSize, Buffer);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_BLKIO, "%a(): Error Write Block Data and Status = %r\n", __func__, Status));
> + MmcStopTransmission (MmcHost);
> + return Status;
> + }
> + }
> +
> + // Command 13 - Read status and wait for programming to complete (return to tran)
> + Timeout = MMCI0_TIMEOUT;
> + CmdArg = MmcHostInstance->CardInfo.RCA << 16;
> + Response[0] = 0;
> + while(!(Response[0] & MMC_R0_READY_FOR_DATA)
> + && (MMC_R0_CURRENTSTATE (Response) != MMC_R0_STATE_TRAN)
> + && Timeout--) {
> + Status = MmcHost->SendCommand (MmcHost, MMC_CMD13, CmdArg);
> + if (!EFI_ERROR (Status)) {
> + MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);
> + if (Response[0] & MMC_R0_READY_FOR_DATA) {
> + break; // Prevents delay once finished
> + }
> + }
> + gBS->Stall (1);
Can you provide a comment of why this stall was chosen?
(Ah, again, moved code. Ignore.)
> + }
> +
> + if (BufferSize > This->Media->BlockSize) {
> + Status = MmcHost->SendCommand (MmcHost, MMC_CMD12, 0);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_BLKIO, "%a(): Error and Status:%r\n", __func__, Status));
> + }
> + }
> +
> + Status = MmcNotifyState (MmcHostInstance, MmcTransferState);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "MmcIoBlocks() : Error MmcTransferState\n"));
> + return Status;
> + }
> + return Status;
> +}
> +
> EFI_STATUS
> MmcIoBlocks (
> IN EFI_BLOCK_IO_PROTOCOL *This,
> @@ -145,6 +234,7 @@ MmcIoBlocks (
> EFI_MMC_HOST_PROTOCOL *MmcHost;
> UINTN BytesRemainingToBeTransfered;
> UINTN BlockCount;
> + UINTN ConsumeSize;
>
> BlockCount = 1;
> MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS (This);
> @@ -165,6 +255,10 @@ MmcIoBlocks (
> return EFI_NO_MEDIA;
> }
>
> + if (MmcHost->IsMultiBlock && MmcHost->IsMultiBlock(MmcHost)) {
> + BlockCount = (BufferSize + This->Media->BlockSize - 1) / This->Media->BlockSize;
> + }
> +
> // All blocks must be within the device
> if ((Lba + (BufferSize / This->Media->BlockSize)) > (This->Media->LastBlock + 1)) {
> return EFI_INVALID_PARAMETER;
> @@ -196,7 +290,7 @@ MmcIoBlocks (
> CmdArg = MmcHostInstance->CardInfo.RCA << 16;
> Response[0] = 0;
> Timeout = 20;
> - while( (!(Response[0] & MMC_R0_READY_FOR_DATA))
> + while(!(Response[0] & MMC_R0_READY_FOR_DATA)
This is cleanup, but it is unrelated to functional changes, so please
leave out.
> && (MMC_R0_CURRENTSTATE (Response) != MMC_R0_STATE_TRAN)
> && Timeout--) {
> Status = MmcHost->SendCommand (MmcHost, MMC_CMD13, CmdArg);
> @@ -210,75 +304,38 @@ MmcIoBlocks (
> return EFI_NOT_READY;
> }
>
> - //Set command argument based on the card access mode (Byte mode or Block mode)
> - if (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1) {
> - CmdArg = Lba;
> - } else {
> - CmdArg = Lba * This->Media->BlockSize;
> - }
> -
> if (Transfer == MMC_IOBLOCKS_READ) {
> - // Read a single block
> - Cmd = MMC_CMD17;
> - } else {
> - // Write a single block
> - Cmd = MMC_CMD24;
> - }
> - Status = MmcHost->SendCommand (MmcHost, Cmd, CmdArg);
> - if (EFI_ERROR (Status)) {
> - DEBUG ((EFI_D_ERROR, "MmcIoBlocks(MMC_CMD%d): Error %r\n", Cmd, Status));
> - return Status;
> - }
> -
> - if (Transfer == MMC_IOBLOCKS_READ) {
> - // Read one block of Data
> - Status = MmcHost->ReadBlockData (MmcHost, Lba, This->Media->BlockSize, Buffer);
> - if (EFI_ERROR (Status)) {
> - DEBUG ((EFI_D_BLKIO, "MmcIoBlocks(): Error Read Block Data and Status = %r\n", Status));
> - MmcStopTransmission (MmcHost);
> - return Status;
> - }
> - Status = MmcNotifyState (MmcHostInstance, MmcProgrammingState);
> - if (EFI_ERROR (Status)) {
> - DEBUG ((EFI_D_ERROR, "MmcIoBlocks() : Error MmcProgrammingState\n"));
> - return Status;
> + if (BlockCount == 1) {
> + // Read a single block
> + Cmd = MMC_CMD17;
> + } else {
> + // Read multiple blocks
> + Cmd = MMC_CMD18;
> }
> } else {
> - // Write one block of Data
> - Status = MmcHost->WriteBlockData (MmcHost, Lba, This->Media->BlockSize, Buffer);
> - if (EFI_ERROR (Status)) {
> - DEBUG ((EFI_D_BLKIO, "MmcIoBlocks(): Error Write Block Data and Status = %r\n", Status));
> - MmcStopTransmission (MmcHost);
> - return Status;
> + if (BlockCount == 1) {
> + // Write a single block
> + Cmd = MMC_CMD24;
> + } else {
> + // Write multiple blocks
> + Cmd = MMC_CMD25;
> }
> }
>
> - // Command 13 - Read status and wait for programming to complete (return to tran)
> - Timeout = MMCI0_TIMEOUT;
> - CmdArg = MmcHostInstance->CardInfo.RCA << 16;
> - Response[0] = 0;
> - while( (!(Response[0] & MMC_R0_READY_FOR_DATA))
> - && (MMC_R0_CURRENTSTATE (Response) != MMC_R0_STATE_TRAN)
> - && Timeout--) {
> - Status = MmcHost->SendCommand (MmcHost, MMC_CMD13, CmdArg);
> - if (!EFI_ERROR (Status)) {
> - MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);
> - if ((Response[0] & MMC_R0_READY_FOR_DATA)) {
> - break; // Prevents delay once finished
> - }
> - }
> - gBS->Stall (1);
> + ConsumeSize = BlockCount * This->Media->BlockSize;
> + if (BytesRemainingToBeTransfered < ConsumeSize) {
> + ConsumeSize = BytesRemainingToBeTransfered;
> }
> -
> - Status = MmcNotifyState (MmcHostInstance, MmcTransferState);
> + Status = MmcTransferBlock (This, Cmd, Transfer, MediaId, Lba, ConsumeSize, Buffer);
> if (EFI_ERROR (Status)) {
> - DEBUG ((EFI_D_ERROR, "MmcIoBlocks() : Error MmcTransferState\n"));
> - return Status;
> + DEBUG ((EFI_D_ERROR, "%a(): Failed to transfer block and Status:%r\n", __func__, Status));
> }
>
> - BytesRemainingToBeTransfered -= This->Media->BlockSize;
> - Lba += BlockCount;
> - Buffer = (UINT8 *)Buffer + This->Media->BlockSize;
> + BytesRemainingToBeTransfered -= ConsumeSize;
> + if (BytesRemainingToBeTransfered > 0) {
> + Lba += BlockCount;
> + Buffer = (UINT8 *)Buffer + ConsumeSize;
> + }
> }
>
> return EFI_SUCCESS;
> --
> 2.7.4
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v5 9/9] PL180: update for indentifying SD
2016-11-13 6:47 ` [PATCH v5 9/9] PL180: update for indentifying SD Haojian Zhuang
@ 2016-11-14 17:27 ` Leif Lindholm
0 siblings, 0 replies; 16+ messages in thread
From: Leif Lindholm @ 2016-11-14 17:27 UTC (permalink / raw)
To: Haojian Zhuang; +Cc: ryan.harkin, edk2-devel, ard.biesheuvel
On Sun, Nov 13, 2016 at 02:47:58PM +0800, Haojian Zhuang wrote:
> When CMD6 & ACMD51 are added into indentifying SD process, PL180
> should also support CMD6 & ACMD51. Otherwise, it'll hang when
> system tries to read expected data.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> Tested-by: Ryan Harkin <ryan.harkin@linaro.org>
The change as such is fine. (More than fine.)
However, should this not be added before the current 6/9, in order to
not leave a gap of commits that fail to boot?
Could I even push it independently of the series?
Regards,
Leif
> ---
> ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c | 29 ++++++++++++++++++++-------
> 1 file changed, 22 insertions(+), 7 deletions(-)
>
> diff --git a/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c b/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
> index 5526aac..b2ba4c0 100644
> --- a/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
> +++ b/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
> @@ -63,11 +63,6 @@ MciIsReadOnly (
> return (MmioRead32 (FixedPcdGet32 (PcdPL180SysMciRegAddress)) & SYS_MCI_WPROT);
> }
>
> -#if 0
> -//Note: This function has been commented out because it is not used yet.
> -// This function could be used to remove the hardcoded BlockLen used
> -// in MciPrepareDataPath
> -
> // Convert block size to 2^n
> STATIC
> UINT32
> @@ -87,7 +82,6 @@ GetPow2BlockLen (
>
> return Pow2BlockLen;
> }
> -#endif
>
> VOID
> MciPrepareDataPath (
> @@ -126,6 +120,23 @@ MciSendCommand (
> MciPrepareDataPath (MCI_DATACTL_CARD_TO_CONT);
> } else if ((MmcCmd == MMC_CMD24) || (MmcCmd == MMC_CMD20)) {
> MciPrepareDataPath (MCI_DATACTL_CONT_TO_CARD);
> + } else if (MmcCmd == MMC_CMD6) {
> + MmioWrite32 (MCI_DATA_TIMER_REG, 0xFFFFFFF);
> + MmioWrite32 (MCI_DATA_LENGTH_REG, 64);
> +#ifndef USE_STREAM
> + MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_CARD_TO_CONT | GetPow2BlockLen (64));
> +#else
> + MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_CARD_TO_CONT | MCI_DATACTL_STREAM_TRANS);
> +#endif
> + } else if (MmcCmd == MMC_ACMD51) {
> + MmioWrite32 (MCI_DATA_TIMER_REG, 0xFFFFFFF);
> + /* SCR register is 8 bytes long. */
> + MmioWrite32 (MCI_DATA_LENGTH_REG, 8);
> +#ifndef USE_STREAM
> + MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_CARD_TO_CONT | GetPow2BlockLen (8));
> +#else
> + MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_CARD_TO_CONT | MCI_DATACTL_STREAM_TRANS);
> +#endif
> }
>
> // Create Command for PL180
> @@ -223,7 +234,11 @@ MciReadBlockData (
>
> // Read data from the RX FIFO
> Loop = 0;
> - Finish = MMCI0_BLOCKLEN / 4;
> + if (Length < MMCI0_BLOCKLEN) {
> + Finish = Length / 4;
> + } else {
> + Finish = MMCI0_BLOCKLEN / 4;
> + }
>
> // Raise the TPL at the highest level to disable Interrupts.
> Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
> --
> 2.7.4
>
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2016-11-14 17:27 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-11-13 6:47 [PATCH v5 0/9] enhance MMC Haojian Zhuang
2016-11-13 6:47 ` [PATCH v5 1/9] MmcDxe: wait OCR busy bit free Haojian Zhuang
2016-11-13 6:47 ` [PATCH v5 2/9] MmcDxe: move ECSD into CardInfo structure Haojian Zhuang
2016-11-13 6:47 ` [PATCH v5 3/9] MmcDxe: declare ECSD structure Haojian Zhuang
2016-11-13 6:47 ` [PATCH v5 4/9] MmcDxe: add SPEC_VERS field in CSD structure Haojian Zhuang
2016-11-13 6:47 ` [PATCH v5 5/9] MmcDxe: add interface to change io width and speed Haojian Zhuang
2016-11-14 16:12 ` Leif Lindholm
2016-11-13 6:47 ` [PATCH v5 6/9] MmcDxe: set io bus width before reading EXTCSD Haojian Zhuang
2016-11-14 16:36 ` Leif Lindholm
2016-11-13 6:47 ` [PATCH v5 7/9] MmcDxe: set iospeed and bus width in SD stack Haojian Zhuang
2016-11-14 17:08 ` Leif Lindholm
2016-11-13 6:47 ` [PATCH v5 8/9] MmcDxe: expand to support multiple blocks Haojian Zhuang
2016-11-14 17:15 ` Leif Lindholm
2016-11-13 6:47 ` [PATCH v5 9/9] PL180: update for indentifying SD Haojian Zhuang
2016-11-14 17:27 ` Leif Lindholm
2016-11-14 15:53 ` [PATCH v5 0/9] enhance MMC Leif Lindholm
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox