Skip to content

Commit a79f485

Browse files
danieldegrassedleach02
authored andcommitted
drivers: disk: add SDMMC zephyr disk driver
Add generic sdmmc zephyr disk driver, which uses the SDMMC subsystem Signed-off-by: Daniel DeGrasse <[email protected]>
1 parent aadcc97 commit a79f485

File tree

3 files changed

+151
-0
lines changed

3 files changed

+151
-0
lines changed

drivers/disk/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@ zephyr_library_sources_ifdef(CONFIG_DISK_DRIVER_RAM ramdisk.c)
1111
zephyr_library_sources_ifdef(CONFIG_SDMMC_OVER_SPI sdmmc_spi.c)
1212
zephyr_library_sources_ifdef(CONFIG_SDMMC_STM32 sdmmc_stm32.c)
1313
zephyr_library_sources_ifdef(CONFIG_SDMMC_USDHC usdhc.c)
14+
zephyr_library_sources_ifdef(CONFIG_SDMMC_SUBSYS sdmmc_subsys.c)
1415

1516
endif()

drivers/disk/Kconfig.sdmmc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
DT_COMPAT_ZEPHYR_MMC_SPI_SLOT := zephyr,mmc-spi-slot
66
DT_COMPAT_NXP_USDHC := nxp,imx-usdhc
77
DT_COMPAT_ST_STM32_SDMMC := st,stm32-sdmmc
8+
DT_COMPAT_ZEPHYR_MMC := zephyr,sdmmc-disk
89

910
config DISK_DRIVER_SDMMC
1011
bool "SDMMC card driver"
@@ -33,6 +34,14 @@ config SDMMC_OVER_SPI
3334
help
3435
File system on a SDHC card accessed over SPI.
3536

37+
config SDMMC_SUBSYS
38+
bool "SDMMC access via SD subsystem"
39+
select SD_STACK
40+
select SDHC
41+
default $(dt_compat_enabled,$(DT_COMPAT_ZEPHYR_MMC))
42+
help
43+
Enable SDMMC access via SD subsystem
44+
3645
config SDMMC_USDHC
3746
bool "NXP i.MXRT USDHC driver"
3847
depends on (HAS_MCUX_USDHC1 || HAS_MCUX_USDHC2)

drivers/disk/sdmmc_subsys.c

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/*
2+
* Copyright 2022 NXP
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/*
8+
* SDMMC disk driver using zephyr SD subsystem
9+
*/
10+
#define DT_DRV_COMPAT zephyr_sdmmc_disk
11+
12+
#include <zephyr/sd/sdmmc.h>
13+
#include <zephyr/drivers/disk.h>
14+
15+
16+
enum sd_status {
17+
SD_UNINIT,
18+
SD_ERROR,
19+
SD_OK,
20+
};
21+
22+
struct sdmmc_config {
23+
const struct device *host_controller;
24+
};
25+
26+
struct sdmmc_data {
27+
struct sd_card card;
28+
enum sd_status status;
29+
char *name;
30+
};
31+
32+
33+
static int disk_sdmmc_access_init(struct disk_info *disk)
34+
{
35+
const struct device *dev = disk->dev;
36+
const struct sdmmc_config *cfg = dev->config;
37+
struct sdmmc_data *data = dev->data;
38+
int ret;
39+
40+
if (data->status == SD_OK) {
41+
/* Called twice, don't reinit */
42+
return 0;
43+
}
44+
45+
if (!sd_is_card_present(cfg->host_controller)) {
46+
return DISK_STATUS_NOMEDIA;
47+
}
48+
49+
ret = sd_init(cfg->host_controller, &data->card);
50+
if (ret) {
51+
data->status = SD_ERROR;
52+
return ret;
53+
}
54+
data->status = SD_OK;
55+
return 0;
56+
}
57+
58+
static int disk_sdmmc_access_status(struct disk_info *disk)
59+
{
60+
const struct device *dev = disk->dev;
61+
const struct sdmmc_config *cfg = dev->config;
62+
struct sdmmc_data *data = dev->data;
63+
64+
if (!sd_is_card_present(cfg->host_controller)) {
65+
return DISK_STATUS_NOMEDIA;
66+
}
67+
if (data->status == SD_OK) {
68+
return DISK_STATUS_OK;
69+
} else {
70+
return DISK_STATUS_UNINIT;
71+
}
72+
}
73+
74+
static int disk_sdmmc_access_read(struct disk_info *disk, uint8_t *buf,
75+
uint32_t sector, uint32_t count)
76+
{
77+
const struct device *dev = disk->dev;
78+
struct sdmmc_data *data = dev->data;
79+
80+
return sdmmc_read_blocks(&data->card, buf, sector, count);
81+
}
82+
83+
static int disk_sdmmc_access_write(struct disk_info *disk, const uint8_t *buf,
84+
uint32_t sector, uint32_t count)
85+
{
86+
const struct device *dev = disk->dev;
87+
struct sdmmc_data *data = dev->data;
88+
89+
return sdmmc_write_blocks(&data->card, buf, sector, count);
90+
}
91+
92+
static int disk_sdmmc_access_ioctl(struct disk_info *disk, uint8_t cmd, void *buf)
93+
{
94+
const struct device *dev = disk->dev;
95+
struct sdmmc_data *data = dev->data;
96+
97+
return sdmmc_ioctl(&data->card, cmd, buf);
98+
}
99+
100+
static const struct disk_operations sdmmc_disk_ops = {
101+
.init = disk_sdmmc_access_init,
102+
.status = disk_sdmmc_access_status,
103+
.read = disk_sdmmc_access_read,
104+
.write = disk_sdmmc_access_write,
105+
.ioctl = disk_sdmmc_access_ioctl,
106+
};
107+
108+
static struct disk_info sdmmc_disk = {
109+
.ops = &sdmmc_disk_ops,
110+
};
111+
112+
static int disk_sdmmc_init(const struct device *dev)
113+
{
114+
struct sdmmc_data *data = dev->data;
115+
116+
data->status = SD_UNINIT;
117+
sdmmc_disk.dev = dev;
118+
sdmmc_disk.name = data->name;
119+
120+
return disk_access_register(&sdmmc_disk);
121+
}
122+
123+
#define DISK_ACCESS_SDMMC_INIT(n) \
124+
static const struct sdmmc_config sdmmc_config_##n = { \
125+
.host_controller = DEVICE_DT_GET(DT_INST_PARENT(n)), \
126+
}; \
127+
\
128+
static struct sdmmc_data sdmmc_data_##n = { \
129+
.name = CONFIG_SDMMC_VOLUME_NAME, \
130+
}; \
131+
\
132+
DEVICE_DT_INST_DEFINE(n, \
133+
&disk_sdmmc_init, \
134+
NULL, \
135+
&sdmmc_data_##n, \
136+
&sdmmc_config_##n, \
137+
POST_KERNEL, \
138+
CONFIG_SDMMC_INIT_PRIORITY, \
139+
NULL);
140+
141+
DT_INST_FOREACH_STATUS_OKAY(DISK_ACCESS_SDMMC_INIT)

0 commit comments

Comments
 (0)