From 1c169e37e42dcbbe27cd62aeee013afaa0b37b3c Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Sat, 29 Apr 2023 16:27:00 +0200 Subject: [PATCH] drivers/mtd_sdcard: add SDMMC support --- drivers/include/mtd_sdcard.h | 12 +++ drivers/mtd/Makefile.dep | 4 +- drivers/mtd_sdcard/mtd_sdcard.c | 133 ++++++++++++++++++++++++++++---- 3 files changed, 133 insertions(+), 16 deletions(-) diff --git a/drivers/include/mtd_sdcard.h b/drivers/include/mtd_sdcard.h index 2c7cabf92faf2..56b4c1d00b804 100644 --- a/drivers/include/mtd_sdcard.h +++ b/drivers/include/mtd_sdcard.h @@ -24,7 +24,14 @@ #include +#if IS_USED(MODULE_SDCARD_SPI) #include "sdcard_spi.h" +#elif IS_USED(MODULE_PERIPH_SDMMC) +#include "sdmmc/sdmmc.h" +#else +#error "No SD Card driver module selected" +#endif + #include "mtd.h" #ifdef __cplusplus @@ -39,8 +46,13 @@ extern "C" */ typedef struct { mtd_dev_t base; /**< inherit from mtd_dev_t object */ +#if IS_USED(MODULE_SDCARD_SPI) sdcard_spi_t *sd_card; /**< sdcard_spi dev descriptor */ const sdcard_spi_params_t *params; /**< params for sdcard_spi init */ +#elif IS_USED(MODULE_PERIPH_SDMMC) + uint8_t sd_card_idx; /**< sdmmc peripheral index */ + sdmmc_dev_t *sd_card; /**< sdmmc dev descriptor */ +#endif } mtd_sdcard_t; /** diff --git a/drivers/mtd/Makefile.dep b/drivers/mtd/Makefile.dep index 6c0bce41d74b0..0dfb5f9ac1bdb 100644 --- a/drivers/mtd/Makefile.dep +++ b/drivers/mtd/Makefile.dep @@ -11,5 +11,7 @@ ifneq (,$(filter mtd_sdcard_default,$(USEMODULE))) endif ifneq (,$(filter mtd_sdcard,$(USEMODULE))) - USEMODULE += sdcard_spi + ifeq (,$(filter sdmmc,$(USEMODULE))) + USEMODULE += sdcard_spi + endif endif diff --git a/drivers/mtd_sdcard/mtd_sdcard.c b/drivers/mtd_sdcard/mtd_sdcard.c index 39136723dd1df..3d739c85d5f59 100644 --- a/drivers/mtd_sdcard/mtd_sdcard.c +++ b/drivers/mtd_sdcard/mtd_sdcard.c @@ -18,23 +18,33 @@ * * @} */ + +#include +#include +#include + #define ENABLE_DEBUG 0 #include "debug.h" #include "kernel_defines.h" #include "macros/utils.h" #include "mtd.h" #include "mtd_sdcard.h" + +#if IS_USED(MODULE_SDCARD_SPI) #include "sdcard_spi.h" #include "sdcard_spi_internal.h" +#endif -#include -#include -#include +#if IS_USED(MODULE_SDMMC) +#define SD_HC_BLOCK_SIZE SDMMC_SDHC_BLOCK_SIZE +#endif static int mtd_sdcard_init(mtd_dev_t *dev) { DEBUG("mtd_sdcard_init\n"); mtd_sdcard_t *mtd_sd = (mtd_sdcard_t*)dev; + +#if IS_USED(MODULE_SDCARD_SPI) if ((mtd_sd->sd_card->init_done == true) || (sdcard_spi_init(mtd_sd->sd_card, mtd_sd->params) == 0)) { /* erasing whole sectors is handled internally by the card so you can @@ -47,13 +57,33 @@ static int mtd_sdcard_init(mtd_dev_t *dev) dev->write_size = SD_HC_BLOCK_SIZE; return 0; } +#elif IS_USED(MODULE_SDMMC) + /* get the SDMMC device descriptor from SDMMC peripheral index */ + mtd_sd->sd_card = sdmmc_get_dev(mtd_sd->sd_card_idx); + + if ((mtd_sd->sd_card->init_done == true) || + (sdmmc_card_init(mtd_sd->sd_card) == 0)) { + /* erasing whole sectors is handled internally by the card so you can + delete single blocks (i.e. pages) */ + dev->pages_per_sector = 1; + dev->sector_count = (uint32_t)(sdmmc_get_capacity(mtd_sd->sd_card) / + SDMMC_SDHC_BLOCK_SIZE); + + /* sdcard uses the fixed block size of SD-HC cards */ + dev->page_size = SDMMC_SDHC_BLOCK_SIZE; + dev->write_size = SDMMC_SDHC_BLOCK_SIZE; + return 0; + } +#endif return -EIO; } static int mtd_sdcard_read_page(mtd_dev_t *dev, void *buff, uint32_t page, uint32_t offset, uint32_t size) { +#if IS_USED(MODULE_SDCARD_SPI) sd_rw_response_t err; +#endif mtd_sdcard_t *mtd_sd = (mtd_sdcard_t*)dev; DEBUG("mtd_sdcard_read_page: page:%" PRIu32 " offset:%" PRIu32 " size:%" PRIu32 "\n", @@ -66,13 +96,19 @@ static int mtd_sdcard_read_page(mtd_dev_t *dev, void *buff, uint32_t page, return -ENOTSUP; } +#if IS_USED(MODULE_SDCARD_SPI) sdcard_spi_read_blocks(mtd_sd->sd_card, page, dev->work_area, SD_HC_BLOCK_SIZE, 1, &err); if (err != SD_RW_OK) { return -EIO; } - +#elif IS_USED(MODULE_SDMMC) + if (sdmmc_read_blocks(mtd_sd->sd_card, page, SDMMC_SDHC_BLOCK_SIZE, + 1, dev->work_area, NULL)) { + return -EIO; + } +#endif size = MIN(size, SD_HC_BLOCK_SIZE - offset); DEBUG("mtd_sdcard_read_page: read %" PRIu32 " bytes at offset %" PRIu32 "\n", size, offset); @@ -83,19 +119,31 @@ static int mtd_sdcard_read_page(mtd_dev_t *dev, void *buff, uint32_t page, #endif } +#if IS_USED(MODULE_SDCARD_SPI) sdcard_spi_read_blocks(mtd_sd->sd_card, page, buff, SD_HC_BLOCK_SIZE, size / SD_HC_BLOCK_SIZE, &err); if (err != SD_RW_OK) { + DEBUG("mtd_sdcard_read_page: error %d\n", err); + return -EIO; + } +#elif IS_USED(MODULE_SDMMC) + int err = sdmmc_read_blocks(mtd_sd->sd_card, page, SDMMC_SDHC_BLOCK_SIZE, + size / SDMMC_SDHC_BLOCK_SIZE, buff, NULL); + if (err) { + DEBUG("mtd_sdcard_read_page: error %d\n", err); return -EIO; } +#endif return size; } static int mtd_sdcard_write_page(mtd_dev_t *dev, const void *buff, uint32_t page, uint32_t offset, uint32_t size) { +#if IS_USED(MODULE_SDCARD_SPI) sd_rw_response_t err; +#endif mtd_sdcard_t *mtd_sd = (mtd_sdcard_t*)dev; DEBUG("mtd_sdcard_write_page: page:%" PRIu32 " offset:%" PRIu32 " size:%" PRIu32 "\n", @@ -108,24 +156,39 @@ static int mtd_sdcard_write_page(mtd_dev_t *dev, const void *buff, uint32_t page return -ENOTSUP; } +#if IS_USED(MODULE_SDCARD_SPI) sdcard_spi_read_blocks(mtd_sd->sd_card, page, dev->work_area, SD_HC_BLOCK_SIZE, 1, &err); if (err != SD_RW_OK) { return -EIO; } - +#elif IS_USED(MODULE_SDMMC) + if (sdmmc_read_blocks(mtd_sd->sd_card, page, SDMMC_SDHC_BLOCK_SIZE, + 1, dev->work_area, NULL)) { + return -EIO; + } +#endif size = MIN(size, SD_HC_BLOCK_SIZE - offset); DEBUG("mtd_sdcard_write_page: write %" PRIu32 " bytes at offset %" PRIu32 "\n", size, offset); memcpy((uint8_t *)dev->work_area + offset, buff, size); +#if IS_USED(MODULE_SDCARD_SPI) sdcard_spi_write_blocks(mtd_sd->sd_card, page, dev->work_area, SD_HC_BLOCK_SIZE, 1, &err); +#elif IS_USED(MODULE_SDMMC) + if (sdmmc_write_blocks(mtd_sd->sd_card, page, SDMMC_SDHC_BLOCK_SIZE, + 1, dev->work_area, NULL)) { + return -EIO; + } +#endif #else return -ENOTSUP; #endif - } else { + } +#if IS_USED(MODULE_SDCARD_SPI) + else { sdcard_spi_write_blocks(mtd_sd->sd_card, page, buff, SD_HC_BLOCK_SIZE, size / SD_HC_BLOCK_SIZE, &err); @@ -135,6 +198,16 @@ static int mtd_sdcard_write_page(mtd_dev_t *dev, const void *buff, uint32_t page DEBUG("mtd_sdcard_write_page: error %d\n", err); return -EIO; } +#elif IS_USED(MODULE_SDMMC) + else { + int err = sdmmc_write_blocks(mtd_sd->sd_card, page, SDMMC_SDHC_BLOCK_SIZE, + size / SDMMC_SDHC_BLOCK_SIZE, buff, NULL); + if (err) { + DEBUG("mtd_sdcard_write_page: error %d\n", err); + return -EIO; + } + } +#endif return size; } @@ -152,6 +225,7 @@ static int mtd_sdcard_erase_sector(mtd_dev_t *dev, uint32_t sector, uint32_t cou } memset(dev->work_area, 0, SD_HC_BLOCK_SIZE); while (count) { +#if IS_USED(MODULE_SDCARD_SPI) sd_rw_response_t err; sdcard_spi_write_blocks(mtd_sd->sd_card, sector, dev->work_area, SD_HC_BLOCK_SIZE, @@ -160,6 +234,12 @@ static int mtd_sdcard_erase_sector(mtd_dev_t *dev, uint32_t sector, uint32_t cou DEBUG("mtd_sdcard_erase_sector: error %d\n", err); return -EIO; } +#elif IS_USED(MODULE_SDMMC) + if (sdmmc_write_blocks(mtd_sd->sd_card, sector, SDMMC_SDHC_BLOCK_SIZE, + 1, dev->work_area, NULL)) { + return -EIO; + } +#endif --count; ++sector; } @@ -167,9 +247,16 @@ static int mtd_sdcard_erase_sector(mtd_dev_t *dev, uint32_t sector, uint32_t cou (void)dev; (void)sector; (void)count; +#if IS_USED(MODULE_SDMMC) + mtd_sdcard_t *mtd_sd = (mtd_sdcard_t*)dev; + if (IS_ACTIVE(CONFIG_MTD_SDCARD_ERASE)) { + return sdmmc_erase_blocks(mtd_sd->sd_card, sector, count); + } +#else if (IS_ACTIVE(CONFIG_MTD_SDCARD_ERASE)) { return -ENOTSUP; } +#endif #endif return 0; } @@ -223,17 +310,22 @@ const mtd_desc_t mtd_sdcard_driver = { }; #if IS_USED(MODULE_MTD_SDCARD_DEFAULT) -#include "sdcard_spi_params.h" #include "vfs_default.h" -#define SDCARD_NUMOF ARRAY_SIZE(sdcard_spi_params) - #ifndef CONFIG_SDCARD_GENERIC_MTD_OFFSET #define CONFIG_SDCARD_GENERIC_MTD_OFFSET 0 #endif +#if IS_USED(MODULE_SDCARD_SPI) +#include "sdcard_spi_params.h" + +#define SDCARD_NUMOF ARRAY_SIZE(sdcard_spi_params) + +/* this is provided by the sdcard_spi driver see drivers/sdcard_spi/sdcard_spi.c */ +extern sdcard_spi_t sdcard_spi_devs[SDCARD_NUMOF]; + #define MTD_SDCARD_DEV(n, m) \ - mtd_sdcard_t mtd_sdcard_dev ## n = { \ + mtd_sdcard_t mtd_sdcard_dev ##n = { \ .base = { \ .driver = &mtd_sdcard_driver, \ }, \ @@ -241,13 +333,24 @@ const mtd_desc_t mtd_sdcard_driver = { .params = &sdcard_spi_params[n] \ }; \ \ - mtd_dev_t CONCAT(*mtd, m) = (mtd_dev_t *)&mtd_sdcard_dev ## n + mtd_dev_t CONCAT(*mtd, m) = (mtd_dev_t *)&mtd_sdcard_dev ##n -#define MTD_SDCARD_DEV_FS(n, m, filesystem) \ - VFS_AUTO_MOUNT(filesystem, VFS_MTD(mtd_sdcard_dev ## n), VFS_DEFAULT_SD(n), m) +#elif IS_USED(MODULE_SDMMC) -/* this is provided by the sdcard_spi driver see drivers/sdcard_spi/sdcard_spi.c */ -extern sdcard_spi_t sdcard_spi_devs[SDCARD_NUMOF]; +#define MTD_SDCARD_DEV(n, m) \ + mtd_sdcard_t mtd_sdcard_dev ##n = { \ + .base = { \ + .driver = &mtd_sdcard_driver, \ + }, \ + .sd_card_idx = n, \ + }; \ + \ + mtd_dev_t CONCAT(*mtd, m) = (mtd_dev_t *)&mtd_sdcard_dev ##n + +#endif /* IS_USED(MODULE_SDMMC) */ + +#define MTD_SDCARD_DEV_FS(n, m, filesystem) \ + VFS_AUTO_MOUNT(filesystem, VFS_MTD(mtd_sdcard_dev ##n), VFS_DEFAULT_SD(n), m) MTD_SDCARD_DEV(0, CONFIG_SDCARD_GENERIC_MTD_OFFSET); #ifdef MODULE_FATFS_VFS