drivers/sdmmc_stm32: add eMMC support
The only difference is calling HAL_MMC_*() instead of HAL_SD_*() functions, and removing the card detect logic. Signed-off-by: Armin Brauns <armin.brauns@embedded-solutions.at>
This commit is contained in:
parent
0d53af4aa1
commit
444018f133
|
@ -38,8 +38,10 @@ config SDMMC_STM32
|
|||
bool "STM32 SDMMC driver"
|
||||
default y
|
||||
depends on DT_HAS_ST_STM32_SDMMC_ENABLED
|
||||
select USE_STM32_HAL_SD
|
||||
select USE_STM32_HAL_SD_EX if SOC_SERIES_STM32L4X
|
||||
select USE_STM32_HAL_SD if !SDMMC_STM32_EMMC
|
||||
select USE_STM32_HAL_SD_EX if !SDMMC_STM32_EMMC && SOC_SERIES_STM32L4X
|
||||
select USE_STM32_HAL_MMC if SDMMC_STM32_EMMC
|
||||
select USE_STM32_HAL_MMC_EX if SDMMC_STM32_EMMC && SOC_SERIES_STM32L4X
|
||||
select USE_STM32_LL_SDMMC
|
||||
select USE_STM32_HAL_DMA if (SOC_SERIES_STM32L4X || SOC_SERIES_STM32F7X || SOC_SERIES_STM32F4X)
|
||||
select DMA if ($(DT_STM32_SDMMC_HAS_DMA) && SOC_SERIES_STM32F4X)
|
||||
|
@ -58,6 +60,12 @@ config SDMMC_STM32_HWFC
|
|||
Enable SDMMC Hardware Flow Control to avoid FIFO underrun (TX mode) and
|
||||
overrun (RX mode) errors.
|
||||
|
||||
config SDMMC_STM32_EMMC
|
||||
bool "STM32 SDMMC eMMC mode"
|
||||
depends on SDMMC_STM32
|
||||
help
|
||||
Use eMMC instead of SDIO (SD card) protocol. These are similar, but not entirely the same.
|
||||
|
||||
config SDMMC_STM32_CLOCK_CHECK
|
||||
bool "Runtime SDMMC 48MHz clock check"
|
||||
depends on SDMMC_STM32
|
||||
|
|
|
@ -64,11 +64,19 @@ struct sdmmc_dma_stream {
|
|||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SDMMC_STM32_EMMC
|
||||
typedef MMC_HandleTypeDef HandleTypeDef;
|
||||
typedef HAL_MMC_CardInfoTypeDef CardInfoTypeDef;
|
||||
#else
|
||||
typedef SD_HandleTypeDef HandleTypeDef;
|
||||
typedef HAL_SD_CardInfoTypeDef CardInfoTypeDef;
|
||||
#endif
|
||||
|
||||
struct stm32_sdmmc_priv {
|
||||
irq_config_func_t irq_config;
|
||||
struct k_sem thread_lock;
|
||||
struct k_sem sync;
|
||||
SD_HandleTypeDef hsd;
|
||||
HandleTypeDef hsd;
|
||||
int status;
|
||||
struct k_work work;
|
||||
struct gpio_callback cd_cb;
|
||||
|
@ -97,38 +105,32 @@ static void stm32_sdmmc_isr(const struct device *dev)
|
|||
{
|
||||
struct stm32_sdmmc_priv *priv = dev->data;
|
||||
|
||||
#ifdef CONFIG_SDMMC_STM32_EMMC
|
||||
HAL_MMC_IRQHandler(&priv->hsd);
|
||||
#else
|
||||
HAL_SD_IRQHandler(&priv->hsd);
|
||||
#endif
|
||||
}
|
||||
|
||||
void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
struct stm32_sdmmc_priv *priv =
|
||||
CONTAINER_OF(hsd, struct stm32_sdmmc_priv, hsd);
|
||||
#define DEFINE_HAL_CALLBACK(name) \
|
||||
void name(HandleTypeDef *hsd) \
|
||||
{ \
|
||||
struct stm32_sdmmc_priv *priv = CONTAINER_OF(hsd, struct stm32_sdmmc_priv, hsd); \
|
||||
\
|
||||
priv->status = hsd->ErrorCode; \
|
||||
\
|
||||
k_sem_give(&priv->sync); \
|
||||
}
|
||||
|
||||
priv->status = hsd->ErrorCode;
|
||||
|
||||
k_sem_give(&priv->sync);
|
||||
}
|
||||
|
||||
void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
struct stm32_sdmmc_priv *priv =
|
||||
CONTAINER_OF(hsd, struct stm32_sdmmc_priv, hsd);
|
||||
|
||||
priv->status = hsd->ErrorCode;
|
||||
|
||||
k_sem_give(&priv->sync);
|
||||
}
|
||||
|
||||
void HAL_SD_ErrorCallback(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
struct stm32_sdmmc_priv *priv =
|
||||
CONTAINER_OF(hsd, struct stm32_sdmmc_priv, hsd);
|
||||
|
||||
priv->status = hsd->ErrorCode;
|
||||
|
||||
k_sem_give(&priv->sync);
|
||||
}
|
||||
#ifdef CONFIG_SDMMC_STM32_EMMC
|
||||
DEFINE_HAL_CALLBACK(HAL_MMC_TxCpltCallback);
|
||||
DEFINE_HAL_CALLBACK(HAL_MMC_RxCpltCallback);
|
||||
DEFINE_HAL_CALLBACK(HAL_MMC_ErrorCallback);
|
||||
#else
|
||||
DEFINE_HAL_CALLBACK(HAL_SD_TxCpltCallback);
|
||||
DEFINE_HAL_CALLBACK(HAL_SD_RxCpltCallback);
|
||||
DEFINE_HAL_CALLBACK(HAL_SD_ErrorCallback);
|
||||
#endif
|
||||
|
||||
static int stm32_sdmmc_clock_enable(struct stm32_sdmmc_priv *priv)
|
||||
{
|
||||
|
@ -166,6 +168,7 @@ static int stm32_sdmmc_clock_enable(struct stm32_sdmmc_priv *priv)
|
|||
return clock_control_on(clock, (clock_control_subsys_t)&priv->pclken[0]);
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_SDMMC_STM32_EMMC)
|
||||
static int stm32_sdmmc_clock_disable(struct stm32_sdmmc_priv *priv)
|
||||
{
|
||||
const struct device *clock;
|
||||
|
@ -175,6 +178,7 @@ static int stm32_sdmmc_clock_disable(struct stm32_sdmmc_priv *priv)
|
|||
return clock_control_off(clock,
|
||||
(clock_control_subsys_t)&priv->pclken);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if STM32_SDMMC_USE_DMA
|
||||
|
||||
|
@ -289,7 +293,11 @@ static int stm32_sdmmc_access_init(struct disk_info *disk)
|
|||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SDMMC_STM32_EMMC
|
||||
err = HAL_MMC_Init(&priv->hsd);
|
||||
#else
|
||||
err = HAL_SD_Init(&priv->hsd);
|
||||
#endif
|
||||
if (err != HAL_OK) {
|
||||
LOG_ERR("failed to init stm32_sdmmc (ErrorCode 0x%X)", priv->hsd.ErrorCode);
|
||||
return -EIO;
|
||||
|
@ -303,11 +311,14 @@ static int stm32_sdmmc_access_init(struct disk_info *disk)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_SDMMC_STM32_EMMC)
|
||||
static void stm32_sdmmc_access_deinit(struct stm32_sdmmc_priv *priv)
|
||||
{
|
||||
HAL_SD_DeInit(&priv->hsd);
|
||||
|
||||
stm32_sdmmc_clock_disable(priv);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int stm32_sdmmc_access_status(struct disk_info *disk)
|
||||
{
|
||||
|
@ -317,6 +328,37 @@ static int stm32_sdmmc_access_status(struct disk_info *disk)
|
|||
return priv->status;
|
||||
}
|
||||
|
||||
static int stm32_sdmmc_is_card_in_transfer(HandleTypeDef *hsd)
|
||||
{
|
||||
#ifdef CONFIG_SDMMC_STM32_EMMC
|
||||
return HAL_MMC_GetCardState(hsd) == HAL_MMC_CARD_TRANSFER;
|
||||
#else
|
||||
return HAL_SD_GetCardState(hsd) == HAL_SD_CARD_TRANSFER;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int stm32_sdmmc_read_blocks(HandleTypeDef *hsd, uint8_t *data_buf,
|
||||
uint32_t start_sector, uint32_t num_sector)
|
||||
{
|
||||
#if STM32_SDMMC_USE_DMA || IS_ENABLED(DT_PROP(DT_DRV_INST(0), idma))
|
||||
|
||||
#ifdef CONFIG_SDMMC_STM32_EMMC
|
||||
return HAL_MMC_ReadBlocks_DMA(hsd, data_buf, start_sector, num_sector);
|
||||
#else
|
||||
return HAL_SD_ReadBlocks_DMA(hsd, data_buf, start_sector, num_sector);
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifdef CONFIG_SDMMC_STM32_EMMC
|
||||
return HAL_MMC_ReadBlocks_IT(hsd, data_buf, start_sector, num_sector);
|
||||
#else
|
||||
return HAL_SD_ReadBlocks_IT(hsd, data_buf, start_sector, num_sector);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static int stm32_sdmmc_access_read(struct disk_info *disk, uint8_t *data_buf,
|
||||
uint32_t start_sector, uint32_t num_sector)
|
||||
{
|
||||
|
@ -326,13 +368,7 @@ static int stm32_sdmmc_access_read(struct disk_info *disk, uint8_t *data_buf,
|
|||
|
||||
k_sem_take(&priv->thread_lock, K_FOREVER);
|
||||
|
||||
#if STM32_SDMMC_USE_DMA || IS_ENABLED(DT_PROP(DT_DRV_INST(0), idma))
|
||||
err = HAL_SD_ReadBlocks_DMA(&priv->hsd, data_buf, start_sector,
|
||||
num_sector);
|
||||
#else
|
||||
err = HAL_SD_ReadBlocks_IT(&priv->hsd, data_buf, start_sector,
|
||||
num_sector);
|
||||
#endif
|
||||
err = stm32_sdmmc_read_blocks(&priv->hsd, data_buf, start_sector, num_sector);
|
||||
if (err != HAL_OK) {
|
||||
LOG_ERR("sd read block failed %d", err);
|
||||
err = -EIO;
|
||||
|
@ -347,7 +383,7 @@ static int stm32_sdmmc_access_read(struct disk_info *disk, uint8_t *data_buf,
|
|||
goto end;
|
||||
}
|
||||
|
||||
while (HAL_SD_GetCardState(&priv->hsd) != HAL_SD_CARD_TRANSFER) {
|
||||
while (!stm32_sdmmc_is_card_in_transfer(&priv->hsd)) {
|
||||
}
|
||||
|
||||
end:
|
||||
|
@ -355,6 +391,29 @@ end:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int stm32_sdmmc_write_blocks(HandleTypeDef *hsd,
|
||||
uint8_t *data_buf,
|
||||
uint32_t start_sector, uint32_t num_sector)
|
||||
{
|
||||
#if STM32_SDMMC_USE_DMA || IS_ENABLED(DT_PROP(DT_DRV_INST(0), idma))
|
||||
|
||||
#ifdef CONFIG_SDMMC_STM32_EMMC
|
||||
return HAL_MMC_WriteBlocks_DMA(hsd, data_buf, start_sector, num_sector);
|
||||
#else
|
||||
return HAL_SD_WriteBlocks_DMA(hsd, data_buf, start_sector, num_sector);
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifdef CONFIG_SDMMC_STM32_EMMC
|
||||
return HAL_MMC_WriteBlocks_IT(hsd, data_buf, start_sector, num_sector);
|
||||
#else
|
||||
return HAL_SD_WriteBlocks_IT(hsd, data_buf, start_sector, num_sector);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static int stm32_sdmmc_access_write(struct disk_info *disk,
|
||||
const uint8_t *data_buf,
|
||||
uint32_t start_sector, uint32_t num_sector)
|
||||
|
@ -365,13 +424,7 @@ static int stm32_sdmmc_access_write(struct disk_info *disk,
|
|||
|
||||
k_sem_take(&priv->thread_lock, K_FOREVER);
|
||||
|
||||
#if STM32_SDMMC_USE_DMA || IS_ENABLED(DT_PROP(DT_DRV_INST(0), idma))
|
||||
err = HAL_SD_WriteBlocks_DMA(&priv->hsd, (uint8_t *)data_buf, start_sector,
|
||||
num_sector);
|
||||
#else
|
||||
err = HAL_SD_WriteBlocks_IT(&priv->hsd, (uint8_t *)data_buf, start_sector,
|
||||
num_sector);
|
||||
#endif
|
||||
err = stm32_sdmmc_write_blocks(&priv->hsd, (uint8_t *)data_buf, start_sector, num_sector);
|
||||
if (err != HAL_OK) {
|
||||
LOG_ERR("sd write block failed %d", err);
|
||||
err = -EIO;
|
||||
|
@ -386,7 +439,7 @@ static int stm32_sdmmc_access_write(struct disk_info *disk,
|
|||
goto end;
|
||||
}
|
||||
|
||||
while (HAL_SD_GetCardState(&priv->hsd) != HAL_SD_CARD_TRANSFER) {
|
||||
while (!stm32_sdmmc_is_card_in_transfer(&priv->hsd)) {
|
||||
}
|
||||
|
||||
end:
|
||||
|
@ -394,24 +447,33 @@ end:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int stm32_sdmmc_get_card_info(HandleTypeDef *hsd, CardInfoTypeDef *info)
|
||||
{
|
||||
#ifdef CONFIG_SDMMC_STM32_EMMC
|
||||
return HAL_MMC_GetCardInfo(hsd, info);
|
||||
#else
|
||||
return HAL_SD_GetCardInfo(hsd, info);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int stm32_sdmmc_access_ioctl(struct disk_info *disk, uint8_t cmd,
|
||||
void *buff)
|
||||
{
|
||||
const struct device *dev = disk->dev;
|
||||
struct stm32_sdmmc_priv *priv = dev->data;
|
||||
HAL_SD_CardInfoTypeDef info;
|
||||
CardInfoTypeDef info;
|
||||
int err;
|
||||
|
||||
switch (cmd) {
|
||||
case DISK_IOCTL_GET_SECTOR_COUNT:
|
||||
err = HAL_SD_GetCardInfo(&priv->hsd, &info);
|
||||
err = stm32_sdmmc_get_card_info(&priv->hsd, &info);
|
||||
if (err != HAL_OK) {
|
||||
return -EIO;
|
||||
}
|
||||
*(uint32_t *)buff = info.LogBlockNbr;
|
||||
break;
|
||||
case DISK_IOCTL_GET_SECTOR_SIZE:
|
||||
err = HAL_SD_GetCardInfo(&priv->hsd, &info);
|
||||
err = stm32_sdmmc_get_card_info(&priv->hsd, &info);
|
||||
if (err != HAL_OK) {
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -442,6 +504,13 @@ static struct disk_info stm32_sdmmc_info = {
|
|||
.ops = &stm32_sdmmc_ops,
|
||||
};
|
||||
|
||||
|
||||
#ifdef CONFIG_SDMMC_STM32_EMMC
|
||||
static bool stm32_sdmmc_card_present(struct stm32_sdmmc_priv *priv)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#else /* CONFIG_SDMMC_STM32_EMMC */
|
||||
/*
|
||||
* Check if the card is present or not. If no card detect gpio is set, assume
|
||||
* the card is present. If reading the gpio fails for some reason, assume the
|
||||
|
@ -539,6 +608,7 @@ static int stm32_sdmmc_card_detect_uninit(struct stm32_sdmmc_priv *priv)
|
|||
gpio_remove_callback(priv->cd.port, &priv->cd_cb);
|
||||
return 0;
|
||||
}
|
||||
#endif /* !CONFIG_SDMMC_STM32_EMMC */
|
||||
|
||||
static int stm32_sdmmc_pwr_init(struct stm32_sdmmc_priv *priv)
|
||||
{
|
||||
|
@ -588,8 +658,6 @@ static int disk_stm32_sdmmc_init(const struct device *dev)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
k_work_init(&priv->work, stm32_sdmmc_cd_handler);
|
||||
|
||||
/* Configure dt provided device signals when available */
|
||||
err = pinctrl_apply_state(priv->pcfg, PINCTRL_STATE_DEFAULT);
|
||||
if (err < 0) {
|
||||
|
@ -602,10 +670,14 @@ static int disk_stm32_sdmmc_init(const struct device *dev)
|
|||
k_sem_init(&priv->thread_lock, 1, 1);
|
||||
k_sem_init(&priv->sync, 0, 1);
|
||||
|
||||
#if !defined(CONFIG_SDMMC_STM32_EMMC)
|
||||
k_work_init(&priv->work, stm32_sdmmc_cd_handler);
|
||||
|
||||
err = stm32_sdmmc_card_detect_init(priv);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
err = stm32_sdmmc_pwr_init(priv);
|
||||
if (err) {
|
||||
|
@ -628,7 +700,9 @@ static int disk_stm32_sdmmc_init(const struct device *dev)
|
|||
err_pwr:
|
||||
stm32_sdmmc_pwr_uninit(priv);
|
||||
err_card_detect:
|
||||
#if !defined(CONFIG_SDMMC_STM32_EMMC)
|
||||
stm32_sdmmc_card_detect_uninit(priv);
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue