1 /***************************************************************************//**
2 * \file cyhal_sdhc.h
3 *
4 * \brief
5 * Provides a high level interface for interacting with the Infineon SDHC.
6 * This interface abstracts out the chip specific details. If any chip specific
7 * functionality is necessary, or performance is critical the low level functions
8 * can be used directly.
9 *
10 ********************************************************************************
11 * \copyright
12 * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
13 * an affiliate of Cypress Semiconductor Corporation
14 *
15 * SPDX-License-Identifier: Apache-2.0
16 *
17 * Licensed under the Apache License, Version 2.0 (the "License");
18 * you may not use this file except in compliance with the License.
19 * You may obtain a copy of the License at
20 *
21 *     http://www.apache.org/licenses/LICENSE-2.0
22 *
23 * Unless required by applicable law or agreed to in writing, software
24 * distributed under the License is distributed on an "AS IS" BASIS,
25 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26 * See the License for the specific language governing permissions and
27 * limitations under the License.
28 *******************************************************************************/
29 
30 /**
31 * \addtogroup group_hal_sdhc SDHC (SD Host Controller)
32 * \ingroup group_hal
33 * \{
34 * High level interface to the Secure Digital Host Controller (SDHC).
35 *
36 * The SDHC driver allows data to be read from and written to an SD Card using the SDHC block.
37 * The data is transferred in blocks with a block size of 512 bytes.
38 *
39 * \section subsection_sdhc_features Features
40 * * Supports the 4-bit interface
41 * * Supports Ultra High Speed (UHS-I) mode
42 * * Supports Default Speed (DS), High Speed (HS), SDR12, SDR25 and SDR50 speed modes
43 *
44 * \section subsection_sdhc_quickstart Quick Start
45 * Initialize SDHC by using \ref cyhal_sdhc_init by selecting the pins according to the target device used.
46 * Specify the SDHC configuration using the configuration structure (const \ref cyhal_sdhc_config_t * config). <br>
47 * See \ref subsection_sdhc_snippet_1
48 *
49 * \section subsection_sdhc_code_snippets Code Snippets
50 *
51 * \subsection subsection_sdhc_snippet_1 Snippet 1: SDHC Initialization and configuration
52 * The following snippet is used to initialize the SDHC block. SDHC object - \ref cyhal_sdhc_t,
53 * SDHC card configuration structure (const \ref cyhal_sdhc_config_t * config). The pins connected to the SDHC block
54 * needs to be provided to the \ref cyhal_sdhc_init function.
55 * \snippet hal_sdhc.c snippet_cyhal_sdhc_init
56 *
57 * \subsection subsection_sdhc_snippet_2 Snippet 2: Reading a block of data from an SD Card
58 * The following snippet reads a block of data from the SD Card.
59 * \snippet hal_sdhc.c snippet_cyhal_sdhc_read
60 
61 * \subsection subsection_sdhc_snippet_3 Snippet 3: Writing a block of data to an SD Card
62 * The following snippet writes a block of data to the SD Card.
63 * \snippet hal_sdhc.c snippet_cyhal_sdhc_write
64 
65 */
66 
67 #pragma once
68 
69 #include <stdint.h>
70 #include <stdbool.h>
71 #include "cy_result.h"
72 #include "cyhal_hw_types.h"
73 
74 #if defined(__cplusplus)
75 extern "C" {
76 #endif
77 
78 /*******************************************************************************
79 *       Defines
80 *******************************************************************************/
81 
82 /** \addtogroup group_hal_results_sdhc SDHC HAL Results
83  *  SDHC specific return codes
84  *  \ingroup group_hal_results
85  *  \{ *//**
86  */
87 
88 /** Pin related Error. */
89 #define CYHAL_SDHC_RSLT_ERR_PIN                         \
90     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_SDHC, 0))
91 /** Requested feature is not supported on this hardware. */
92 #define CYHAL_SDHC_RSLT_ERR_UNSUPPORTED                 \
93     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_SDHC, 1))
94 /** Timeout during waiting for erase complete. */
95 #define CYHAL_SDHC_RSLT_ERR_ERASE_CMPLT_TIMEOUT         \
96     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_SDHC, 2))
97 /** Block count cannot be retrieved. */
98 #define CYHAL_SDHC_RSLT_ERR_BLOCK_COUNT_GET_FAILURE     \
99     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_SDHC, 3))
100 /** Cannot set desired SD bus frequency. */
101 #define CYHAL_SDHC_RSLT_ERR_SET_FREQ                    \
102     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_SDHC, 4))
103 /** Incorrect function parameter. */
104 #define CYHAL_SDHC_RSLT_ERR_WRONG_PARAM                 \
105     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_SDHC, 5))
106 /** Error occured during I/O voltage switch sequence. */
107 #define CYHAL_SDHC_RSLT_ERR_IO_VOLT_SWITCH_SEQ          \
108     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_SDHC, 6))
109 /** Cannot configure data timeout. */
110 #define CYHAL_SDHC_RSLT_ERR_TOUT_CFG                    \
111     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_SDHC, 7))
112 /** Cannot make changes in user provided clock configuration or provided clock is incorrect. */
113 #define CYHAL_SDHC_RSLT_ERR_CLOCK                       \
114     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_SDHC, 8))
115 
116 /**
117  * \}
118  */
119 
120 /*******************************************************************************
121 *       Enumerations
122 *******************************************************************************/
123 
124 /** Card types */
125 typedef enum
126 {
127     CYHAL_SDHC_SD,                              //!< Secure Digital card
128     CYHAL_SDHC_SDIO,                            //!< SD Input Output card
129     CYHAL_SDHC_EMMC,                            //!< Embedded Multimedia card
130     CYHAL_SDHC_COMBO,                           //!< Combo Card (SD + SDIO)
131     CYHAL_SDHC_UNUSABLE,                        //!< Unusable card or unsupported type
132     CYHAL_SDHC_NOT_EMMC,                        //!< Not an eMMC card
133 } cyhal_sdhc_card_type_t;
134 
135 /** SDHC interrupt triggers */
136 typedef enum {
137     CYHAL_SDHC_CMD_COMPLETE         = 0x00001,  //!< Command Complete
138     CYHAL_SDHC_XFER_COMPLETE        = 0x00002,  //!< Host read/write transfer is complete
139     CYHAL_SDHC_BGAP_EVENT           = 0x00004,  //!< This bit is set when both read/write transaction is stopped at the block gap
140     CYHAL_SDHC_DMA_INTERRUPT        = 0x00008,  //!< Host controller detects an SDMA Buffer Boundary during transfer
141     CYHAL_SDHC_BUF_WR_READY         = 0x00010,  //!< This bit is set if the Buffer Write Enable changes from 0 to 1
142     CYHAL_SDHC_BUF_RD_READY         = 0x00020,  //!< This bit is set if the Buffer Read Enable changes from 0 to 1
143     CYHAL_SDHC_CARD_INSERTION       = 0x00040,  //!< This bit is set if the Card Inserted in the Present State register changes from 0 to 1.
144     CYHAL_SDHC_CARD_REMOVAL         = 0x00080,  //!< This bit is set if the Card Inserted in the Present State register changes from 1 to 0.
145     CYHAL_SDHC_INT_A                = 0x00200,
146     CYHAL_SDHC_INT_B                = 0x00400,
147     CYHAL_SDHC_INT_C                = 0x00800,
148     CYHAL_SDHC_RE_TUNE_EVENT        = 0x01000,  //!< This bit is set if the Re-Tuning Request changes from 0 to 1
149     CYHAL_SDHC_FX_EVENT             = 0x02000,  //!< This status is set when R[14] of response register is set to 1
150     CYHAL_SDHC_CQE_EVENT            = 0x04000,  //!< This status is set if Command Queuing/Crypto event has occurred
151     CYHAL_SDHC_ERR_INTERRUPT        = 0x08000,  //!< If any of the bits in the Error Interrupt Status register are set
152     CYHAL_SDHC_ALL_INTERRUPTS       = 0x0FEFF,  //!< Is used to enable/disable all interrupts
153 } cyhal_sdhc_event_t;
154 
155 /** I/O voltage levels */
156 typedef enum
157 {
158     CYHAL_SDHC_IO_VOLTAGE_3_3V                  = 0U,   //!< I/O voltage is 3.3V.
159     CYHAL_SDHC_IO_VOLTAGE_1_8V                  = 1U    //!< I/O voltage is 1.8V.
160 } cyhal_sdhc_io_voltage_t;
161 
162 /** SDHC I/O voltage select principle */
163 typedef enum
164 {
165     CYHAL_SDHC_IO_VOLT_ACTION_NEGOTIATE         = 0U,   //!< (Recommended) HAL driver performs all steps, needed for switching I/O bus voltage to certain level: sends needed commands to prepare card, changes level of io_volt_sel pin and performs switching sequence according to SD specification.
166     CYHAL_SDHC_IO_VOLT_ACTION_SWITCH_SEQ_ONLY   = 1U,   //!< HAL driver performs switching sequence (if voltage is being switched to 1.8V) and changes io_volt_sel pin level accordingly. No commands are being send to the card in this mode.
167     CYHAL_SDHC_IO_VOLT_ACTION_NONE              = 2U,   //!< I/O voltage is changed by changing io_volt_sel pin's level. No commands are being send to the card in this mode.
168 } cyhal_sdhc_io_volt_action_type_t;
169 
170 /** SDHC response types */
171 typedef enum
172 {
173     CYHAL_SDHC_RESPONSE_NONE        = 0U,       //!< No Response.
174     CYHAL_SDHC_RESPONSE_LEN_136     = 1U,       //!< Response Length 136.
175     CYHAL_SDHC_RESPONSE_LEN_48      = 2U,       //!< Response Length 48.
176     CYHAL_SDHC_RESPONSE_LEN_48B     = 3U        //!< Response Length 48. Check Busy after response.
177 } cyhal_sdhc_cmd_response_type_t;
178 
179 /** SDHC auto command enable selection. */
180 typedef enum
181 {
182     CYHAL_SDHC_AUTO_CMD_NONE        = 0U,       //!< Auto command disable.
183     CYHAL_SDHC_AUTO_CMD_12          = 1U,       //!< Auto command 12 enable.
184     CYHAL_SDHC_AUTO_CMD_23          = 2U,       //!< Auto command 23 enable.
185     CYHAL_SDHC_AUTO_CMD_AUTO        = 3U        //!< Auto command Auto enable.
186 } cyhal_sdhc_auto_cmd_t;
187 
188 /** SDHC command types */
189 typedef enum
190 {
191     CYHAL_SDHC_CMD_NORMAL           = 0U,       //!< Other commands.
192     CYHAL_SDHC_CMD_SUSPEND          = 1U,       //!< CMD52 for writing "Bus Suspend" in CCCR.
193     CYHAL_SDHC_CMD_RESUME           = 2U,       //!< CMD52 for writing "Function Select" in CCCR.
194     CYHAL_SDHC_CMD_ABORT            = 3U        //!< CMD12, CMD52 for writing "I/O Abort" in CCCR.
195 } cyhal_sdhc_cmd_type_t;
196 
197 /** SDHC command error states */
198 typedef enum
199 {
200     /** Last operation did not cause any error status. */
201     CYHAL_SDHC_NO_ERR               = 0x0000U,
202     /** Command timeout error. In SD/eMMC Mode, this event is set only if no response is returned
203     * within 64 SD clock cycles from the end bit of the command. If the Host Controller detects a CMD line conflict,
204     * along with Command CRC Error bit, this event is set to 1, without waiting for 64 SD/eMMC card clock cycles. */
205     CYHAL_SDHC_CMD_TOUT_ERR         = 0x0001U,
206     /** Command CRC error. A Command CRC Error is generated in SD/eMMC mode when:
207     * 1. A response is returned and the Command Timeout Error is set to 0 (indicating no timeout),
208     * this bit is set to 1 when detecting a CRC error in the command response.
209     * 2. The Host Controller detects a CMD line conflict by monitoring the CMD line when a command is issued. If
210     * the Host Controller drives the CMD line to level 1, but detects level 0 on the CMD line at the next SD clock
211     * edge, then the Host Controller aborts the command (stop driving CMD line) and sets this bit to 1. The Command
212     * Timeout Error is also set to 1 to distinguish a CMD line conflict. */
213     CYHAL_SDHC_CMD_CRC_ERR          = 0x0002U,
214     /** Command End Bit error. This bit is set after detecting that the end bit of a command response is 0 in SD/eMMC mode. */
215     CYHAL_SDHC_CMD_END_BIT_ERR      = 0x0004U,
216     /** Command Index error. This bit is set if a Command Index error occurs in the command response in SD/eMMC mode. */
217     CYHAL_SDHC_CMD_IDX_ERR          = 0x0008U,
218     /** Data Timeout error. This bit is set in SD/eMMC mode when detecting one of the following timeout conditions:
219     * *  Busy timeout for R1b, R5b type
220     * *  Busy timeout after Write CRC status
221     * *  Write CRC Status timeout
222     * *  Read Data timeout. */
223     CYHAL_SDHC_DATA_TOUT_ERR        = 0x0010U,
224     /** Data CRC error. This error occurs in SD/eMMC mode after detecting a CRC error while transferring read data
225     * that uses the DAT line, detecting the Write CRC status having a value other than 010 or when writing a CRC status timeout. */
226     CYHAL_SDHC_DATA_CRC_ERR         = 0x0020U,
227     /** Data End Bit error. This error occurs in SD/eMMC mode either when detecting 0 at the end bit position of read
228     * data that uses the DAT line or at the end bit position of the CRC status. */
229     CYHAL_SDHC_DATA_END_BIT_ERR     = 0x0040U,
230     /** Current Limit error. */
231     CYHAL_SDHC_CUR_LMT_ERR          = 0x0080U,
232     /** Auto CMD error. This error status is used by Auto CMD12 and Auto CMD23 in SD/eMMC mode. This bit is set after
233     * detecting that any of the bits D00 to D05 in the Auto CMD Error Status register has changed from 0 to 1. D07 is
234     * effective in case for Auto CMD12. The Auto CMD Error Status register is valid while this bit is set to 1 and may
235     * be cleared by clearing this bit. */
236     CYHAL_SDHC_AUTO_CMD_ERR         = 0x0100U,
237     /** ADMA error. This bit is set when the Host Controller detects an error during an ADMA-based data transfer.
238     * The possible reasons for an error:
239     * * An error response is received from the System bus;
240     * * ADMA3, ADMA2 Descriptors are invalid;
241     * * CQE Task or Transfer descriptors are invalid.
242     * When an error occurs, the state of the ADMA is saved in the ADMA Error Status register. */
243     CYHAL_SDHC_ADMA_ERR             = 0x0200U,
244     /** Tuning error. */
245     CYHAL_SDHC_TUNNING_ERR          = 0x0400U,
246     /** Response error. Host Controller Version 4.00 supports the response error check function to avoid overhead of
247     * the response error check by Host Driver during DMA execution. If the Response Error Check Enable is set to 1 in
248     * the Transfer Mode register, the Host Controller checks R1 or R5 response. If an error is detected in a response,
249     * this bit is set to 1. This is applicable in SD/eMMC mode. */
250     CYHAL_SDHC_RESP_ERR             = 0x0800U,
251     /** Boot Acknowledgement error. This bit is set when there is a timeout for boot acknowledgement or after detecting
252     * the boot ACK status having a value other than 010. This is applicable only when boot acknowledgement is expected in eMMC mode. */
253     CYHAL_SDHC_BOOT_ACK_ERR         = 0x1000U
254 } cyhal_sdhc_error_type_t;
255 
256 /*******************************************************************************
257 *       Typedefs
258 *******************************************************************************/
259 
260 /** Handler for SDHC interrupts */
261 typedef void (*cyhal_sdhc_event_callback_t)(void *callback_arg, cyhal_sdhc_event_t event);
262 
263 /*******************************************************************************
264 *       Data Structures
265 *******************************************************************************/
266 
267 /** Defines configuration options for the SDHC block */
268 typedef struct
269 {
270     bool                            enableLedControl;               //!< Drive one IO to indicate when the card is being accessed
271     bool                            lowVoltageSignaling;            //!< Whether 1.8V signaling is supported
272     bool                            isEmmc;                         //!< true if eMMC card, otherwise false
273     uint8_t                         busWidth;                       //!< The desired bus width, 1-bit, 4-bit, 8-bit
274 } cyhal_sdhc_config_t;
275 
276 /** Defines data configuration */
277 typedef struct
278 {
279     uint32_t*                       data_ptr;                        //!< The pointer to data for send/receive. Data will be transfered using DMA, which will be configured automaticaly by SDHC HAL driver.
280     uint32_t                        block_size;                      //!< The size of the data block.
281     uint32_t                        number_of_blocks;                //!< The number of blocks with size block_size to send.
282     cyhal_sdhc_auto_cmd_t           auto_command;                    //!< Selects which auto commands are used if any.
283     bool                            is_read;                         //!< true = Read from the card, false = Write to the card.
284 } cyhal_sdhc_data_config_t;
285 
286 /** Defines command configuration for \ref cyhal_sdhc_send_cmd function */
287 typedef struct
288 {
289     uint32_t                        command_index;                   //!< The index of the command.
290     uint32_t                        command_argument;                //!< The argument for the command.
291     bool                            enable_crc_check;                //!< Enables the CRC check on the response.
292     cyhal_sdhc_cmd_response_type_t  response_type;                   //!< The response type.
293     bool                            enable_idx_check;                //!< Checks the index of the response.
294     cyhal_sdhc_cmd_type_t           command_type;                    //!< The command type.
295     cyhal_sdhc_data_config_t        *data_config;                    //!< Data transfer configuration, defined in \ref cyhal_sdhc_data_config_t. Should be NULL if data transfer is not expected for provided command.
296 } cyhal_sdhc_cmd_config_t;
297 
298 /*******************************************************************************
299 *       Functions
300 *******************************************************************************/
301 
302 /** Initialize SDHC driver and corresponding hardware.
303  *
304  * @param[out] obj                  Pointer to an SDHC object. The caller must allocate the memory for this object but
305  *  the init function will initialize its contents.
306  * @param[in]  config               The card configuration object
307  * @param[out] clk                  The pin connected to the clk signal
308  * @param[in]  cmd                  The pin connected to the command signal
309  * @param[in]  data0                The pin connected to the data0 signal
310  * @param[in]  data1                The pin connected to the data1 signal. This pin can be NC if bus width is 1-bit.
311  * @param[in]  data2                The pin connected to the data2 signal. This pin can be NC if bus width is 1-bit.
312  * @param[in]  data3                The pin connected to the data3 signal. This pin can be NC if bus width is 1-bit.
313  * @param[in]  data4                The pin connected to the data4 signal. This pin can be NC if bus width is less than 8-bit.
314  * @param[in]  data5                The pin connected to the data5 signal. This pin can be NC if bus width is less than 8-bit.
315  * @param[in]  data6                The pin connected to the data6 signal. This pin can be NC if bus width is less than 8-bit.
316  * @param[in]  data7                The pin connected to the data7 signal. This pin can be NC if bus width is less than 8-bit.
317  * @param[in]  card_detect          The pin connected to the card_detect signal
318  *  Card is considered as inserted if card_detect pin in low state.
319  *  This pin can be NC.
320  * @param[out] io_volt_sel          The pin connected to the io_volt_sel signal. This pin changes the logic level on the
321  *  sd_io_volt_sel line. It assumes that this line is used to control a regulator connected to the VDDIO of the MCU.
322  *  This regulator allows for switching between the 3.3V and 1.8V signaling. High level on the pin stands for
323  *  1.8V signaling, while low - for 3.3V.
324  *  This pin can be NC.
325  * @param[out] card_pwr_en          The pin connected to the card_pwr_en signal This pin can be used to enable a voltage
326  *  regulator used to power the card. High level on the pin - card is powered. Low - card is not powered.
327  *  This pin can be NC.
328  * @param[in]  card_mech_write_prot The pin connected to the card_mech_write_prot signal This pin is used for card
329  *  mechanical write protect checking.
330  *  If pin in high state - card is mechanically write protected, if in low state - card is not mechanically write
331  *  protected.
332  *  \ref cyhal_sdhc_is_card_mech_write_protected function can be used to check card write protection state.
333  *  This pin can be NC.
334  * @param[in]  led_ctrl             The pin connected to the led_ctrl signal. This pin can be NC.
335  * @param[in]  emmc_reset           The pin connected to the emmc_reset signal. This pin can be NC.
336  * @param[in]  block_clk            The clock to use can be shared, if not provided a new clock will be allocated
337  * @return The status of the init request
338  *
339  */
340 cy_rslt_t cyhal_sdhc_init_hw(cyhal_sdhc_t *obj,
341                         const cyhal_sdhc_config_t *config,
342                         cyhal_gpio_t cmd,
343                         cyhal_gpio_t clk,
344                         cyhal_gpio_t data0,
345                         cyhal_gpio_t data1,
346                         cyhal_gpio_t data2,
347                         cyhal_gpio_t data3,
348                         cyhal_gpio_t data4,
349                         cyhal_gpio_t data5,
350                         cyhal_gpio_t data6,
351                         cyhal_gpio_t data7,
352                         cyhal_gpio_t card_detect,
353                         cyhal_gpio_t io_volt_sel,
354                         cyhal_gpio_t card_pwr_en,
355                         cyhal_gpio_t card_mech_write_prot,
356                         cyhal_gpio_t led_ctrl,
357                         cyhal_gpio_t emmc_reset,
358                         cyhal_clock_t *block_clk);
359 
360 /** Initialize the connected card.
361  * \note This function should be called after \ref cyhal_sdhc_init_hw
362  *
363  * @param[in,out] obj               The SDHC object
364  * @return The status of the card init request
365  */
366 cy_rslt_t cyhal_sdhc_init_card(cyhal_sdhc_t *obj);
367 
368 /** Initialize the SDHC block and connected card.
369  * This function is a combination of \ref cyhal_sdhc_init_hw and \ref cyhal_sdhc_init_card calls.
370  * \note refer to \ref cyhal_sdhc_init_hw function description for detailed parameter guidance.
371  *
372  * @param[out] obj                  Pointer to an SDHC object. The caller must allocate the memory for this object but
373  *  the init function will initialize its contents.
374  * @param[in]  config               The card configuration object
375  * @param[out] clk                  The pin connected to the clk signal
376  * @param[in]  cmd                  The pin connected to the command signal
377  * @param[in]  data0                The pin connected to the data0 signal
378  * @param[in]  data1                The pin connected to the data1 signal. This pin can be NC if bus width is 1-bit.
379  * @param[in]  data2                The pin connected to the data2 signal. This pin can be NC if bus width is 1-bit.
380  * @param[in]  data3                The pin connected to the data3 signal. This pin can be NC if bus width is 1-bit.
381  * @param[in]  data4                The pin connected to the data4 signal. This pin can be NC if bus width is less than 8-bit.
382  * @param[in]  data5                The pin connected to the data5 signal. This pin can be NC if bus width is less than 8-bit.
383  * @param[in]  data6                The pin connected to the data6 signal. This pin can be NC if bus width is less than 8-bit.
384  * @param[in]  data7                The pin connected to the data7 signal. This pin can be NC if bus width is less than 8-bit.
385  * @param[in]  card_detect          The pin connected to the card_detect signal
386  * @param[out] io_volt_sel          The pin connected to the io_volt_sel signal
387  * @param[out] card_pwr_en          The pin connected to the card_pwr_en signal
388  * @param[in]  card_mech_write_prot The pin connected to the card_mech_write_prot signal
389  * @param[in]  led_ctrl             The pin connected to the led_ctrl signal
390  * @param[in]  emmc_reset           The pin connected to the emmc_reset signal
391  * @param[in]  block_clk            The clock to use can be shared, if not provided a new clock will be allocated
392  * @return The status of the init request
393  *
394  */
395 cy_rslt_t cyhal_sdhc_init(cyhal_sdhc_t *obj,
396                           const cyhal_sdhc_config_t *config,
397                           cyhal_gpio_t cmd,
398                           cyhal_gpio_t clk,
399                           cyhal_gpio_t data0,
400                           cyhal_gpio_t data1,
401                           cyhal_gpio_t data2,
402                           cyhal_gpio_t data3,
403                           cyhal_gpio_t data4,
404                           cyhal_gpio_t data5,
405                           cyhal_gpio_t data6,
406                           cyhal_gpio_t data7,
407                           cyhal_gpio_t card_detect,
408                           cyhal_gpio_t io_volt_sel,
409                           cyhal_gpio_t card_pwr_en,
410                           cyhal_gpio_t card_mech_write_prot,
411                           cyhal_gpio_t led_ctrl,
412                           cyhal_gpio_t emmc_reset,
413                           cyhal_clock_t *block_clk);
414 
415 /** Release the SDHC peripheral, not currently invoked. It requires further
416  *  resource management.
417  *
418  * @param[in,out] obj               The SDHC object
419  */
420 void cyhal_sdhc_free(cyhal_sdhc_t *obj);
421 
422 /** Attempts to read data synchronously over the SDHC peripheral.
423  *
424  * This will read as many blocks as possible, up to `length` blocks, into the buffer
425  * pointed to by `data`, then return. The value pointed to by `length` will be
426  * updated to reflect the number of words that were actually read.
427  *
428  * See \ref subsection_sdhc_snippet_2
429  *
430  * @param[in]     obj               The SDHC object
431  * @param[in]     address           The address to read data from
432  * @param[out]    data              Pointer to the byte-array where data read from the device should be stored
433  * @param[in,out] length            Number of 512 byte blocks to read, updated with the number actually read
434  * @return The status of the read request
435  */
436 cy_rslt_t cyhal_sdhc_read(cyhal_sdhc_t *obj, uint32_t address, uint8_t *data, size_t *length);
437 
438 /** Attempts to write data synchronously over SDHC peripheral
439  *
440  * This will write as many blocks as possible, up to `length` blocks, then return.
441  * The value pointed to by `length` will be updated to reflect the number of words
442  * that were actually read.
443  *
444  * See \ref subsection_sdhc_snippet_3
445  *
446  * @param[in]     obj               The SDHC object
447  * @param[in]     address           The address to write data to
448  * @param[in]     data              Pointer to the byte-array of data to write to the device
449  * @param[in,out] length            Number of 512 byte blocks to write, updated with the number actually written
450  * @return The status of the write request
451  *
452  */
453 cy_rslt_t cyhal_sdhc_write(cyhal_sdhc_t *obj, uint32_t address, const uint8_t *data, size_t *length);
454 
455 /** Erases a block of data over the SDHC peripheral
456  *
457  * @param[in] obj                   The SDHC object
458  * @param[in] start_addr            Is the address of the first byte to erase
459  * @param[in] length                Number of 512 byte blocks (starting at start_addr) to erase
460  * @param[in] timeout_ms            Timeout value in ms for waiting/polling operations. If zero is provided
461  * for this parameter the default value will be used. See implementation specific
462  * documentation for timeout details.
463  * @return The status of the erase request
464  *
465  */
466 cy_rslt_t cyhal_sdhc_erase(cyhal_sdhc_t *obj, uint32_t start_addr, size_t length, uint32_t timeout_ms);
467 
468 /** Start SDHC asynchronous read
469  *
470  * This will transfer `length` 512 byte blocks into the buffer pointed to by `data` in the background.
471  * When the requested quantity of data has been read, the \ref CYHAL_SDHC_XFER_COMPLETE event will
472  * be raised. See \ref cyhal_sdhc_register_callback and \ref cyhal_sdhc_enable_event.
473  *
474  * @param[in]     obj               The SDHC object that holds the transfer information
475  * @param[in]     address           The address to read data from
476  * @param[out]    data              The receive buffer
477  * @param[in,out] length            Number of 512 byte blocks to read, updated with the number actually read
478  * @return The status of the read_async request
479  */
480 cy_rslt_t cyhal_sdhc_read_async(cyhal_sdhc_t *obj, uint32_t address, uint8_t *data, size_t *length);
481 
482 /** Start asynchronous SDHC write
483  *
484  * This will transfer `length` 512 byte blocks from the buffer pointed to by `data` in the background.
485  * When the requested quantity of data has been written, the \ref CYHAL_SDHC_XFER_COMPLETE event
486  * will be raised. See \ref cyhal_sdhc_register_callback and \ref cyhal_sdhc_enable_event.
487  *
488  * @param[in]     obj               The SDHC object that holds the transfer information
489  * @param[in]     address           The address to write data to
490  * @param[in]     data              The transmit buffer
491  * @param[in,out] length            The number of 512 byte blocks to write, updated with the number actually written
492  * @return The status of the write_async request
493  */
494 cy_rslt_t cyhal_sdhc_write_async(cyhal_sdhc_t *obj, uint32_t address, const uint8_t *data, size_t *length);
495 
496 /** Checks if the specified SDHC peripheral is in use
497  *
498  * @param[in]  obj                  The SDHC peripheral to check
499  * @return Indication of whether the SDHC is still transmitting
500  */
501 bool cyhal_sdhc_is_busy(const cyhal_sdhc_t *obj);
502 
503 /** Abort an SDHC transfer
504  *
505  * @param[in] obj                   The SDHC peripheral to stop
506  * @return The status of the abort_async request
507  */
508 cy_rslt_t cyhal_sdhc_abort_async(cyhal_sdhc_t *obj);
509 
510 /** Register an SDHC callback handler
511  *
512  * This function will be called when one of the events enabled by \ref cyhal_sdhc_enable_event occurs.
513  *
514  * @param[in] obj                   The SDHC object
515  * @param[in] callback              The callback handler which will be invoked when the event fires
516  * @param[in] callback_arg          Generic argument that will be provided to the callback when called
517  */
518 void cyhal_sdhc_register_callback(cyhal_sdhc_t *obj, cyhal_sdhc_event_callback_t callback, void *callback_arg);
519 
520 /** Configure SDHC event enablement.
521  *
522  * When an enabled event occurs, the function specified by \ref cyhal_sdhc_register_callback will be called.
523  *
524  * @param[in] obj                   The SDHC object
525  * @param[in] event                 The SDHC event type
526  * @param[in] intr_priority         The priority for NVIC interrupt events
527  * @param[in] enable                True to turn on interrupts, False to turn off
528  */
529 void cyhal_sdhc_enable_event(cyhal_sdhc_t *obj, cyhal_sdhc_event_t event, uint8_t intr_priority, bool enable);
530 
531 /** Checks if SD card is inserted
532  *
533  * @param[in]  obj                  The SDHC peripheral to check
534  * @return Indication of whether the card is inserted.
535  */
536 bool cyhal_sdhc_is_card_inserted(const cyhal_sdhc_t *obj);
537 
538 /** Checks if the inserted SD card is mechanically write protected
539  *
540  * @param[in]  obj                  The SDHC peripheral to check
541  * @return Indication of whether the inserted SD card is mechanically write protected
542  */
543 bool cyhal_sdhc_is_card_mech_write_protected(const cyhal_sdhc_t *obj);
544 
545 /** Get block count of inserted SD card / eMMC
546  * \note SDHC driver should be initialized with \ref cyhal_sdhc_init prior to using this function.
547  *
548  * @param[in]  obj                  The SDHC object
549  * @param[in]  block_count          Pointer to variable where block count will be stored
550  * @return The status of the operation
551  */
552 cy_rslt_t cyhal_sdhc_get_block_count(cyhal_sdhc_t *obj, uint32_t *block_count);
553 
554 /** Sets the SD bus frequency (frequency on which SD card / eMMC is accessed)
555  * \note Actual frequency may differ from the desired frequency due to available dividers and the frequency of source clock.
556  * Function will set the closest possible (but not greater than) frequency to what was requested.
557  * Use \ref cyhal_sdhc_get_frequency function to get actual frequency value that was achieved and set.
558  * \note If data timeout was configured by \ref cyhal_sdhc_set_data_read_timeout, it can be automaticaly recalculated
559  * according to new SD bus frequency. For details, please refer to \ref cyhal_sdhc_set_data_read_timeout function description.
560  *
561  * @param[in]  obj                  The SDHC object
562  * @param[in]  hz                   Desired SD bus frequency in Hz
563  * @param[in]  negotiate            Whether new frequency value needs to be negotiated with card or not. true is
564  *  recommended and it means that new frequency will be negotiated.
565  * @return The status of the operation
566  */
567 cy_rslt_t cyhal_sdhc_set_frequency(cyhal_sdhc_t *obj, uint32_t hz, bool negotiate);
568 
569 /** Get the actual frequency that SD bus is configured for
570  *
571  * @param[in] obj                   The SDHC object
572  * @return Frequency in Hz
573  */
574 uint32_t cyhal_sdhc_get_frequency(cyhal_sdhc_t *obj);
575 
576 /** Sets the maximum time to wait for data from the card. The time is specified in number of card clock cycles.
577  * With SD bus frequency changed by \ref cyhal_sdhc_set_frequency, timeout can automaticaly be recalculated according
578  * to new clock frequency. This can be activated by 'auto_reconfigure' parameter.
579  *
580  * @param[in]  obj                  The SDHC object
581  * @param[in]  timeout              Time to wait for data from the card.
582  * @param[in]  auto_reconfigure     Timeout value will be automaticaly reconfigured upon clock change
583  *
584  * @return The status of the operation
585  */
586 cy_rslt_t cyhal_sdhc_set_data_read_timeout(cyhal_sdhc_t *obj, uint32_t timeout, bool auto_reconfigure);
587 
588 /**  Initializes the SD block and DMA for a data transfer. It does not start a transfer.
589  *  \ref cyhal_sdhc_send_cmd needs to be called after this function in order to start data transfer.
590  *
591  * @param[in]  obj                  The SDHC object
592  * @param[in]  data_config          Data transfer configuration
593  * @return The status of the operation
594  */
595 cy_rslt_t cyhal_sdhc_config_data_transfer(cyhal_sdhc_t *obj, cyhal_sdhc_data_config_t *data_config);
596 
597 /** Sends a command to the card and wait until it is sent. If the command assumes data transfer via data lines,
598  * \ref cyhal_sdhc_config_data_transfer function needs to be called prior to this one. The response of issued command
599  * can be retrieved by using \ref cyhal_sdhc_get_response function.
600  * \note Function does not wait until data (configured with \ref cyhal_sdhc_config_data_transfer) transfer complete.
601  * In order to do so, user can:
602  * - register \ref CYHAL_SDHC_XFER_COMPLETE and wait for it
603  * - wait until \ref cyhal_sdhc_is_busy return false
604  * - use \ref cyhal_sdhc_wait_transfer_complete function
605  *
606  * @param[in]  obj                  The SDHC object
607  * @param[in]  cmd_config           Command configuration
608  * @return The status of the operation
609  */
610 cy_rslt_t cyhal_sdhc_send_cmd(cyhal_sdhc_t *obj, cyhal_sdhc_cmd_config_t *cmd_config);
611 
612 /** Returns a response of last issued by \ref cyhal_sdhc_send_cmd function command.
613  *
614  * @param[in]  obj                  The SDHC object
615  * @param[in]  response             Pointer to array where response will be stored
616  * @param[in]  large_response       If true, the expected response is 136 bits, false - 48 bits, which corresponds to
617  * 120 and 32 bits of useful for application data respectively. So for large_response 4 uint32_t element array can be used
618  * while for not large_response 1 uint32_t value will be enough.
619  * @return The status of the operation
620  */
621 cy_rslt_t cyhal_sdhc_get_response(cyhal_sdhc_t *obj, uint32_t *response, bool large_response);
622 
623 /** Wait for asynchronous data transfer to complete. Such data transfer can be triggered by \ref cyhal_sdhc_write_async,
624  * \ref cyhal_sdhc_read_async or by \ref cyhal_sdhc_config_data_transfer + \ref cyhal_sdhc_send_cmd functions.
625  *
626  * @param[in]  obj                  The SDHC object
627  * @return The status of the operation
628  */
629 cy_rslt_t cyhal_sdhc_wait_transfer_complete(cyhal_sdhc_t *obj);
630 
631 /** Sets the voltage level of the I/O lines.
632  * \note This function requires io_volt_sel and (for some cases) card_pwr_en pins to be assigned. Please refer to
633  *  \ref cyhal_sdhc_init_hw for pin details.
634  * \note Switching from 1.8V to 3.3V can be done only via power cycle sequence (power down card, wait, power up card),
635  *  which is supported by HAL driver and performed only if CYHAL_SDHC_IO_VOLT_ACTION_NEGOTIATE selected. card_pwr_en pin
636  *  has to be assigned. Please refer to \ref cyhal_sdhc_init_hw for pin details.
637  *
638  * @param[in]  obj                  The SDHC object
639  * @param[in]  io_voltage           I/O voltage to be set on lines
640  * @param[in]  io_switch_type       Defines how I/O voltage will be switched
641  * @return The status of the operation
642  */
643 cy_rslt_t cyhal_sdhc_set_io_voltage(cyhal_sdhc_t *obj, cyhal_sdhc_io_voltage_t io_voltage, cyhal_sdhc_io_volt_action_type_t io_switch_type);
644 
645 /** Returns the current voltage level of the I/O lines
646  *
647  * @param[in]   obj                 The SDHC object
648  * @return Current I/O voltage setting value
649  */
650 cyhal_sdhc_io_voltage_t cyhal_sdhc_get_io_voltage(cyhal_sdhc_t *obj);
651 
652 /** Configures data bus width on host side and (optionally) informs the card about new width configuration.
653  *
654  * @param[in]  obj                  The SDHC object
655  * @param[in]  bus_width            The desired bus width, 1-bit, 4-bit, 8-bit
656  * @param[in]  configure_card       Whether card needs to be configured with new bus width. true is recommended.
657  * @return The status of the operation
658  */
659 cy_rslt_t cyhal_sdhc_set_bus_width(cyhal_sdhc_t *obj, uint8_t bus_width, bool configure_card);
660 
661 /** Returns currently configured data bus width
662  *
663  * @param[in]  obj                  The SDHC object
664  * @return Currently configured bus width, 1-bit, 4-bit, 8-bit
665  */
666 uint8_t cyhal_sdhc_get_bus_width(cyhal_sdhc_t *obj);
667 
668 /** Returns last issued SD operation error states. This function can be used for error checking after any of cmd / data
669  * transfer-related operations. For list of possible errors, that are being tracked, please refer to \ref cyhal_sdhc_error_type_t.
670  *
671  * @param[in]   obj                 The SDHC object
672  * @return Errors occurred during last command
673  */
674 cyhal_sdhc_error_type_t cyhal_sdhc_get_last_command_errors(cyhal_sdhc_t *obj);
675 
676 /** Clears SDHC hardware error states. Error statuses are indicated by \ref cyhal_sdhc_get_last_command_errors function.
677  *
678  * @param[in]   obj                 The SDHC object
679  */
680 void cyhal_sdhc_clear_errors(cyhal_sdhc_t *obj);
681 
682 /** Resets CMD and Data lines and corresponding circuits of SD Host.
683  *
684  * @param[in]   obj                 The SDHC object
685  */
686 void cyhal_sdhc_software_reset(cyhal_sdhc_t *obj);
687 
688 /** Powers up / down the card based on provided parameter. This function uses card_pwr_en pin to change card power
689  * state. Please refer to \ref cyhal_sdhc_init_hw for pin description.
690  *
691  * @param[in]  obj                  The SDHC peripheral to configure
692  * @param[in]  enable               Card is powered if true, not powered if false.
693  * @return The status of the operation
694  */
695 cy_rslt_t cyhal_sdhc_enable_card_power(cyhal_sdhc_t *obj, bool enable);
696 
697 /** Initialize the SDHC peripheral using a configurator generated configuration struct.
698  *
699  * @param[in]  obj                  The SDHC peripheral to configure
700  * @param[in]  cfg                  Configuration structure generated by a configurator.
701  * @return The status of the operation
702  */
703 cy_rslt_t cyhal_sdhc_init_cfg(cyhal_sdhc_t *obj, const cyhal_sdhc_configurator_t *cfg);
704 
705 #if defined(__cplusplus)
706 }
707 #endif
708 
709 #ifdef CYHAL_SDHC_IMPL_HEADER
710 #include CYHAL_SDHC_IMPL_HEADER
711 #endif /* CYHAL_SDHC_IMPL_HEADER */
712 
713 /** \} group_hal_sdhc */
714