1 /* 2 * Copyright (C) 2017-2019 Alibaba Group Holding Limited 3 */ 4 5 /****************************************************************************** 6 * @file drv_sdif.h 7 * @brief head file for sd/mmc sdio 8 * @version V1.0 9 * @date 28. June 2018 10 * @model sdif 11 ******************************************************************************/ 12 #ifndef _CSI_SDIF_H_ 13 #define _CSI_SDIF_H_ 14 15 16 #include <stdbool.h> 17 #include <drv/common.h> 18 19 #ifdef __cplusplus 20 extern "C" { 21 #endif 22 typedef void *sdif_handle_t; 23 24 typedef enum { 25 SDIF_ERROR_CMD_CRC_FAIL = (DRV_ERROR_SPECIFIC + 1), ///< Command response received (but CRC check failed) 26 SDIF_ERROR_DATA_CRC_FAIL, ///< Data block sent/received (CRC check failed) 27 SDIF_ERROR_CMD_RSP_TIMEOUT, ///< Command response timeout 28 SDIF_ERROR_DATA_TIMEOUT, ///< Data timeout 29 SDIF_ERROR_TX_UNDERRUN, ///< Transmit FIFO underrun 30 SDIF_ERROR_RX_OVERRUN, ///< Receive FIFO overrun 31 SDIF_ERROR_ADDR_MISALIGNED, ///< Misaligned address 32 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 33 SDIF_ERROR_ERASE_SEQ_ERR, ///< An error in the sequence of erase command occurs 34 SDIF_ERROR_BAD_ERASE_PARAM, ///< An invalid selection for erase groups 35 SDIF_ERROR_WRITE_PROT_VIOLATION, ///< Attempt to program a write protect block 36 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 37 SDIF_ERROR_COM_CRC_FAILED, ///< CRC check of the previous command failed 38 SDIF_ERROR_ILLEGAL_CMD, ///< Command is not legal for the card state 39 SDIF_ERROR_CARD_ECC_FAILED, ///< Card internal ECC was applied but failed to correct the data 40 SDIF_ERROR_CC_ERR, ///< Internal card controller error 41 SDIF_ERROR_GENERAL_UNKNOWN_ERR, ///< General or unknown error 42 SDIF_ERROR_STREAM_READ_UNDERRUN, ///< The card could not sustain data reading in stream rmode 43 SDIF_ERROR_STREAM_WRITE_OVERRUN, ///< The card could not sustain data programming in stream mode 44 SDIF_ERROR_CID_CSD_OVERWRITE, ///< CID/CSD overwrite error 45 SDIF_ERROR_WP_ERASE_SKIP, ///< Only partial address space was erased 46 SDIF_ERROR_CARD_ECC_DISABLED, ///< Command has been executed without using internal ECC 47 SDIF_ERROR_ERASE_RESET, ///< Erase sequence was cleared before executing because an out 48 SDIF_ERROR_AKE_SEQ_ERR, ///< Error in sequence of authentication 49 SDIF_ERROR_INVALID_VOLTRANGE, ///< Error in case of invalid voltage range 50 SDIF_ERROR_ADDR_OUT_OF_RANGE, ///< Error when addressed block is out of range 51 SDIF_ERROR_REQUEST_NOT_APPLICABLE, ///< Error when command request is not applicable 52 SDIF_ERROR_UNSUPPORTED_FEATURE, ///< Error when feature is not insupported 53 } sdif_error_e; 54 55 /* Host controller capabilities flag mask */ 56 typedef enum { 57 SDIF_SUPPORT_HIGH_SPEED = 0x1U, ///< Support high-speed 58 SDIF_SUPPORT_DMA_SPEED = 0x2U, ///< Support DMA 59 SDIF_SUPPORT_USPEND_RESUME = 0x4U, ///< Support suspend/resume 60 SDIF_SUPPORT_V330 = 0x8U, ///< Support voltage 3.3V 61 SDIF_SUPPORT_4BIT = 0x10U, ///< Support 4 bit mode 62 SDIF_SUPPORT_8BIT = 0x20U, ///< Support 8 bit mode 63 } sdif_capability_flag_e; 64 65 /* \brief define the internal DMA mode */ 66 typedef enum { 67 SDIF_CHAIN_DMA_MODE = 0x01U, ///< one descriptor with one buffer,but one descriptor point to another 68 SDIF_DUAL_DMA_MODE = 0x02U, ///< dual mode is one descriptor with two buffer 69 } sdif_dma_mode_e; 70 71 /* The command type */ 72 typedef enum { 73 SDIF_CARD_COMMAND_NORMAL = 0U, ///< Normal command 74 SDIF_CARD_COMMAND_SUSPEND = 1U, ///< Suspend command 75 SDIF_CARD_COMMAND_RESUME = 2U, ///< Resume command 76 SDIF_CARD_COMMAND_ABORT = 3U, ///< Abort command 77 } sdif_card_command_type_e; 78 79 /* The command response type */ 80 typedef enum { 81 SDIF_CARD_RESPONSE_NONE = 0U, ///< Response type: none 82 SDIF_CARD_RESPONSE_R1 = 1U, ///< Response type: R1 83 SDIF_CARD_RESPONSE_R1b = 2U, ///< Response type: R1b 84 SDIF_CARD_RESPONSE_R2 = 3U, ///< Response type: R2 85 SDIF_CARD_RESPONSE_R3 = 4U, ///< Response type: R3 86 SDIF_CARD_RESPONSE_R4 = 5U, ///< Response type: R4 87 SDIF_CARD_RESPONSE_R5 = 6U, ///< Response type: R5 88 SDIF_CARD_RESPONSE_R5b = 7U, ///< Response type: R5b 89 SDIF_CARD_RESPONSE_R6 = 8U, ///< Response type: R6 90 SDIF_CARD_RESPONSE_R7 = 9U, ///< Response type: R7 91 } sdif_card_response_type_e; 92 93 /* \brief define the card bus width type */ 94 typedef enum { 95 SDIF_BUS_1BIT_WIDTH = 0U, ///< 1bit bus width, 1bit mode and 4bit mode share one register bit 96 SDIF_BUS_4BIT_WIDTH = 1U, ///< 4bit mode mask 97 SDIF_BUS_8BIT_WIDTH = 2U, ///< support 8 bit mode 98 } sdif_bus_width_e; 99 100 /* \brief Defines the internal DMA configure structure. */ 101 typedef struct { 102 bool enable_fix_burst_len; ///< fix burst len enable/disable flag,When set, the AHB will 103 /// use only SINGLE, INCR4, INCR8 or INCR16 during start of 104 /// normal burst transfers. When reset, the AHB will use SINGLE 105 /// and INCR burst transfer operations 106 107 sdif_dma_mode_e mode; ///< define the DMA mode */ 108 109 110 uint32_t *dma_des_buffer_start_addr; ///< internal DMA descriptor start address 111 uint32_t dma_des_buffer_len; /// internal DMA buffer descriptor buffer len ,user need to pay attention to the 112 /// dma descriptor buffer length if it is bigger enough for your transfer 113 uint8_t dma_dws_skip_len; ///< define the descriptor skip length ,the length between two descriptor 114 /// this field is special for dual DMA mode 115 } sdif_dma_config_t; 116 117 /* \brief sdif callback functions. */ 118 typedef struct { 119 void (*card_inserted)(uint32_t idx, void *user_data); ///< card insert call back 120 void (*card_removed)(uint32_t idx, void *user_data); ///< card remove call back 121 void (*sdif_interrupt)(uint32_t idx, void *user_data); ///< SDIF card interrupt occurs 122 void (*dma_des_unavailable)(uint32_t idx, void *user_data);///< DMA descriptor unavailable 123 void (*command_reload)(uint32_t idx, void *user_data); ///< command buffer full,need re-load 124 void (*transfer_complete)(uint32_t idx, 125 void *state, 126 int32_t status, 127 void *user_data); ///<Transfer complete callback 128 } sdif_callback_t; 129 130 /* Card data descriptor */ 131 typedef struct { 132 bool stream_transfer; ///< indicate this is a stream data transfer command 133 bool enable_auto_command12; ///< indicate if auto stop will send when data transfer over 134 bool enable_ignore_error; ///< indicate if enable ignore error when transfer data 135 136 uint32_t block_size; ///< Block size, take care when configure this parameter 137 uint32_t block_count; ///< Block count 138 uint32_t *rx_date_buffer; ///< data buffer to receive 139 const uint32_t *tx_data_buffer; ///< data buffer to transfer 140 } sdif_data_t; 141 142 /* Card command descriptor */ 143 typedef struct { 144 uint32_t index; ///< Command index 145 uint32_t argument; ///< Command argument 146 uint32_t response[4U]; ///< Response for this command 147 uint32_t type; ///< define the command type 148 uint32_t response_type; ///< Command response type 149 uint32_t flags; ///< Cmd flags 150 uint32_t resopnse_error_flags; ///< response error flags, need to check the flags when receive the cmd response 151 } sdif_command_t; 152 /* Transfer state */ 153 typedef struct { 154 sdif_data_t *data; ///< Data to transfer 155 sdif_command_t *command; ///< Command to send 156 } sdif_transfer_t; 157 158 /* Data structure to initialize the sdif */ 159 typedef struct { 160 uint8_t response_timeout; ///< command response timeout value 161 uint32_t card_det_debounce_clock; ///< define the debounce clock count which will used in 162 /// card detect logic,typical value is 5-25ms 163 uint32_t endian_mode; ///< define endian mode ,this field is not used in this 164 /// module actually, keep for compatible with middleware 165 uint32_t data_timeout; ///< data timeout value 166 } sdif_config_t; 167 168 /* 169 * \brief SDIF capability information. 170 * Defines a structure to get the capability information of SDIF. 171 */ 172 typedef struct { 173 uint32_t sd_version; ///< support SD card/SDIF version 174 uint32_t mmc_version; ///< support emmc card version 175 uint32_t max_block_length; ///< Maximum block length united as byte 176 uint32_t max_block_count; ///< Maximum byte count can be transfered 177 uint32_t flags; ///< Capability flags to indicate the support information 178 } sdif_capability_t; 179 180 /** 181 \brief Initializes the SDIF according to the specified 182 \param[in] idx sdif index 183 \param[in] callback callback Structure pointer to contain all callback functions. 184 \param[in] user_data user_data Callback function parameter. 185 \return sdif handle if success 186 */ 187 sdif_handle_t drv_sdif_initialize(uint32_t idx, sdif_callback_t *callback, void *user_data); 188 189 /** 190 \brief De-initialize SD Interface. stops operation and releases the software resources used by the interface 191 \param[in] handle SDIF handle to operate. 192 */ 193 void drv_sdif_uninitialize(sdif_handle_t handle); 194 195 /** 196 \brief Initializes the SDIF config 197 \param[in] idx sdif index 198 \param[in] config sdif config descriptor \ref sdif_config_t 199 */ 200 void drv_sdif_config(sdif_handle_t handle, sdif_config_t *config); 201 202 /** 203 \brief Get driver capabilities. 204 \param[in] handle SDIF handle to operate. 205 \param[out] capability SDIF capability information \ref sdif_capabilities_t 206 */ 207 void drv_sdif_get_capabilities(sdif_handle_t handle, sdif_capability_t *capability); 208 209 /** 210 \brief control sdif power. 211 \param[in] handle SDIF handle to operate. 212 \param[in] state power state.\ref csi_power_stat_e. 213 \return error code 214 */ 215 int32_t drv_sdif_power_control(sdif_handle_t handle, csi_power_stat_e state); 216 217 /** 218 \brief send command to the card 219 \param[in] handle SDIF handle to operate. 220 \param[in] cmd command configuration collection 221 \param[in] retries total number of tries 222 \return error code 223 */ 224 int32_t drv_sdif_send_command(sdif_handle_t handle, sdif_command_t *cmd, uint32_t retries); 225 226 /** 227 \brief SDIF transfer function data/cmd in a non-blocking way 228 this API should be use in interrupt mode, when use this API user 229 must call drv_sdif_create_state first, all status check through 230 interrupt 231 \param[in] handle SDIF handle to operate. 232 \param[in] dma_config DMA config structure \ref sdif_dma_config_t 233 This parameter can be config as: 234 1. NULL 235 In this condition, polling transfer mode is selected 236 2. avaliable DMA config 237 In this condition, DMA transfer mode is selected 238 \param[in] transfer sdif transfer configuration collection. \ref sdif_transfer_t 239 \return error code 240 */ 241 int32_t drv_sdif_transfer(sdif_handle_t handle, sdif_dma_config_t *dma_config, sdif_transfer_t *transfer); 242 243 /** 244 \brief Poll-wait for the response to the last command to be ready. This 245 function should be called even after sending commands that have no 246 response (such as CMD0) to make sure that the hardware is ready to 247 receive the next command. 248 \param[in] handle SDIF handle to operate. 249 \param[in] cmd : The command that was sent. See 32-bit command definitions above. 250 */ 251 void drv_sdif_transfer_abort(sdif_handle_t handle); 252 253 /** 254 \brief Called after change in Bus width has been selected (via ACMD6). Most 255 controllers will need to perform some special operations to work 256 correctly in the new bus mode. 257 \param[in] handle SDIF handle to operate. 258 \param[in] bus_width wide bus mode \ref sdif_bus_width_e. 259 */ 260 void drv_sdif_bus_width(sdif_handle_t handle, sdif_bus_width_e bus_width); 261 262 /** 263 \brief Set SDIF clocking 264 \param[in] handle SDIF handle to operate. 265 \param[in] target_hz card bus clock frequency united in Hz. 266 \return code error 267 */ 268 uint32_t drv_sdif_set_clock(sdif_handle_t handle, uint32_t target_hz); 269 270 /** 271 \brief Get sdif handle 272 \param[in] idx sdif index 273 \return sdif handle 274 */ 275 sdif_handle_t drv_sdif_get_handle(uint32_t idx); 276 277 /** 278 \brief Get sdif index 279 \param[out] handle SDIF handle to operate. 280 \return sdif index 281 */ 282 uint32_t drv_sdif_get_idx(sdif_handle_t handle); 283 284 #ifdef __cplusplus 285 } 286 #endif 287 288 #endif /* _CSI_SDIF_H_ */ 289 290