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