drivers: disk: add SDMMC zephyr disk driver
Add generic sdmmc zephyr disk driver, which uses the SDMMC subsystem Signed-off-by: Daniel DeGrasse <daniel.degrasse@nxp.com>
This commit is contained in:
parent
aadcc97c68
commit
a79f485487
3 changed files with 151 additions and 0 deletions
|
@ -11,5 +11,6 @@ zephyr_library_sources_ifdef(CONFIG_DISK_DRIVER_RAM ramdisk.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_SDMMC_OVER_SPI sdmmc_spi.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SDMMC_STM32 sdmmc_stm32.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SDMMC_USDHC usdhc.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SDMMC_SUBSYS sdmmc_subsys.c)
|
||||
|
||||
endif()
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
DT_COMPAT_ZEPHYR_MMC_SPI_SLOT := zephyr,mmc-spi-slot
|
||||
DT_COMPAT_NXP_USDHC := nxp,imx-usdhc
|
||||
DT_COMPAT_ST_STM32_SDMMC := st,stm32-sdmmc
|
||||
DT_COMPAT_ZEPHYR_MMC := zephyr,sdmmc-disk
|
||||
|
||||
config DISK_DRIVER_SDMMC
|
||||
bool "SDMMC card driver"
|
||||
|
@ -33,6 +34,14 @@ config SDMMC_OVER_SPI
|
|||
help
|
||||
File system on a SDHC card accessed over SPI.
|
||||
|
||||
config SDMMC_SUBSYS
|
||||
bool "SDMMC access via SD subsystem"
|
||||
select SD_STACK
|
||||
select SDHC
|
||||
default $(dt_compat_enabled,$(DT_COMPAT_ZEPHYR_MMC))
|
||||
help
|
||||
Enable SDMMC access via SD subsystem
|
||||
|
||||
config SDMMC_USDHC
|
||||
bool "NXP i.MXRT USDHC driver"
|
||||
depends on (HAS_MCUX_USDHC1 || HAS_MCUX_USDHC2)
|
||||
|
|
141
drivers/disk/sdmmc_subsys.c
Normal file
141
drivers/disk/sdmmc_subsys.c
Normal file
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright 2022 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* SDMMC disk driver using zephyr SD subsystem
|
||||
*/
|
||||
#define DT_DRV_COMPAT zephyr_sdmmc_disk
|
||||
|
||||
#include <zephyr/sd/sdmmc.h>
|
||||
#include <zephyr/drivers/disk.h>
|
||||
|
||||
|
||||
enum sd_status {
|
||||
SD_UNINIT,
|
||||
SD_ERROR,
|
||||
SD_OK,
|
||||
};
|
||||
|
||||
struct sdmmc_config {
|
||||
const struct device *host_controller;
|
||||
};
|
||||
|
||||
struct sdmmc_data {
|
||||
struct sd_card card;
|
||||
enum sd_status status;
|
||||
char *name;
|
||||
};
|
||||
|
||||
|
||||
static int disk_sdmmc_access_init(struct disk_info *disk)
|
||||
{
|
||||
const struct device *dev = disk->dev;
|
||||
const struct sdmmc_config *cfg = dev->config;
|
||||
struct sdmmc_data *data = dev->data;
|
||||
int ret;
|
||||
|
||||
if (data->status == SD_OK) {
|
||||
/* Called twice, don't reinit */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!sd_is_card_present(cfg->host_controller)) {
|
||||
return DISK_STATUS_NOMEDIA;
|
||||
}
|
||||
|
||||
ret = sd_init(cfg->host_controller, &data->card);
|
||||
if (ret) {
|
||||
data->status = SD_ERROR;
|
||||
return ret;
|
||||
}
|
||||
data->status = SD_OK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int disk_sdmmc_access_status(struct disk_info *disk)
|
||||
{
|
||||
const struct device *dev = disk->dev;
|
||||
const struct sdmmc_config *cfg = dev->config;
|
||||
struct sdmmc_data *data = dev->data;
|
||||
|
||||
if (!sd_is_card_present(cfg->host_controller)) {
|
||||
return DISK_STATUS_NOMEDIA;
|
||||
}
|
||||
if (data->status == SD_OK) {
|
||||
return DISK_STATUS_OK;
|
||||
} else {
|
||||
return DISK_STATUS_UNINIT;
|
||||
}
|
||||
}
|
||||
|
||||
static int disk_sdmmc_access_read(struct disk_info *disk, uint8_t *buf,
|
||||
uint32_t sector, uint32_t count)
|
||||
{
|
||||
const struct device *dev = disk->dev;
|
||||
struct sdmmc_data *data = dev->data;
|
||||
|
||||
return sdmmc_read_blocks(&data->card, buf, sector, count);
|
||||
}
|
||||
|
||||
static int disk_sdmmc_access_write(struct disk_info *disk, const uint8_t *buf,
|
||||
uint32_t sector, uint32_t count)
|
||||
{
|
||||
const struct device *dev = disk->dev;
|
||||
struct sdmmc_data *data = dev->data;
|
||||
|
||||
return sdmmc_write_blocks(&data->card, buf, sector, count);
|
||||
}
|
||||
|
||||
static int disk_sdmmc_access_ioctl(struct disk_info *disk, uint8_t cmd, void *buf)
|
||||
{
|
||||
const struct device *dev = disk->dev;
|
||||
struct sdmmc_data *data = dev->data;
|
||||
|
||||
return sdmmc_ioctl(&data->card, cmd, buf);
|
||||
}
|
||||
|
||||
static const struct disk_operations sdmmc_disk_ops = {
|
||||
.init = disk_sdmmc_access_init,
|
||||
.status = disk_sdmmc_access_status,
|
||||
.read = disk_sdmmc_access_read,
|
||||
.write = disk_sdmmc_access_write,
|
||||
.ioctl = disk_sdmmc_access_ioctl,
|
||||
};
|
||||
|
||||
static struct disk_info sdmmc_disk = {
|
||||
.ops = &sdmmc_disk_ops,
|
||||
};
|
||||
|
||||
static int disk_sdmmc_init(const struct device *dev)
|
||||
{
|
||||
struct sdmmc_data *data = dev->data;
|
||||
|
||||
data->status = SD_UNINIT;
|
||||
sdmmc_disk.dev = dev;
|
||||
sdmmc_disk.name = data->name;
|
||||
|
||||
return disk_access_register(&sdmmc_disk);
|
||||
}
|
||||
|
||||
#define DISK_ACCESS_SDMMC_INIT(n) \
|
||||
static const struct sdmmc_config sdmmc_config_##n = { \
|
||||
.host_controller = DEVICE_DT_GET(DT_INST_PARENT(n)), \
|
||||
}; \
|
||||
\
|
||||
static struct sdmmc_data sdmmc_data_##n = { \
|
||||
.name = CONFIG_SDMMC_VOLUME_NAME, \
|
||||
}; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(n, \
|
||||
&disk_sdmmc_init, \
|
||||
NULL, \
|
||||
&sdmmc_data_##n, \
|
||||
&sdmmc_config_##n, \
|
||||
POST_KERNEL, \
|
||||
CONFIG_SDMMC_INIT_PRIORITY, \
|
||||
NULL);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(DISK_ACCESS_SDMMC_INIT)
|
Loading…
Add table
Add a link
Reference in a new issue