1 /*
2 * Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define SDMMC_FREQ_DEFAULT 20000 /*!< SD/MMC Default speed (limited by clock divider) */
8 #define SDMMC_FREQ_HIGHSPEED 40000 /*!< SD High speed (limited by clock divider) */
9 #define SDMMC_FREQ_PROBING 400 /*!< SD/MMC probing speed */
10 #define SDMMC_FREQ_52M 52000 /*!< MMC 52MHz speed */
11 #define SDMMC_FREQ_26M 26000 /*!< MMC 26MHz speed */
12
13 #define SDMMC_DATA_ERR_MASK \
14 (uint32_t)(SDMMC_INTMASK_DTO | SDMMC_INTMASK_DCRC | SDMMC_INTMASK_HTO | \
15 SDMMC_INTMASK_SBE | SDMMC_INTMASK_EBE)
16
17 #define SDMMC_DMA_DONE_MASK \
18 (uint32_t)(SDMMC_IDMAC_INTMASK_RI | SDMMC_IDMAC_INTMASK_TI | SDMMC_IDMAC_INTMASK_NI)
19
20 #define SDMMC_CMD_ERR_MASK \
21 (uint32_t)(SDMMC_INTMASK_RTO | SDMMC_INTMASK_RCRC | SDMMC_INTMASK_RESP_ERR)
22
23 enum sdmmc_req_state {
24 SDMMC_IDLE,
25 SDMMC_SENDING_CMD,
26 SDMMC_SENDING_DATA,
27 SDMMC_BUSY,
28 };
29
30 /* SDHC command flags */
31 #define SCF_ITSDONE 0x0001 /*!< command is complete */
32 #define SCF_CMD(flags) ((flags) & 0x00f0)
33 #define SCF_CMD_AC 0x0000
34 #define SCF_CMD_ADTC 0x0010
35 #define SCF_CMD_BC 0x0020
36 #define SCF_CMD_BCR 0x0030
37 #define SCF_CMD_READ 0x0040 /*!< read command (data expected) */
38 #define SCF_RSP_BSY 0x0100
39 #define SCF_RSP_136 0x0200
40 #define SCF_RSP_CRC 0x0400
41 #define SCF_RSP_IDX 0x0800
42 #define SCF_RSP_PRESENT 0x1000
43 /* response types */
44 #define SCF_RSP_R0 0 /*!< none */
45 #define SCF_RSP_R1 (SCF_RSP_PRESENT | SCF_RSP_CRC | SCF_RSP_IDX)
46 #define SCF_RSP_R1B (SCF_RSP_PRESENT | SCF_RSP_CRC | SCF_RSP_IDX | SCF_RSP_BSY)
47 #define SCF_RSP_R2 (SCF_RSP_PRESENT | SCF_RSP_CRC | SCF_RSP_136)
48 #define SCF_RSP_R3 (SCF_RSP_PRESENT)
49 #define SCF_RSP_R4 (SCF_RSP_PRESENT)
50 #define SCF_RSP_R5 (SCF_RSP_PRESENT | SCF_RSP_CRC | SCF_RSP_IDX)
51 #define SCF_RSP_R5B (SCF_RSP_PRESENT | SCF_RSP_CRC | SCF_RSP_IDX | SCF_RSP_BSY)
52 #define SCF_RSP_R6 (SCF_RSP_PRESENT | SCF_RSP_CRC | SCF_RSP_IDX)
53 #define SCF_RSP_R7 (SCF_RSP_PRESENT | SCF_RSP_CRC | SCF_RSP_IDX)
54 /* special flags */
55 #define SCF_WAIT_BUSY 0x2000 /*!< Wait for completion of card busy signal before returning */
56
57 #define SD_OCR_SDHC_CAP (1 << 30)
58 #define SD_OCR_VOL_MASK 0xFF8000 /* bits 23:15 */
59
60 /* For debug only */
61 static const char *const timingStr[] = {"UNKNOWN", "LEGACY", "HS", "SDR12", "SDR25", "SDR50",
62 "SDR104", "DDR50", "DDR52", "HS200", "HS400"};
63
64 struct sdmmc_transfer_state {
65 uint8_t *ptr;
66 size_t size_remaining;
67 size_t next_desc;
68 size_t desc_remaining;
69 };
70
71 struct sdmmc_event {
72 uint32_t header_DUMMY; /* Reserved for system use (Zephyr message queue) */
73 uint32_t sdmmc_status; /* masked SDMMC interrupt status */
74 uint32_t dma_status; /* masked DMA interrupt status */
75 };
76
77 /**
78 * Host contexts
79 */
80 struct host_ctx {
81 intr_handle_t intr_handle;
82 struct k_msgq *event_queue;
83 };
84
85 /**
86 * SD/MMC command information
87 */
88 struct sdmmc_command {
89 uint32_t opcode; /*!< SD or MMC command index */
90 uint32_t arg; /*!< SD/MMC command argument */
91 uint32_t response[4]; /*!< response buffer */
92 void *data; /*!< buffer to send or read into */
93 size_t datalen; /*!< length of data in the buffer */
94 size_t buflen; /*!< length of the buffer */
95 size_t blklen; /*!< block length */
96 int flags; /*!< see below */
97 esp_err_t error; /*!< error returned from transfer */
98 uint32_t timeout_ms; /*!< response timeout, in milliseconds */
99 };
100
101 /**
102 * @brief Convert ESP to Zephyr error codes
103 *
104 * @param ret_esp ESP return value
105 *
106 * @return Zephyr error code
107 */
err_esp2zep(int ret_esp)108 static __attribute__((always_inline)) inline int err_esp2zep(int ret_esp)
109 {
110 int ret;
111
112 switch (ret_esp) {
113 /* Treating the error codes most relevant to be individuated */
114 case ESP_ERR_INVALID_ARG:
115 ret = -EINVAL;
116 break;
117 case ESP_ERR_TIMEOUT:
118 ret = -ETIMEDOUT;
119 break;
120 case ESP_ERR_NOT_FOUND:
121 ret = -ENODEV; /* SD card not inserted (requires CD signal) */
122 break;
123 case ESP_ERR_INVALID_STATE:
124 ret = -EACCES; /* SD card write-protected (requires WP sinal) */
125 break;
126 default:
127 ret = -EIO;
128 break;
129 }
130
131 return ret;
132 }
133