From 3bc095a8100363ba9ad70e9adea010e523855d77 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Tue, 30 Aug 2022 11:04:08 -0500 Subject: [PATCH] sd: MMC API, and MMC Spec - Adds the declaration of the MMC API - Adds MMC spec related declarations - Adds some properties to sdhc dts binding for mmc Signed-off-by: Declan Snyder --- dts/bindings/sdhc/sdhc.yaml | 10 +++ include/zephyr/drivers/sdhc.h | 3 + include/zephyr/sd/mmc.h | 76 +++++++++++++++++++ include/zephyr/sd/sd.h | 3 +- include/zephyr/sd/sd_spec.h | 139 +++++++++++++++++++++++++++++++++- 5 files changed, 227 insertions(+), 4 deletions(-) create mode 100644 include/zephyr/sd/mmc.h diff --git a/dts/bindings/sdhc/sdhc.yaml b/dts/bindings/sdhc/sdhc.yaml index 75c0dd53922..458d601b717 100644 --- a/dts/bindings/sdhc/sdhc.yaml +++ b/dts/bindings/sdhc/sdhc.yaml @@ -49,3 +49,13 @@ properties: description: | time in ms for SDHC to delay when toggling power to the SD card. This delay gives the card time to power up or down fully + + mmc-hs200-1_8v: + type: boolean + description: | + The host controller supports HS200 at 1.8V + + mmc-hs400-1_8v: + type: boolean + description: | + The host controller supports HS400 at 1.8V diff --git a/include/zephyr/drivers/sdhc.h b/include/zephyr/drivers/sdhc.h index dfd53f2af06..3143424b4b3 100644 --- a/include/zephyr/drivers/sdhc.h +++ b/include/zephyr/drivers/sdhc.h @@ -165,6 +165,7 @@ struct sdhc_host_caps { unsigned int sd_base_clk: 8; unsigned int max_blk_len: 2; unsigned int bus_8_bit_support: 1; + unsigned int bus_4_bit_support: 1; unsigned int adma_2_support: 1; unsigned int _rsvd_20: 1; unsigned int high_spd_support: 1; @@ -193,6 +194,8 @@ struct sdhc_host_caps { unsigned int adma3_support: 1; unsigned int vdd2_180_support: 1; unsigned int _rsvd_61: 3; + unsigned int hs200_support: 1; + unsigned int hs400_support: 1; }; /** diff --git a/include/zephyr/sd/mmc.h b/include/zephyr/sd/mmc.h new file mode 100644 index 00000000000..f2149519de1 --- /dev/null +++ b/include/zephyr/sd/mmc.h @@ -0,0 +1,76 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Public API for MMC memory card subsystem + */ + +#ifndef ZEPHYR_INCLUDE_SD_MMC_H_ +#define ZEPHYR_INCLUDE_SD_MMC_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Write blocks to MMC card from buffer + * + * Writes blocks from MMC buffer to MMC card. For best performance, this buffer + * should be aligned to CONFIG_SDHC_BUFFER_ALIGNMENT + * @param card MMC card to write from + * @param wbuf write buffer + * @param start_block first block to write to + * @param num_blocks number of blocks to write + * @retval 0 write succeeded + * @retval -EBUSY: card is busy with another request + * @retval -ETIMEDOUT: card write timed out + * @retval -EIO: I/O error + */ +int mmc_write_blocks(struct sd_card *card, const uint8_t *wbuf, + uint32_t start_block, uint32_t num_blocks); + +/** + * @brief Read block from MMC card to buffer + * + * Reads blocks into MMC buffer from MMC card. For best performance, this buffer + * should be aligned to CONFIG_SDHC_BUFFER_ALIGNMENT + * @param card MMC card to read from + * @param rbuf read buffer + * @param start_block first block to read from + * @param num_blocks number of blocks to read + * @retval 0 read succeeded + * @retval -EBUSY: card is busy with another request + * @retval -ETIMEDOUT: card read timed out + * @retval -EIO: I/O error + */ +int mmc_read_blocks(struct sd_card *card, uint8_t *rbuf, + uint32_t start_block, uint32_t num_blocks); + +/** + * @brief Get I/O control data from MMC card + * + * Sends I/O control commands to MMC card. + * @param card MMC card + * @param cmd I/O control command + * Mirrors disk subsystem, + * see include/zephyr/drivers/disk.h for list of possible commands. + * @param buf I/O control buf + * @retval 0 IOCTL command succeeded + * @retval -ENOTSUP: IOCTL command not supported + * @retval -EIO: I/O failure + */ +int mmc_ioctl(struct sd_card *card, uint8_t cmd, void *buf); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_SD_MMC_H_ */ diff --git a/include/zephyr/sd/sd.h b/include/zephyr/sd/sd.h index 8e4dd62edad..1aa13cfea89 100644 --- a/include/zephyr/sd/sd.h +++ b/include/zephyr/sd/sd.h @@ -36,6 +36,7 @@ enum card_type { CARD_SDMMC = 0, /*!< SD memory card */ CARD_SDIO = 1, /*!< SD I/O card */ CARD_COMBO = 2, /*!< SD memory and I/O card */ + CARD_MMC = 3, /*!< MMC memory card */ }; @@ -59,7 +60,7 @@ struct sd_card { uint32_t block_count; /*!< Number of blocks in SD card */ uint32_t block_size; /*!< SD block size */ uint32_t sd_version; /*!< SD specification version */ - enum sd_timing_mode card_speed; /*!< Card timing mode */ + uint32_t card_speed; /*!< Card timing mode */ enum card_status status; /*!< Card status */ enum card_type type; /*!< Card type */ uint32_t flags; /*!< Card flags */ diff --git a/include/zephyr/sd/sd_spec.h b/include/zephyr/sd/sd_spec.h index ee6a672b4d2..ed0426766ec 100644 --- a/include/zephyr/sd/sd_spec.h +++ b/include/zephyr/sd/sd_spec.h @@ -26,22 +26,28 @@ extern "C" { */ enum sd_opcode { SD_GO_IDLE_STATE = 0, + MMC_SEND_OP_COND = 1, SD_ALL_SEND_CID = 2, SD_SEND_RELATIVE_ADDR = 3, + MMC_SEND_RELATIVE_ADDR = 3, SDIO_SEND_OP_COND = 5, /* SDIO cards only */ SD_SWITCH = 6, SD_SELECT_CARD = 7, SD_SEND_IF_COND = 8, + MMC_SEND_EXT_CSD = 8, SD_SEND_CSD = 9, SD_SEND_CID = 10, SD_VOL_SWITCH = 11, SD_STOP_TRANSMISSION = 12, SD_SEND_STATUS = 13, + MMC_CHECK_BUS_TEST = 14, SD_GO_INACTIVE_STATE = 15, SD_SET_BLOCK_SIZE = 16, SD_READ_SINGLE_BLOCK = 17, SD_READ_MULTIPLE_BLOCK = 18, SD_SEND_TUNING_BLOCK = 19, + MMC_SEND_BUS_TEST = 19, + MMC_SEND_TUNING_BLOCK = 21, SD_SET_BLOCK_COUNT = 23, SD_WRITE_SINGLE_BLOCK = 24, SD_WRITE_MULTIPLE_BLOCK = 25, @@ -278,6 +284,20 @@ enum sd_ocr_flag { /*!< VDD 3.4-3.5 */ }; +/** + * @brief MMC OCR bit flags + * + * bit flags present in MMC OCR response. Used to determine status and + * supported functions of MMC card. + */ +enum mmc_ocr_flag { + MMC_OCR_VDD170_195FLAG = BIT(7), + MMC_OCR_VDD20_26FLAG = 0x7F << 8, + MMC_OCR_VDD27_36FLAG = 0x1FF << 15, + MMC_OCR_SECTOR_MODE = BIT(30), + MMC_OCR_PWR_BUSY_FLAG = BIT(31) +}; + #define SDIO_OCR_IO_NUMBER_SHIFT (28U) /* Lower 24 bits hold SDIO I/O OCR */ #define SDIO_IO_OCR_MASK (0xFFFFFFU) @@ -397,7 +417,7 @@ enum sdhc_clock_speed { MMC_CLOCK_52MHZ = 52000000U, MMC_CLOCK_DDR52 = 52000000U, MMC_CLOCK_HS200 = 200000000U, - MMC_CLOCK_HS400 = 400000000U, + MMC_CLOCK_HS400 = 200000000U, /* Same clock freq as HS200, just DDR */ }; /** @@ -525,7 +545,6 @@ struct sd_csd { /*!< Maximum write current at VDD max [52:50] */ uint8_t dev_size_mul; /*!< Device size multiplier [49:47] */ - uint8_t erase_size; /*!< Erase sector size [45:39] */ uint8_t write_prtect_size; @@ -538,6 +557,120 @@ struct sd_csd { /*!< File format [11:10] */ }; +/** + * @brief MMC Maximum Frequency + * + * Max freq in MMC csd + */ +enum mmc_csd_freq { + MMC_MAXFREQ_100KHZ = 0U << 0U, + MMC_MAXFREQ_1MHZ = 1U << 0U, + MMC_MAXFREQ_10MHZ = 2U << 0U, + MMC_MAXFREQ_100MHZ = 3U << 0U, + MMC_MAXFREQ_MULT_10 = 1U << 3U, + MMC_MAXFREQ_MULT_12 = 2U << 3U, + MMC_MAXFREQ_MULT_13 = 3U << 3U, + MMC_MAXFREQ_MULT_15 = 4U << 3U, + MMC_MAXFREQ_MULT_20 = 5U << 3U, + MMC_MAXFREQ_MULT_26 = 6U << 3U, + MMC_MAXFREQ_MULT_30 = 7U << 3U, + MMC_MAXFREQ_MULT_35 = 8U << 3U, + MMC_MAXFREQ_MULT_40 = 9U << 3U, + MMC_MAXFREQ_MULT_45 = 0xAU << 3U, + MMC_MAXFREQ_MULT_52 = 0xBU << 3U, + MMC_MAXFREQ_MULT_55 = 0xCU << 3U, + MMC_MAXFREQ_MULT_60 = 0xDU << 3U, + MMC_MAXFREQ_MULT_70 = 0xEU << 3U, + MMC_MAXFREQ_MULT_80 = 0xFU << 3u +}; + +/** + * @brief MMC Timing Modes + * + * MMC Timing Mode, encoded in EXT_CSD + */ +enum mmc_timing_mode { + MMC_LEGACY_TIMING = 0U, + MMC_HS_TIMING = 1U, + MMC_HS200_TIMING = 2U, + MMC_HS400_TIMING = 3U +}; + +/** + * @brief MMC Driver Strengths + * + * Encoded in EXT_CSD + */ +enum mmc_driver_strengths { + mmc_driv_type0 = 0U, + mmc_driv_type1 = 1U, + mmc_driv_type2 = 2U, + mmc_driv_type3 = 3U, + mmc_driv_type4 = 4U +}; + + +/** + * @brief MMC Device Type + * + * Encoded in EXT_CSD + */ +struct mmc_device_type { + bool MMC_HS400_DDR_1200MV; + bool MMC_HS400_DDR_1800MV; + bool MMC_HS200_SDR_1200MV; + bool MMC_HS200_SDR_1800MV; + bool MMC_HS_DDR_1200MV; + bool MMC_HS_DDR_1800MV; + bool MMC_HS_52_DV; + bool MMC_HS_26_DV; +}; + +/** + * @brief CSD Revision + * + * Value of CSD rev in EXT_CSD + */ +enum mmc_ext_csd_rev { + MMC_5_1 = 8U, + MMC_5_0 = 7U, + MMC_4_5 = 6U, + MMC_4_4 = 5U, + MMC_4_3 = 3U, + MMC_4_2 = 2U, + MMC_4_1 = 1U, + MMC_4_0 = 0U +}; + +/** + * @brief MMC extended card specific data register + * + * Extended card specific data register. + * Contains additional additional data about MMC card. + */ +struct mmc_ext_csd { + uint32_t sec_count; + /*!< Sector Count [215:212] >*/ + uint8_t bus_width; + /*!< Bus Width Mode [183] >*/ + enum mmc_timing_mode hs_timing; + /*!< High Speed Timing Mode [185] >*/ + struct mmc_device_type device_type; + /*!< Device Type [196] >*/ + enum mmc_ext_csd_rev rev; + /*!< Extended CSD Revision [192] >*/ + uint8_t power_class; + /*!< Selected power class [187]>*/ + uint8_t mmc_driver_strengths; + /*!< Driver strengths [197] >*/ + uint8_t pwr_class_200MHZ_VCCQ195; + /*!< Power class information for HS200 at VCC!=1.95V [237] >*/ + uint8_t pwr_class_HS400; + /*!< Power class information for HS400 [253] >*/ + uint32_t cache_size; + /*!< Size of eMMC cache [252:249]>*/ +}; + /** * @brief SD card specific data flags * @@ -622,7 +755,7 @@ enum sd_spec_version { #define SDMMC_DEFAULT_BLOCK_SIZE (512U) - +#define MMC_EXT_CSD_BYTES 512 #ifdef __cplusplus }