/* * Copyright (C) 2017-2020 Alibaba Group Holding Limited */ /****************************************************************************** * @file drv/sdif.h * @brief Header File for SDIF Driver * @version V1.0 * @date 28. June 2020 * @model sdif ******************************************************************************/ #ifndef _DRV_SDIF_H_ #define _DRV_SDIF_H_ #include #include #ifdef __cplusplus extern "C" { #endif typedef void *sdif_handle_t; /*! @brief Construct a status code value from a group and code number. */ #define MAKE_STATUS(group, code) ((((group)*100) + (code))) /*! @brief Status group numbers. */ enum _status_groups { kStatusGroup_Generic = 0, /*!< Group number for generic status codes. */ kStatusGroup_SDMMC = 18, /*!< Group number for SDMMC status code */ kStatusGroup_SDIF = 59, /*!< Group number for SDIF status codes.*/ kStatusGroup_ApplicationRangeStart = 101, /*!< Starting number for application groups. */ }; /*! @brief Generic status return codes. */ enum _generic_status { kStatus_Success = MAKE_STATUS(kStatusGroup_Generic, 0), kStatus_Fail = MAKE_STATUS(kStatusGroup_Generic, 1), kStatus_ReadOnly = MAKE_STATUS(kStatusGroup_Generic, 2), kStatus_OutOfRange = MAKE_STATUS(kStatusGroup_Generic, 3), kStatus_InvalidArgument = MAKE_STATUS(kStatusGroup_Generic, 4), kStatus_Timeout = MAKE_STATUS(kStatusGroup_Generic, 5), kStatus_NoTransferInProgress = MAKE_STATUS(kStatusGroup_Generic, 6), }; /*! @brief Type used for all status and error return values. */ typedef int32_t status_t; /*! @brief Computes the number of elements in an array. */ #if !defined(ARRAY_SIZE) #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #endif /*! Macro to change a value to a given size aligned value */ #define SDK_SIZEALIGN(var, alignbytes) \ ((unsigned int)((var) + ((alignbytes)-1)) & (unsigned int)(~(unsigned int)((alignbytes)-1))) ///< #define assert(__e) ((void)0) /*! @name Min/max macros */ #if !defined(MIN) #define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif #if !defined(MAX) #define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif #define SDK_ALIGN(var, alignbytes) var static inline uint32_t cpu_to_dma(uint32_t addr) { return addr; } static inline uint32_t *ptr_cpu_to_dma(uint32_t *addr) { return (uint32_t *)cpu_to_dma((uint32_t)addr); } typedef enum { SDIF_ERROR_CMD_CRC_FAIL = (1), ///< Command response received (but CRC check failed) SDIF_ERROR_DATA_CRC_FAIL, ///< Data block sent/received (CRC check failed) SDIF_ERROR_CMD_RSP_TIMEOUT, ///< Command response timeout SDIF_ERROR_DATA_TIMEOUT, ///< Data timeout SDIF_ERROR_TX_UNDERRUN, ///< Transmit FIFO underrun SDIF_ERROR_RX_OVERRUN, ///< Receive FIFO overrun SDIF_ERROR_ADDR_MISALIGNED, ///< Misaligned address SDIF_ERROR_BLOCK_LEN_ERR, ///< Transferred block length is not allowed for the card or the number of transferred bytes does not match the block length SDIF_ERROR_ERASE_SEQ_ERR, ///< An error in the sequence of erase command occurs SDIF_ERROR_BAD_ERASE_PARAM, ///< An invalid selection for erase groups SDIF_ERROR_WRITE_PROT_VIOLATION, ///< Attempt to program a write protect block SDIF_ERROR_LOCK_UNLOCK_FAILED, ///< Sequence or password error has been detected in unlock command or if there was an attempt to access a locked card SDIF_ERROR_COM_CRC_FAILED, ///< CRC check of the previous command failed SDIF_ERROR_ILLEGAL_CMD, ///< Command is not legal for the card state SDIF_ERROR_CARD_ECC_FAILED, ///< Card internal ECC was applied but failed to correct the data SDIF_ERROR_CC_ERR, ///< Internal card controller error SDIF_ERROR_GENERAL_UNKNOWN_ERR, ///< General or unknown error SDIF_ERROR_STREAM_READ_UNDERRUN, ///< The card could not sustain data reading in stream rmode SDIF_ERROR_STREAM_WRITE_OVERRUN, ///< The card could not sustain data programming in stream mode SDIF_ERROR_CID_CSD_OVERWRITE, ///< CID/CSD overwrite error SDIF_ERROR_WP_ERASE_SKIP, ///< Only partial address space was erased SDIF_ERROR_CARD_ECC_DISABLED, ///< Command has been executed without using internal ECC SDIF_ERROR_ERASE_RESET, ///< Erase sequence was cleared before executing because an out SDIF_ERROR_AKE_SEQ_ERR, ///< Error in sequence of authentication SDIF_ERROR_INVALID_VOLTRANGE, ///< Error in case of invalid voltage range SDIF_ERROR_ADDR_OUT_OF_RANGE, ///< Error when addressed block is out of range SDIF_ERROR_REQUEST_NOT_APPLICABLE, ///< Error when command request is not applicable SDIF_ERROR_UNSUPPORTED_FEATURE, ///< Error when feature is not insupported } sdif_error_e; /* Host controller capabilities flag mask */ typedef enum { SDIF_SUPPORT_HIGH_SPEED = 0x1U, ///< Support high-speed SDIF_SUPPORT_DMA_SPEED = 0x2U, ///< Support DMA SDIF_SUPPORT_USPEND_RESUME = 0x4U, ///< Support suspend/resume SDIF_SUPPORT_V330 = 0x8U, ///< Support voltage 3.3V SDIF_SUPPORT_4BIT = 0x10U, ///< Support 4 bit mode SDIF_SUPPORT_8BIT = 0x20U, ///< Support 8 bit mode } sdif_capability_flag_e; /* \brief define the internal DMA mode */ typedef enum { SDIF_CHAIN_DMA_MODE = 0x01U, ///< one descriptor with one buffer,but one descriptor point to another SDIF_DUAL_DMA_MODE = 0x02U, ///< dual mode is one descriptor with two buffer } sdif_dma_mode_e; /* The command type */ typedef enum { SDIF_CARD_COMMAND_NORMAL = 0U, ///< Normal command SDIF_CARD_COMMAND_SUSPEND = 1U, ///< Suspend command SDIF_CARD_COMMAND_RESUME = 2U, ///< Resume command SDIF_CARD_COMMAND_ABORT = 3U, ///< Abort command } sdif_card_command_type_e; /* The command response type */ typedef enum { SDIF_CARD_RESPONSE_NONE = 0U, ///< Response type: none SDIF_CARD_RESPONSE_R1 = 1U, ///< Response type: R1 SDIF_CARD_RESPONSE_R1b = 2U, ///< Response type: R1b SDIF_CARD_RESPONSE_R2 = 3U, ///< Response type: R2 SDIF_CARD_RESPONSE_R3 = 4U, ///< Response type: R3 SDIF_CARD_RESPONSE_R4 = 5U, ///< Response type: R4 SDIF_CARD_RESPONSE_R5 = 6U, ///< Response type: R5 SDIF_CARD_RESPONSE_R5b = 7U, ///< Response type: R5b SDIF_CARD_RESPONSE_R6 = 8U, ///< Response type: R6 SDIF_CARD_RESPONSE_R7 = 9U, ///< Response type: R7 } sdif_card_response_type_e; /* \brief define the card bus width type */ typedef enum { SDIF_BUS_1BIT_WIDTH = 0U, ///< 1bit bus width, 1bit mode and 4bit mode share one register bit SDIF_BUS_4BIT_WIDTH = 1U, ///< 4bit mode mask SDIF_BUS_8BIT_WIDTH = 2U, ///< support 8 bit mode } sdif_bus_width_e; /* \brief Defines the internal DMA configure structure. */ typedef struct { bool enable_fix_burst_len; ///< fix burst len enable/disable flag,When set, the AHB will ///< use only SINGLE, INCR4, INCR8 or INCR16 during start of ///< normal burst transfers. When reset, the AHB will use SINGLE ///< and INCR burst transfer operations sdif_dma_mode_e mode; ///< define the DMA mode */ uint32_t *dma_des_buffer_start_addr; ///< internal DMA descriptor start address uint32_t dma_des_buffer_len; ///< internal DMA buffer descriptor buffer len ,user need to pay attention to the ///< dma descriptor buffer length if it is bigger enough for your transfer uint8_t dma_dws_skip_len; ///< define the descriptor skip length ,the length between two descriptor ///< this field is special for dual DMA mode } sdif_dma_config_t; /* \brief sdif callback functions. */ typedef struct { void (*card_inserted)(uint32_t idx, void *user_data); ///< card insert call back void (*card_removed)(uint32_t idx, void *user_data); ///< card remove call back void (*sdif_interrupt)(uint32_t idx, void *user_data); ///< SDIF card interrupt occurs void (*dma_des_unavailable)(uint32_t idx, void *user_data);///< DMA descriptor unavailable void (*command_reload)(uint32_t idx, void *user_data); ///< command buffer full,need re-load void (*transfer_complete)(uint32_t idx, void *state, int32_t status, void *user_data); ///