mmc: adjust switching to 4-bit mode for MMC devices
CMD6 is a normal command on MMC, but an application command on SD. And the parameters and response type are different. Change-Id: I0583b8a98cf18dc4d77d28066673d0d07229e161 Reviewed-on: https://review.haiku-os.org/c/haiku/+/10934 Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
committed by
Adrien Destugues
parent
1e9473f97e
commit
5efaab5061
@@ -46,10 +46,10 @@ enum SD_COMMANDS {
|
||||
// Basic commands, class 0
|
||||
GO_IDLE_STATE = 0,
|
||||
MMC_SEND_OP_COND = 1,
|
||||
// MMC only,reserved in SD.
|
||||
ALL_SEND_CID = 2,
|
||||
SD_SEND_RELATIVE_ADDR = 3,
|
||||
MMC_SET_RELATIVE_ADDR = 3,
|
||||
MMC_SWITCH = 6, // Same command number as SD_SET_BUS_WIDTH, but this one is not an ACMD
|
||||
SELECT_DESELECT_CARD = 7,
|
||||
SD_SEND_IF_COND = 8,
|
||||
MMC_SEND_EXT_CSD = 8,
|
||||
@@ -76,6 +76,7 @@ enum SD_COMMANDS {
|
||||
};
|
||||
|
||||
|
||||
// Application commands are sent with a prefix CMD55 (SD_APP_CMD)
|
||||
enum SDHCI_APPLICATION_COMMANDS {
|
||||
SD_SET_BUS_WIDTH = 6,
|
||||
SD_SEND_OP_COND = 41,
|
||||
|
||||
@@ -229,7 +229,6 @@ SdhciBus::ExecuteCommand(uint8_t command, uint32_t argument, uint32_t* response)
|
||||
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;
|
||||
break;
|
||||
case SELECT_DESELECT_CARD:
|
||||
@@ -246,6 +245,12 @@ SdhciBus::ExecuteCommand(uint8_t command, uint32_t argument, uint32_t* response)
|
||||
break;
|
||||
|
||||
// Commands defined with different reply types in SD and MMC specifications
|
||||
case SD_SET_BUS_WIDTH: // SD application command. Also MMC_SWITCH, which is not.
|
||||
if (fCardType == CARD_TYPE_MMC)
|
||||
replyType = Command::kR1bType;
|
||||
else
|
||||
replyType = Command::kR1Type;
|
||||
break;
|
||||
case SD_SEND_RELATIVE_ADDR: // also MMC_SET_RELATIVE_ADDR
|
||||
if (fCardType == CARD_TYPE_MMC)
|
||||
replyType = Command::kR1Type;
|
||||
|
||||
@@ -181,15 +181,46 @@ mmc_block_get_geometry(mmc_disk_driver_info* info, device_geometry* geometry)
|
||||
// This function will be called before all data transfers, so we use this
|
||||
// opportunity to switch the card to 4-bit data transfers (instead of the
|
||||
// default 1 bit mode)
|
||||
uint32_t cardStatus;
|
||||
const uint32 k4BitMode = 2;
|
||||
info->mmc->execute_command(info->parent, info->parentCookie, info->rca,
|
||||
SD_APP_CMD, info->rca << 16, &cardStatus);
|
||||
info->mmc->execute_command(info->parent, info->parentCookie, info->rca,
|
||||
SD_SET_BUS_WIDTH, k4BitMode, &cardStatus);
|
||||
uint32_t cardStatus = 0;
|
||||
status_t status = B_OK;
|
||||
|
||||
// From now on we use 4 bit mode
|
||||
info->mmc->set_bus_width(info->parent, info->parentCookie, 4);
|
||||
// TODO have the card type at hand instead of using the csd version here
|
||||
if (csd.structure_version() < 3) {
|
||||
const uint32 k4BitMode = 2;
|
||||
info->mmc->execute_command(info->parent, info->parentCookie, info->rca,
|
||||
SD_APP_CMD, info->rca << 16, &cardStatus);
|
||||
status = info->mmc->execute_command(info->parent, info->parentCookie, info->rca,
|
||||
SD_SET_BUS_WIDTH, k4BitMode, &cardStatus);
|
||||
} else {
|
||||
// TODO according to the eMMC spec, we should first run a test with CMD19 and CMD14 to
|
||||
// determine if the 4-bit (and possibly the 8-bit) bus is wired, and also check if we need
|
||||
// to switch to a different POWER_CLASS. See Jedec 84-B50 appendix A.6.3
|
||||
//
|
||||
// Command parameters for CMD6 (SWITCH):
|
||||
// bits 31-26: set to 0
|
||||
// bits 25-24: access (3 = write byte)
|
||||
// bits 23-16: index (B7 = 183 in decimal is the offset of BUS_WIDTH in the EXT_CSD register)
|
||||
// bits 15-8: value (1 = 4 bit mode)
|
||||
// bits 7-3: set to 0
|
||||
// bits 2-0: command set (kee using command set 0)
|
||||
//
|
||||
// See chapter 7.4.61 of the JEDEC spec as well as table 41 in section 6.10.4.
|
||||
//
|
||||
// The application note A.6.3 just gives the "magic" value to use without details as below:
|
||||
const uint32 k4BitMode = 0x3B70100;
|
||||
status = info->mmc->execute_command(info->parent, info->parentCookie, info->rca,
|
||||
MMC_SWITCH, k4BitMode, &cardStatus);
|
||||
}
|
||||
|
||||
TRACE("Card status after switching to 4 bit mode: %08x\n", cardStatus);
|
||||
|
||||
if (status == B_OK) {
|
||||
// From now on we use 4 bit mode
|
||||
TRACE("Switch to 4 bit mode for data transfers\n");
|
||||
info->mmc->set_bus_width(info->parent, info->parentCookie, 4);
|
||||
} else {
|
||||
TRACE("Switching to 4 bit mode failed: %s\n", strerror(status));
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user