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