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