Add eMMC driver support

- Fix DMA addressing issues within litex_sendsetup/litex_recvsetup
- Extend with handling specific to eMMC commands during init & use.
- Cleanup of 4-bit BUS handling for SD and eMMC
- For eMMC, Send CMD0 during init as per JEDEC v4.41 for pre-idle
This commit is contained in:
Radek Pesina 2023-03-29 11:04:50 +11:00 committed by David Sidrane
parent eb0e05be0d
commit 50a8ec62c4
5 changed files with 316 additions and 31 deletions

View file

@ -860,10 +860,12 @@ static int litex_recvsetup(struct sdio_dev_s *dev, uint8_t *buffer,
/* flush CPU d-cache */
#ifndef CONFIG_LITEX_COHERENT_DMA
up_invalidate_dcache_all();
#endif
putreg32(0, LITEX_SDBLOCK2MEM_DMA_ENABLE);
putreg32((uintptr_t)buffer >> 32, LITEX_SDBLOCK2MEM_DMA_BASE);
putreg32((uintptr_t)(&buffer[4]), LITEX_SDBLOCK2MEM_DMA_BASE);
putreg32((uintptr_t)buffer, LITEX_SDBLOCK2MEM_DMA_BASE + 0x04);
putreg32(nbytes, LITEX_SDBLOCK2MEM_DMA_LENGTH);
putreg32(1, LITEX_SDBLOCK2MEM_DMA_ENABLE);
@ -903,10 +905,12 @@ static int litex_sendsetup(struct sdio_dev_s *dev,
/* flush CPU d-cache */
#ifndef CONFIG_LITEX_COHERENT_DMA
up_invalidate_dcache_all();
#endif
putreg32(0, LITEX_SDMEM2BLOCK_DMA_ENABLE);
putreg32((uintptr_t)buffer >> 32, LITEX_SDMEM2BLOCK_DMA_BASE);
putreg32((uintptr_t)(&buffer[4]), LITEX_SDMEM2BLOCK_DMA_BASE);
putreg32((uintptr_t)buffer, LITEX_SDMEM2BLOCK_DMA_BASE + 0x04);
putreg32(nbytes, LITEX_SDMEM2BLOCK_DMA_LENGTH);
putreg32(1, LITEX_SDMEM2BLOCK_DMA_ENABLE);

View file

@ -5,6 +5,44 @@
if ARCH_BOARD_ARTY_A7
config LITEX_SDIO
bool "SDIO"
default n
select SCHED_HPWORK
select MMCSD
select MMCSD_SDIO
select SDIO_BLOCKSETUP
select ARCH_HAVE_SDIO
select SDIO_DMA
config LITEX_SDIO1
bool "Enable SDIO1"
default y if LITEX_SDIO
select LITEX_SDIO_DMA
depends on LITEX_SDIO
config LITEX_IDMODE_FREQ
int "ID mode frequency"
default 400000
depends on LITEX_SDIO
---help---
Initial, ID mode SD frequency
config LITEX_MMCXFR_FREQ
int "MMC transfer frequency"
default 25000000
depends on LITEX_SDIO
---help---
Frequency to use for transferring data to/from an MMC card
config LITEX_SD4BIT_FREQ
int "SD 4-bit transfer frequency"
default 50000000
depends on LITEX_SDIO
---help---
Frequency to use for transferring data to/from an SD card using all four data lines.
config LITEX_SDIO_MOUNT
bool "Mount SDIO at startup"
default n

View file

@ -0,0 +1,75 @@
#
# This file is autogenerated: PLEASE DO NOT EDIT IT.
#
# You can use "make menuconfig" to make any modifications to the installed .config file.
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
# modifications.
#
# CONFIG_DISABLE_PTHREAD is not set
# CONFIG_FS_PROCFS_EXCLUDE_BLOCKS is not set
# CONFIG_FS_PROCFS_EXCLUDE_ENVIRON is not set
# CONFIG_FS_PROCFS_EXCLUDE_MEMDUMP is not set
# CONFIG_FS_PROCFS_EXCLUDE_MEMINFO is not set
# CONFIG_FS_PROCFS_EXCLUDE_MOUNT is not set
# CONFIG_FS_PROCFS_EXCLUDE_MOUNTS is not set
# CONFIG_FS_PROCFS_EXCLUDE_PROCESS is not set
# CONFIG_FS_PROCFS_EXCLUDE_UPTIME is not set
# CONFIG_FS_PROCFS_EXCLUDE_USAGE is not set
# CONFIG_FS_PROCFS_EXCLUDE_VERSION is not set
# CONFIG_NSH_DISABLEBG is not set
# CONFIG_NSH_DISABLE_LOSMART is not set
# CONFIG_NSH_DISABLE_UNAME is not set
# CONFIG_STANDARD_SERIAL is not set
CONFIG_ARCH="risc-v"
CONFIG_ARCH_BOARD="arty_a7"
CONFIG_ARCH_BOARD_ARTY_A7=y
CONFIG_ARCH_CHIP="litex"
CONFIG_ARCH_CHIP_LITEX=y
CONFIG_ARCH_INTERRUPTSTACK=8192
CONFIG_ARCH_RISCV=y
CONFIG_ARCH_STACKDUMP=y
CONFIG_BINFMT_DISABLE=y
CONFIG_BOARD_LOOPSPERMSEC=10000
CONFIG_BUILTIN=y
CONFIG_DEBUG_FULLOPT=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_DEFAULT_SMALL=y
CONFIG_DEV_ZERO=y
CONFIG_EXAMPLES_HELLO=y
CONFIG_EXAMPLES_HELLO_STACKSIZE=8192
CONFIG_FAT_DMAMEMORY=y
CONFIG_FAT_FORCE_INDIRECT=y
CONFIG_FAT_LFN=y
CONFIG_FS_FAT=y
CONFIG_FS_FATTIME=y
CONFIG_FS_PROCFS=y
CONFIG_GRAN=y
CONFIG_IDLETHREAD_STACKSIZE=8192
CONFIG_INIT_ENTRYPOINT="nsh_main"
CONFIG_INIT_STACKSIZE=8192
CONFIG_INTELHEX_BINARY=y
CONFIG_LIBC_PERROR_STDOUT=y
CONFIG_LIBC_STRERROR=y
CONFIG_LITEX_SDIO=y
CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
CONFIG_NSH_ARCHINIT=y
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_FILEIOSIZE=64
CONFIG_NSH_STRERROR=y
CONFIG_POSIX_SPAWN_DEFAULT_STACKSIZE=8192
CONFIG_PTHREAD_STACK_DEFAULT=8192
CONFIG_RAM_SIZE=268435456
CONFIG_RAM_START=0x40000000
CONFIG_RAW_BINARY=y
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_WAITPID=y
CONFIG_STACK_COLORATION=y
CONFIG_START_DAY=20
CONFIG_START_MONTH=3
CONFIG_START_YEAR=2020
CONFIG_SYSTEM_NSH=y
CONFIG_TASK_NAME_SIZE=12
CONFIG_TESTING_GETPRIME=y
CONFIG_UART0_RXBUFSIZE=128
CONFIG_UART0_SERIAL_CONSOLE=y
CONFIG_UART0_TXBUFSIZE=128

View file

@ -355,6 +355,7 @@ static inline int mmcsd_sendcmd4(FAR struct mmcsd_state_s *priv)
if (priv->dsrimp != false)
{
finfo("Card supports DSR - send DSR.\n");
/* CMD4 = SET_DSR will set the cards DSR register. The DSR and CMD4
* support are optional. However, since this is a broadcast command
* with no response (like CMD0), we will never know if the DSR was
@ -369,6 +370,10 @@ static inline int mmcsd_sendcmd4(FAR struct mmcsd_state_s *priv)
mmcsd_sendcmdpoll(priv, MMCSD_CMD4, CONFIG_MMCSD_DSR << 16);
nxsig_usleep(MMCSD_DSR_DELAY);
}
else
{
finfo("Card does not support DSR.\n");
}
#endif
return ret;
@ -2472,9 +2477,14 @@ static int mmcsd_widebus(FAR struct mmcsd_state_s *priv)
* SCR or in the SDIO driver capabililities)
*/
if ((priv->buswidth & MMCSD_SCR_BUSWIDTH_4BIT) != 0 &&
if (IS_SD(priv->type) &&
(priv->buswidth & MMCSD_SCR_BUSWIDTH_4BIT) != 0 &&
(priv->caps & SDIO_CAPS_1BIT_ONLY) == 0)
{
/* SD card supports 4-bit BUS and host settings is not 1-bit only. */
finfo("Setting SD BUS width to 4-bit. Card type: %d\n", priv->type);
/* Disconnect any CD/DAT3 pull up using ACMD42. ACMD42 is optional and
* need not be supported by all SD calls.
*
@ -2504,7 +2514,7 @@ static int mmcsd_widebus(FAR struct mmcsd_state_s *priv)
return ret;
}
/* Now send ACMD6 to select wide, 4-bit bus operation, beginning
/* Now send ACMD6 to select bus width operation, beginning
* with CMD55, APP_CMD:
*/
@ -2519,27 +2529,82 @@ static int mmcsd_widebus(FAR struct mmcsd_state_s *priv)
/* Then send ACMD6 */
mmcsd_sendcmdpoll(priv, SD_ACMD6, MMCSD_ACMD6_BUSWIDTH_4);
ret = mmcsd_recv_r1(priv, SD_ACMD6);
if (ret != OK)
{
return ret;
}
}
#ifdef CONFIG_MMCSD_MMCSUPPORT
else if (IS_MMC(priv->type) &&
((priv->buswidth & MMCSD_SCR_BUSWIDTH_4BIT) != 0 &&
(priv->caps & SDIO_CAPS_1BIT_ONLY) == 0))
{
/* SD card supports 4-bit BUS and host settings is not 1-bit only.
* Configuring MMC - Use MMC_SWITCH access modes.
*/
/* Configure the SDIO peripheral */
uint32_t arg = MMCSD_CMD6_MODE_WRITE_BYTE | MMCSD_CMD6_BUSWIDTH_RW;
finfo("Wide bus operation selected\n");
SDIO_WIDEBUS(priv->dev, true);
priv->widebus = true;
arg |= MMCSD_CMD6_BUS_WIDTH_4;
SDIO_CLOCK(priv->dev, CLOCK_SD_TRANSFER_4BIT);
mmcsd_sendcmdpoll(priv, MMCSD_CMD6, arg);
ret = mmcsd_recv_r1(priv, MMCSD_CMD6);
if (ret != OK)
{
ferr("ERROR: (MMCSD_CMD6) Setting MMC BUS width: %d\n", ret);
return ret;
}
}
#endif /* #ifdef CONFIG_MMCSD_MMCSUPPORT */
else
{
fwarn("No card inserted.\n");
SDIO_WIDEBUS(priv->dev, false);
priv->widebus = false;
SDIO_CLOCK(priv->dev, CLOCK_SDIO_DISABLED);
nxsig_usleep(MMCSD_CLK_DELAY);
return OK;
}
/* Wide bus operation not supported */
/* Configure the SDIO peripheral */
fwarn("WARNING: Card does not support wide-bus operation\n");
return -ENOSYS;
if ((priv->buswidth & MMCSD_SCR_BUSWIDTH_4BIT) != 0)
{
finfo("Wide bus operation selected\n");
SDIO_WIDEBUS(priv->dev, true);
priv->widebus = true;
}
else
{
finfo("Narrow bus operation selected\n");
SDIO_WIDEBUS(priv->dev, false);
priv->widebus = false;
}
if (IS_SD(priv->type))
{
if ((priv->buswidth & MMCSD_SCR_BUSWIDTH_4BIT) != 0)
{
SDIO_CLOCK(priv->dev, CLOCK_SD_TRANSFER_4BIT);
}
else
{
SDIO_CLOCK(priv->dev, CLOCK_SD_TRANSFER_1BIT);
}
}
#ifdef CONFIG_MMCSD_MMCSUPPORT
else
{
SDIO_CLOCK(priv->dev, CLOCK_MMC_TRANSFER);
}
#endif /* #ifdef CONFIG_MMCSD_MMCSUPPORT */
nxsig_usleep(MMCSD_CLK_DELAY);
return OK;
}
/****************************************************************************
@ -2571,6 +2636,8 @@ static int mmcsd_mmcinitialize(FAR struct mmcsd_state_s *priv)
* identification state / card-identification mode.
*/
finfo("Initialising MMC card.\n");
mmcsd_sendcmdpoll(priv, MMCSD_CMD2, 0);
ret = SDIO_RECVR2(priv->dev, MMCSD_CMD2, cid);
if (ret != OK)
@ -2587,7 +2654,7 @@ static int mmcsd_mmcinitialize(FAR struct mmcsd_state_s *priv)
*/
priv->rca = 1; /* There is only one card */
mmcsd_sendcmdpoll(priv, MMC_CMD3, priv->rca << 16);
mmcsd_sendcmdpoll(priv, MMC_CMD3, (uint32_t)priv->rca << 16);
ret = mmcsd_recv_r1(priv, MMC_CMD3);
if (ret != OK)
{
@ -2597,8 +2664,8 @@ static int mmcsd_mmcinitialize(FAR struct mmcsd_state_s *priv)
/* This should have caused a transition to standby state. However, this
* will not be reflected in the present R1/6 status. R1/6 contains the
* state of the card when the command was received, not when it completed
* execution.
* state of the card when the command was received, not when it
* completed execution.
*
* Verify that we are in standby state/data-transfer mode
*/
@ -2612,10 +2679,18 @@ static int mmcsd_mmcinitialize(FAR struct mmcsd_state_s *priv)
/* Send CMD9, SEND_CSD in standby state/data-transfer mode to obtain the
* Card Specific Data (CSD) register, e.g., block length, card storage
* capacity, etc. (Stays in standby state/data-transfer mode)
* capacity, etc. (Stays in standby state/data-transfer mode).
* NOTE in v2.0 high capacity cards, the following values are always
* returned:
* - write block length = 9 = 2^9 = 512
* - read block length = 9 = 512
* - rw2 factor = 0x2 (010b)
* - size_mult = 0
* We can't decode the CSD register yet as we also need to read the
* extended CSD register.
*/
mmcsd_sendcmdpoll(priv, MMCSD_CMD9, priv->rca << 16);
mmcsd_sendcmdpoll(priv, MMCSD_CMD9, (uint32_t) priv->rca << 16);
ret = SDIO_RECVR2(priv->dev, MMCSD_CMD9, csd);
if (ret != OK)
{
@ -2623,6 +2698,13 @@ static int mmcsd_mmcinitialize(FAR struct mmcsd_state_s *priv)
return ret;
}
/* Decode the CSD register to obtain version. We will need to
* decode further if card is v4.0 or higher as it supports
* ext_csd commands.
*/
mmcsd_decode_csd(priv, csd);
/* Set the Driver Stage Register (DSR) if (1) a CONFIG_MMCSD_DSR has been
* provided and (2) the card supports a DSR register. If no DSR value
* the card default value (0x0404) will be used.
@ -2630,7 +2712,8 @@ static int mmcsd_mmcinitialize(FAR struct mmcsd_state_s *priv)
mmcsd_sendcmd4(priv);
/* Send CMD7 with the argument == RCA in order to select the card
/* Select the card.
* Send CMD7 with the argument == RCA in order to select the card
* and send it in data-trasfer mode. Since we are supporting
* only a single card, we just leave the card selected all of the time.
*/
@ -2643,14 +2726,33 @@ static int mmcsd_mmcinitialize(FAR struct mmcsd_state_s *priv)
return ret;
}
/* If the hardware only supports 4-bit transfer mode then we forced to
* attempt to setup the card in this mode before checking the ext CSD
* register.
*/
if ((priv->caps & SDIO_CAPS_4BIT_ONLY) != 0)
{
/* Select width (4-bit) bus operation */
priv->buswidth = MMCSD_SCR_BUSWIDTH_4BIT;
ret = mmcsd_widebus(priv);
if (ret != OK)
{
ferr("ERROR: Failed to set wide bus operation: %d\n", ret);
}
}
/* CSD Decoding for MMC should be done after entering in data-transfer mode
* because if the card has block addressing then extended CSD register
* must be read in order to get the right number of blocks and capacity,
* but it has to be done in data-transfer mode.
* and BUS width but it has to be done in data-transfer mode.
*/
if (IS_BLOCK(priv->type))
{
finfo("Card supports eMMC spec 4.0 (or greater). Reading ext_csd.\n");
ret = mmcsd_read_csd(priv);
if (ret != OK)
{
@ -2661,10 +2763,17 @@ static int mmcsd_mmcinitialize(FAR struct mmcsd_state_s *priv)
mmcsd_decode_csd(priv, csd);
/* Select high speed MMC clocking (which may depend on the DSR setting) */
if ((priv->caps & SDIO_CAPS_4BIT_ONLY) != 0)
{
/* Select width (4-bit) bus operation (if the card supports it) */
ret = mmcsd_widebus(priv);
if (ret != OK)
{
ferr("ERROR: Failed to set wide bus operation: %d\n", ret);
}
}
SDIO_CLOCK(priv->dev, CLOCK_MMC_TRANSFER);
nxsig_usleep(MMCSD_CLK_DELAY);
return OK;
}
@ -2698,6 +2807,7 @@ static int mmcsd_read_csd(FAR struct mmcsd_state_s *priv)
memset(buffer, 0, sizeof(buffer));
#if defined(CONFIG_SDIO_DMA) && defined(CONFIG_ARCH_HAVE_SDIO_PREFLIGHT)
/* If we think we are going to perform a DMA transfer, make sure that we
* will be able to before we commit the card to the operation.
*/
@ -2726,7 +2836,7 @@ static int mmcsd_read_csd(FAR struct mmcsd_state_s *priv)
return ret;
}
/* Select the block size for the card */
/* Select the block size for the card (CMD16) */
ret = mmcsd_setblocklen(priv, 512);
if (ret != OK)
@ -2745,6 +2855,7 @@ static int mmcsd_read_csd(FAR struct mmcsd_state_s *priv)
#ifdef CONFIG_SDIO_DMA
if ((priv->caps & SDIO_CAPS_DMASUPPORTED) != 0)
{
finfo("Setting up for DMA transfer.\n");
ret = SDIO_DMARECVSETUP(priv->dev, buffer, 512);
if (ret != OK)
{
@ -3274,8 +3385,9 @@ static int mmcsd_sdinitialize(FAR struct mmcsd_state_s *priv)
{
/* Select width (4-bit) bus operation */
priv->buswidth = 4;
priv->buswidth = MMCSD_SCR_BUSWIDTH_4BIT;
ret = mmcsd_widebus(priv);
if (ret != OK)
{
ferr("ERROR: Failed to set wide bus operation: %d\n", ret);
@ -3296,7 +3408,7 @@ static int mmcsd_sdinitialize(FAR struct mmcsd_state_s *priv)
mmcsd_decode_scr(priv, scr);
if ((priv->caps & SDIO_CAPS_4BIT_ONLY) == 0)
if ((priv->caps & SDIO_CAPS_4BIT_ONLY) != 0)
{
/* Select width (4-bit) bus operation (if the card supports it) */
@ -3335,6 +3447,8 @@ static int mmcsd_cardidentify(FAR struct mmcsd_state_s *priv)
clock_t elapsed;
int ret;
finfo("Identifying card...\n");
/* Assume failure to identify the card */
priv->type = MMCSD_CARDTYPE_UNKNOWN;
@ -3349,6 +3463,13 @@ static int mmcsd_cardidentify(FAR struct mmcsd_state_s *priv)
return -ENODEV;
}
/* For eMMC, Send CMD0 with argument 0xf0f0f0f0 as per JEDEC v4.41
* for pre-idle. No effect for SD.
*/
mmcsd_sendcmdpoll(priv, MMCSD_CMD0, 0xf0f0f0f0);
nxsig_usleep(MMCSD_IDLE_DELAY);
/* Set ID mode clocking (<400KHz) */
SDIO_CLOCK(priv->dev, CLOCK_IDMODE);
@ -3376,12 +3497,14 @@ static int mmcsd_cardidentify(FAR struct mmcsd_state_s *priv)
if (ret != OK)
{
ferr("ERROR: CMD1 RECVR3: %d\n", ret);
fwarn("WARNING: CMD1 RECVR3: %d. \
NOTE: This is expected for SD cards.\n", ret);
/* CMD1 did not succeed, card is not MMC. This sleep let
* the communication to recover before another send.
/* CMD1 did not succeed, card is not MMC. Return to idle
* to allow the communication to recover before another send.
*/
mmcsd_sendcmdpoll(priv, MMCSD_CMD0, 0);
nxsig_usleep(MMCSD_IDLE_DELAY);
}
else
@ -3471,7 +3594,7 @@ static int mmcsd_cardidentify(FAR struct mmcsd_state_s *priv)
}
}
/* At this point, type is either UNKNOWN or SDV2. Try sending
/* At this point, type is either UNKNOWN, eMMC or SDV2. Try sending
* CMD55 and (maybe) ACMD41 for up to 1 second or until the card
* exits the IDLE state. CMD55 is supported by SD V1.x and SD V2.x,
* but not MMC
@ -3481,7 +3604,7 @@ static int mmcsd_cardidentify(FAR struct mmcsd_state_s *priv)
elapsed = 0;
do
{
/* We may have already determined that his card is an MMC card from
/* We may have already determined that this card is an MMC card from
* an earlier pass through this loop. In that case, we should
* skip the SD-specific commands.
*/
@ -3602,6 +3725,8 @@ static int mmcsd_cardidentify(FAR struct mmcsd_state_s *priv)
{
/* CMD1 succeeded... this must be an MMC card */
finfo("Confirmed MMC card present.\n");
priv->type = MMCSD_CARDTYPE_MMC;
/* Now, check if this is a MMC card/chip that supports block
@ -3633,9 +3758,13 @@ static int mmcsd_cardidentify(FAR struct mmcsd_state_s *priv)
* Then break out of the look with an MMC card identified
*/
finfo("MMC card/chip ready!\n");
finfo("MMC card/chip is ready!\n");
break;
}
else
{
finfo("MMC card/chip is busy. Waiting for reply...\n");
}
}
}
#endif
@ -3708,6 +3837,8 @@ static int mmcsd_probe(FAR struct mmcsd_state_s *priv)
{
/* Yes.. probe it. First, what kind of card was inserted? */
finfo("Card present. Probing....\n");
ret = mmcsd_cardidentify(priv);
if (ret != OK)
{
@ -3722,24 +3853,33 @@ static int mmcsd_probe(FAR struct mmcsd_state_s *priv)
/* Bit 1: SD version 1.x */
case MMCSD_CARDTYPE_SDV1:
finfo("SD version 1.x .\n");
ret = mmcsd_sdinitialize(priv);
break;
/* SD version 2.x with byte addressing */
case MMCSD_CARDTYPE_SDV2:
finfo("SD version 2.x with byte addressing.\n");
ret = mmcsd_sdinitialize(priv);
break;
/* SD version 2.x with block addressing */
case MMCSD_CARDTYPE_SDV2 | MMCSD_CARDTYPE_BLOCK:
finfo("SD version 2.x with block addressing.\n");
ret = mmcsd_sdinitialize(priv);
break;
/* MMC card with byte addressing */
case MMCSD_CARDTYPE_MMC:
finfo("MMC card with byte addressing.\n");
/* MMC card with block addressing */
case MMCSD_CARDTYPE_MMC | MMCSD_CARDTYPE_BLOCK:
finfo("MMC card with block addressing.\n");
#ifdef CONFIG_MMCSD_MMCSUPPORT
ret = mmcsd_mmcinitialize(priv);
break;
@ -3824,8 +3964,10 @@ static int mmcsd_removed(FAR struct mmcsd_state_s *priv)
/* Go back to the default 1-bit data bus. */
priv->buswidth = MMCSD_SCR_BUSWIDTH_1BIT;
SDIO_WIDEBUS(priv->dev, false);
priv->widebus = false;
mmcsd_widebus(priv);
/* Disable clocking to the card */

View file

@ -32,6 +32,32 @@
* Pre-processor Definitions
****************************************************************************/
/* CMD6 (MMC_SWITCH) argument
* MMC_SWITCH argument format:
*
* [31:26] Always 0
* [25:24] Access Mode
* [23:16] Location of target Byte in EXT_CSD
* [15:08] Value Byte
* [07:03] Always 0
* [02:00] Command Set
*/
#define MMCSD_CMD6_BUSWIDTH_RWSHIFT (16)
# define MMCSD_CMD6_BUSWIDTH_RW ((uint32_t)0xb7 << MMCSD_CMD6_BUSWIDTH_RWSHIFT) /* R/W */
#define MMCSD_CMD6_WRITE_BYTE_SHIFT (24)
# define MMCSD_CMD6_MODE_CMD_SET ((uint32_t)0x00 << MMCSD_CMD6_WRITE_BYTE_SHIFT) /* Change the command set */
# define MMCSD_CMD6_MODE_SET_BITS ((uint32_t)0x01 << MMCSD_CMD6_WRITE_BYTE_SHIFT) /* Set bits which are 1 in value */
# define MMCSD_CMD6_MODE_CLEAR_BITS ((uint32_t)0x02 << MMCSD_CMD6_WRITE_BYTE_SHIFT) /* Clear bits which are 1 in value */
# define MMCSD_CMD6_MODE_WRITE_BYTE ((uint32_t)0x03 << MMCSD_CMD6_WRITE_BYTE_SHIFT) /* Set target to value */
#define MMCSD_CMD6_BUS_WIDTH_SHIFT (8)
# define MMCSD_CMD6_BUS_WIDTH_1 ((uint32_t)0x00 << MMCSD_CMD6_BUS_WIDTH_SHIFT) /* Card is in 1 bit mode */
# define MMCSD_CMD6_BUS_WIDTH_4 ((uint32_t)0x01 << MMCSD_CMD6_BUS_WIDTH_SHIFT) /* Card is in 4 bit mode */
# define MMCSD_CMD6_CSD_BUS_WIDTH_8 ((uint32_t)0x02 << MMCSD_CMD6_BUS_WIDTH_SHIFT) /* Card is in 8 bit mode */
# define MMCSD_CMD6_DDR_BUS_WIDTH_4 ((uint32_t)0x05 << MMCSD_CMD6_BUS_WIDTH_SHIFT) /* Card is in 4 bit DDR mode */
# define MMCSD_CMD6_DDR_BUS_WIDTH_8 ((uint32_t)0x06 << MMCSD_CMD6_BUS_WIDTH_SHIFT) /* Card is in 8 bit DDR mode */
/* CMD8 Argument:
* [31:12]: Reserved (shall be set to '0')
* [11:8]: Supply Voltage (VHS) 0x1 (Range: 2.7-3.6 V)