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:
parent
eb0e05be0d
commit
50a8ec62c4
5 changed files with 316 additions and 31 deletions
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
75
boards/risc-v/litex/arty_a7/configs/sdmmc/defconfig
Normal file
75
boards/risc-v/litex/arty_a7/configs/sdmmc/defconfig
Normal 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
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue