sdhci: prepare for MMC EXT_SEND_CSD command
This is needed to handle MMC devices larger than 2GB. The protocol used is different from how it's done in SDHC/SDXC. Change-Id: I12edb1a4196c1e8f375886e9e5a5c1cef111e33c Reviewed-on: https://review.haiku-os.org/c/haiku/+/10929 Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
committed by
Adrien Destugues
parent
9e21efa6d8
commit
05b7380f79
@@ -31,20 +31,27 @@ typedef enum card_type {
|
|||||||
// Commands for SD/eMMC cards defined in:
|
// Commands for SD/eMMC cards defined in:
|
||||||
// SD: Physical Layer Simplified Specification Version 8.00
|
// SD: Physical Layer Simplified Specification Version 8.00
|
||||||
// eMMC: JEDEC Standard No. 84-B51. Sec 6.10.4
|
// eMMC: JEDEC Standard No. 84-B51. Sec 6.10.4
|
||||||
|
//
|
||||||
// They are in the common .h file for the mmc stack because the SDHCI driver
|
// They are in the common .h file for the mmc stack because the SDHCI driver
|
||||||
// currently needs to map them to the corresponding expected response types.
|
// currently needs to map them to the corresponding expected response types.
|
||||||
// card type prefix to distinguish non common commands.
|
//
|
||||||
|
// TODO maybe it would be simpler to have the upper layers (the bus manager and mmc_disk) specify
|
||||||
|
// the expected response type when sending a command. This would avoid hardcoding command types
|
||||||
|
// and the corresponding response types in the command sending code.
|
||||||
|
//
|
||||||
|
// When the commands are specific to SD or MMC types, the constant is named with the corresponding
|
||||||
|
// prefix.
|
||||||
enum SD_COMMANDS {
|
enum SD_COMMANDS {
|
||||||
// Basic commands, class 0
|
// Basic commands, class 0
|
||||||
GO_IDLE_STATE = 0,
|
GO_IDLE_STATE = 0,
|
||||||
MMC_SEND_OP_COND = 1,
|
MMC_SEND_OP_COND = 1,
|
||||||
// MMC only,reserved in SD.
|
// MMC only,reserved in SD.
|
||||||
ALL_SEND_CID = 2,
|
ALL_SEND_CID = 2,
|
||||||
SD_SEND_RELATIVE_ADDR = 3,
|
SD_SEND_RELATIVE_ADDR = 3,
|
||||||
MMC_SET_RELATIVE_ADDR = 3,
|
MMC_SET_RELATIVE_ADDR = 3,
|
||||||
SELECT_DESELECT_CARD = 7,
|
SELECT_DESELECT_CARD = 7,
|
||||||
// resp can be R1 per mmc spec,keep R1b for now.
|
|
||||||
SD_SEND_IF_COND = 8,
|
SD_SEND_IF_COND = 8,
|
||||||
|
MMC_SEND_EXT_CSD = 8,
|
||||||
SEND_CSD = 9,
|
SEND_CSD = 9,
|
||||||
SD_STOP_TRANSMISSION = 12,
|
SD_STOP_TRANSMISSION = 12,
|
||||||
|
|
||||||
|
|||||||
@@ -220,73 +220,71 @@ SdhciBus::ExecuteCommand(uint8_t command, uint32_t argument, uint32_t* response)
|
|||||||
|
|
||||||
uint32_t replyType;
|
uint32_t replyType;
|
||||||
uint16 transferMode = 0;
|
uint16 transferMode = 0;
|
||||||
bool cmdResolved = false;
|
|
||||||
|
|
||||||
// Resolve replyType for card type specific commands.
|
switch (command) {
|
||||||
if (fCardType == CARD_TYPE_MMC) {
|
// Basic reply types
|
||||||
if (command == MMC_SET_RELATIVE_ADDR) {
|
case GO_IDLE_STATE:
|
||||||
|
replyType = Command::kNoReplyType;
|
||||||
|
break;
|
||||||
|
case SD_APP_CMD:
|
||||||
|
case SD_ERASE_WR_BLK_START:
|
||||||
|
case SD_ERASE_WR_BLK_END:
|
||||||
|
case SD_SET_BUS_WIDTH: // SD Application command
|
||||||
replyType = Command::kR1Type;
|
replyType = Command::kR1Type;
|
||||||
cmdResolved = true;
|
break;
|
||||||
}
|
case SELECT_DESELECT_CARD:
|
||||||
} else if (command == SD_SEND_RELATIVE_ADDR) {
|
case SD_ERASE:
|
||||||
replyType = Command::kR6Type;
|
replyType = Command::kR1bType;
|
||||||
cmdResolved = true;
|
break;
|
||||||
}
|
case ALL_SEND_CID:
|
||||||
if (cmdResolved == false) {
|
case SEND_CSD:
|
||||||
switch (command) {
|
replyType = Command::kR2Type;
|
||||||
case GO_IDLE_STATE:
|
break;
|
||||||
replyType = Command::kNoReplyType;
|
case MMC_SEND_OP_COND:
|
||||||
break;
|
case SD_SEND_OP_COND: // SD Application command
|
||||||
case ALL_SEND_CID:
|
replyType = Command::kR3Type;
|
||||||
case SEND_CSD:
|
break;
|
||||||
replyType = Command::kR2Type;
|
|
||||||
break;
|
// Commands defined with different reply types in SD and MMC specifications
|
||||||
case SELECT_DESELECT_CARD:
|
case SD_SEND_RELATIVE_ADDR: // also MMC_SET_RELATIVE_ADDR
|
||||||
case SD_ERASE:
|
if (fCardType == CARD_TYPE_MMC)
|
||||||
replyType = Command::kR1bType;
|
|
||||||
break;
|
|
||||||
case SD_SEND_IF_COND:
|
|
||||||
replyType = Command::kR7Type;
|
|
||||||
break;
|
|
||||||
case SD_READ_SINGLE_BLOCK:
|
|
||||||
transferMode = TransferMode::kRead | TransferMode::kDmaEnable;
|
|
||||||
replyType = Command::kR1Type | Command::kDataPresent;
|
|
||||||
break;
|
|
||||||
case SD_READ_MULTIPLE_BLOCKS:
|
|
||||||
transferMode = TransferMode::kRead | TransferMode::kMulti
|
|
||||||
| TransferMode::kAutoCmd12Enable | TransferMode::kBlockCountEnable
|
|
||||||
| TransferMode::kDmaEnable;
|
|
||||||
replyType = Command::kR1Type | Command::kDataPresent;
|
|
||||||
break;
|
|
||||||
case SD_WRITE_SINGLE_BLOCK:
|
|
||||||
transferMode = TransferMode::kWrite | TransferMode::kDmaEnable;
|
|
||||||
replyType = Command::kR1Type | Command::kDataPresent;
|
|
||||||
break;
|
|
||||||
case SD_WRITE_MULTIPLE_BLOCKS:
|
|
||||||
transferMode = TransferMode::kWrite | TransferMode::kMulti
|
|
||||||
| TransferMode::kAutoCmd12Enable | TransferMode::kBlockCountEnable
|
|
||||||
| TransferMode::kDmaEnable;
|
|
||||||
replyType = Command::kR1Type | Command::kDataPresent;
|
|
||||||
break;
|
|
||||||
case SD_APP_CMD:
|
|
||||||
case SD_ERASE_WR_BLK_START:
|
|
||||||
case SD_ERASE_WR_BLK_END:
|
|
||||||
case SD_SET_BUS_WIDTH: // SD Application command
|
|
||||||
replyType = Command::kR1Type;
|
replyType = Command::kR1Type;
|
||||||
break;
|
else
|
||||||
case SD_SEND_OP_COND: // SD Application command
|
replyType = Command::kR6Type;
|
||||||
replyType = Command::kR3Type;
|
break;
|
||||||
break;
|
case SD_SEND_IF_COND: // also MMC_SEND_EXT_CSD
|
||||||
// MMC / eMMC commands
|
if (fCardType == CARD_TYPE_MMC)
|
||||||
case MMC_SEND_OP_COND:
|
replyType = Command::kR1Type;
|
||||||
// MMC/eMMC SEND_OP_COND command, CMD1.
|
else
|
||||||
replyType = Command::kR3Type;
|
replyType = Command::kR7Type;
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
ERROR("Unknown command %x\n", command);
|
// Commands with data transfer replies, also set transferMode
|
||||||
return B_BAD_DATA;
|
case SD_READ_SINGLE_BLOCK:
|
||||||
}
|
transferMode = TransferMode::kRead | TransferMode::kDmaEnable;
|
||||||
|
replyType = Command::kR1Type | Command::kDataPresent;
|
||||||
|
break;
|
||||||
|
case SD_READ_MULTIPLE_BLOCKS:
|
||||||
|
transferMode = TransferMode::kRead | TransferMode::kMulti
|
||||||
|
| TransferMode::kAutoCmd12Enable | TransferMode::kBlockCountEnable
|
||||||
|
| TransferMode::kDmaEnable;
|
||||||
|
replyType = Command::kR1Type | Command::kDataPresent;
|
||||||
|
break;
|
||||||
|
case SD_WRITE_SINGLE_BLOCK:
|
||||||
|
transferMode = TransferMode::kWrite | TransferMode::kDmaEnable;
|
||||||
|
replyType = Command::kR1Type | Command::kDataPresent;
|
||||||
|
break;
|
||||||
|
case SD_WRITE_MULTIPLE_BLOCKS:
|
||||||
|
transferMode = TransferMode::kWrite | TransferMode::kMulti
|
||||||
|
| TransferMode::kAutoCmd12Enable | TransferMode::kBlockCountEnable
|
||||||
|
| TransferMode::kDmaEnable;
|
||||||
|
replyType = Command::kR1Type | Command::kDataPresent;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ERROR("Unknown command %x\n", command);
|
||||||
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if DATA line is available (if needed)
|
// Check if DATA line is available (if needed)
|
||||||
if ((replyType & Command::k32BitResponseCheckBusy) != 0
|
if ((replyType & Command::k32BitResponseCheckBusy) != 0
|
||||||
&& command != SD_STOP_TRANSMISSION && command != SD_IO_ABORT) {
|
&& command != SD_STOP_TRANSMISSION && command != SD_IO_ABORT) {
|
||||||
|
|||||||
Reference in New Issue
Block a user