1 /*
2  * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
3  * Adaptations to ESP-IDF Copyright (c) 2016-2018 Espressif Systems (Shanghai) PTE LTD
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include "sdmmc_common.h"
19 
20 static const char* TAG = "sdmmc_common";
21 
sdmmc_init_ocr(sdmmc_card_t * card)22 esp_err_t sdmmc_init_ocr(sdmmc_card_t* card)
23 {
24     esp_err_t err;
25     /* In SPI mode, READ_OCR (CMD58) command is used to figure out which voltage
26      * ranges the card can support. This step is skipped since 1.8V isn't
27      * supported on the ESP32.
28      */
29 
30     uint32_t host_ocr = get_host_ocr(card->host.io_voltage);
31     if ((card->ocr & SD_OCR_SDHC_CAP) != 0) {
32         host_ocr |= SD_OCR_SDHC_CAP;
33     }
34     /* Send SEND_OP_COND (ACMD41) command to the card until it becomes ready. */
35     err = sdmmc_send_cmd_send_op_cond(card, host_ocr, &card->ocr);
36 
37     /* If time-out, re-try send_op_cond as MMC */
38     if (err == ESP_ERR_TIMEOUT && !host_is_spi(card)) {
39         ESP_LOGD(TAG, "send_op_cond timeout, trying MMC");
40         card->is_mmc = 1;
41         err = sdmmc_send_cmd_send_op_cond(card, host_ocr, &card->ocr);
42     }
43 
44     if (err != ESP_OK) {
45         ESP_LOGE(TAG, "%s: send_op_cond (1) returned 0x%x", __func__, err);
46         return err;
47     }
48     if (host_is_spi(card)) {
49         err = sdmmc_send_cmd_read_ocr(card, &card->ocr);
50         if (err != ESP_OK) {
51             ESP_LOGE(TAG, "%s: read_ocr returned 0x%x", __func__, err);
52             return err;
53         }
54     }
55     ESP_LOGD(TAG, "host_ocr=0x%x card_ocr=0x%x", host_ocr, card->ocr);
56 
57     /* Clear all voltage bits in host's OCR which the card doesn't support.
58      * Don't touch CCS bit because in SPI mode cards don't report CCS in ACMD41
59      * response.
60      */
61     host_ocr &= (card->ocr | (~SD_OCR_VOL_MASK));
62     ESP_LOGD(TAG, "sdmmc_card_init: host_ocr=%08x, card_ocr=%08x", host_ocr, card->ocr);
63     return ESP_OK;
64 }
65 
sdmmc_init_cid(sdmmc_card_t * card)66 esp_err_t sdmmc_init_cid(sdmmc_card_t* card)
67 {
68     esp_err_t err;
69     sdmmc_response_t raw_cid;
70     if (!host_is_spi(card)) {
71         err = sdmmc_send_cmd_all_send_cid(card, &raw_cid);
72         if (err != ESP_OK) {
73             ESP_LOGE(TAG, "%s: all_send_cid returned 0x%x", __func__, err);
74             return err;
75         }
76         if (!card->is_mmc) {
77             err = sdmmc_decode_cid(raw_cid, &card->cid);
78             if (err != ESP_OK) {
79                 ESP_LOGE(TAG, "%s: decoding CID failed (0x%x)", __func__, err);
80                 return err;
81             }
82         } else {
83             /* For MMC, need to know CSD to decode CID. But CSD can only be read
84              * in data transfer mode, and it is not possible to read CID in data
85              * transfer mode. We temporiliy store the raw cid and do the
86              * decoding after the RCA is set and the card is in data transfer
87              * mode.
88              */
89             memcpy(card->raw_cid, raw_cid, sizeof(sdmmc_response_t));
90         }
91     } else {
92         err = sdmmc_send_cmd_send_cid(card, &card->cid);
93         if (err != ESP_OK) {
94             ESP_LOGE(TAG, "%s: send_cid returned 0x%x", __func__, err);
95             return err;
96         }
97     }
98     return ESP_OK;
99 }
100 
sdmmc_init_rca(sdmmc_card_t * card)101 esp_err_t sdmmc_init_rca(sdmmc_card_t* card)
102 {
103     esp_err_t err;
104     err = sdmmc_send_cmd_set_relative_addr(card, &card->rca);
105     if (err != ESP_OK) {
106         ESP_LOGE(TAG, "%s: set_relative_addr returned 0x%x", __func__, err);
107         return err;
108     }
109     return ESP_OK;
110 }
111 
sdmmc_init_mmc_decode_cid(sdmmc_card_t * card)112 esp_err_t sdmmc_init_mmc_decode_cid(sdmmc_card_t* card)
113 {
114     esp_err_t err;
115     sdmmc_response_t raw_cid;
116     memcpy(raw_cid, card->raw_cid, sizeof(raw_cid));
117     err = sdmmc_mmc_decode_cid(card->csd.mmc_ver, raw_cid, &card->cid);
118     if (err != ESP_OK) {
119         ESP_LOGE(TAG, "%s: decoding CID failed (0x%x)", __func__, err);
120         return err;
121     }
122     return ESP_OK;
123 }
124 
sdmmc_init_csd(sdmmc_card_t * card)125 esp_err_t sdmmc_init_csd(sdmmc_card_t* card)
126 {
127     assert(card->is_mem == 1);
128     /* Get and decode the contents of CSD register. Determine card capacity. */
129     esp_err_t err = sdmmc_send_cmd_send_csd(card, &card->csd);
130     if (err != ESP_OK) {
131         ESP_LOGE(TAG, "%s: send_csd returned 0x%x", __func__, err);
132         return err;
133     }
134     const size_t max_sdsc_capacity = UINT32_MAX / card->csd.sector_size + 1;
135     if (!(card->ocr & SD_OCR_SDHC_CAP) &&
136          card->csd.capacity > max_sdsc_capacity) {
137         ESP_LOGW(TAG, "%s: SDSC card reports capacity=%u. Limiting to %u.",
138                 __func__, card->csd.capacity, max_sdsc_capacity);
139         card->csd.capacity = max_sdsc_capacity;
140     }
141     return ESP_OK;
142 }
143 
sdmmc_init_select_card(sdmmc_card_t * card)144 esp_err_t sdmmc_init_select_card(sdmmc_card_t* card)
145 {
146     assert(!host_is_spi(card));
147     esp_err_t err = sdmmc_send_cmd_select_card(card, card->rca);
148     if (err != ESP_OK) {
149         ESP_LOGE(TAG, "%s: select_card returned 0x%x", __func__, err);
150         return err;
151     }
152     return ESP_OK;
153 }
154 
sdmmc_init_card_hs_mode(sdmmc_card_t * card)155 esp_err_t sdmmc_init_card_hs_mode(sdmmc_card_t* card)
156 {
157     esp_err_t err = ESP_ERR_NOT_SUPPORTED;
158     if (card->is_mem && !card->is_mmc) {
159         err = sdmmc_enable_hs_mode_and_check(card);
160     } else if (card->is_sdio) {
161         err = sdmmc_io_enable_hs_mode(card);
162     } else if (card->is_mmc){
163         err = sdmmc_mmc_enable_hs_mode(card);
164     }
165     if (err == ESP_ERR_NOT_SUPPORTED) {
166         ESP_LOGD(TAG, "%s: host supports HS mode, but card doesn't", __func__);
167         card->max_freq_khz = SDMMC_FREQ_DEFAULT;
168     } else if (err != ESP_OK) {
169         return err;
170     }
171     return ESP_OK;
172 }
173 
sdmmc_init_host_bus_width(sdmmc_card_t * card)174 esp_err_t sdmmc_init_host_bus_width(sdmmc_card_t* card)
175 {
176     int bus_width = 1;
177 
178     if ((card->host.flags & SDMMC_HOST_FLAG_4BIT) &&
179         (card->log_bus_width == 2)) {
180         bus_width = 4;
181     } else if ((card->host.flags & SDMMC_HOST_FLAG_8BIT) &&
182         (card->log_bus_width == 3)) {
183         bus_width = 8;
184     }
185     ESP_LOGD(TAG, "%s: using %d-bit bus", __func__, bus_width);
186     if (bus_width > 1) {
187         esp_err_t err = (*card->host.set_bus_width)(card->host.slot, bus_width);
188         if (err != ESP_OK) {
189             ESP_LOGE(TAG, "host.set_bus_width failed (0x%x)", err);
190             return err;
191         }
192     }
193     return ESP_OK;
194 }
195 
sdmmc_init_host_frequency(sdmmc_card_t * card)196 esp_err_t sdmmc_init_host_frequency(sdmmc_card_t* card)
197 {
198     assert(card->max_freq_khz <= card->host.max_freq_khz);
199 
200     /* Find highest frequency in the following list,
201      * which is below card->max_freq_khz.
202      */
203     const uint32_t freq_values[] = {
204             SDMMC_FREQ_52M,
205             SDMMC_FREQ_HIGHSPEED,
206             SDMMC_FREQ_26M,
207             SDMMC_FREQ_DEFAULT
208             //NOTE: in sdspi mode, 20MHz may not work. in that case, add 10MHz here.
209     };
210     const int n_freq_values = sizeof(freq_values) / sizeof(freq_values[0]);
211 
212     uint32_t selected_freq = SDMMC_FREQ_PROBING;
213     for (int i = 0; i < n_freq_values; ++i) {
214         uint32_t freq = freq_values[i];
215         if (card->max_freq_khz >= freq) {
216             selected_freq = freq;
217             break;
218         }
219     }
220 
221     ESP_LOGD(TAG, "%s: using %d kHz bus frequency", __func__, selected_freq);
222     if (selected_freq > SDMMC_FREQ_PROBING) {
223         esp_err_t err = (*card->host.set_card_clk)(card->host.slot, selected_freq);
224         if (err != ESP_OK) {
225             ESP_LOGE(TAG, "failed to switch bus frequency (0x%x)", err);
226             return err;
227         }
228     }
229 
230     if (card->is_ddr) {
231         if (card->host.set_bus_ddr_mode == NULL) {
232             ESP_LOGE(TAG, "host doesn't support DDR mode or voltage switching");
233             return ESP_ERR_NOT_SUPPORTED;
234         }
235         esp_err_t err = (*card->host.set_bus_ddr_mode)(card->host.slot, true);
236         if (err != ESP_OK) {
237             ESP_LOGE(TAG, "failed to switch bus to DDR mode (0x%x)", err);
238             return err;
239         }
240     }
241     return ESP_OK;
242 }
243 
sdmmc_flip_byte_order(uint32_t * response,size_t size)244 void sdmmc_flip_byte_order(uint32_t* response, size_t size)
245 {
246     assert(size % (2 * sizeof(uint32_t)) == 0);
247     const size_t n_words = size / sizeof(uint32_t);
248     for (int i = 0; i < n_words / 2; ++i) {
249         uint32_t left = __builtin_bswap32(response[i]);
250         uint32_t right = __builtin_bswap32(response[n_words - i - 1]);
251         response[i] = right;
252         response[n_words - i - 1] = left;
253     }
254 }
255 
sdmmc_card_print_info(FILE * stream,const sdmmc_card_t * card)256 void sdmmc_card_print_info(FILE* stream, const sdmmc_card_t* card)
257 {
258     bool print_scr = false;
259     bool print_csd = false;
260     const char* type;
261     fprintf(stream, "Name: %s\n", card->cid.name);
262     if (card->is_sdio) {
263         type = "SDIO";
264         print_scr = true;
265         print_csd = true;
266     } else if (card->is_mmc) {
267         type = "MMC";
268         print_csd = true;
269     } else {
270         type = (card->ocr & SD_OCR_SDHC_CAP) ? "SDHC/SDXC" : "SDSC";
271     }
272     fprintf(stream, "Type: %s\n", type);
273     if (card->max_freq_khz < 1000) {
274         fprintf(stream, "Speed: %d kHz\n", card->max_freq_khz);
275     } else {
276         fprintf(stream, "Speed: %d MHz%s\n", card->max_freq_khz / 1000,
277                 card->is_ddr ? ", DDR" : "");
278     }
279     fprintf(stream, "Size: %lluMB\n", ((uint64_t) card->csd.capacity) * card->csd.sector_size / (1024 * 1024));
280 
281     if (print_csd) {
282         fprintf(stream, "CSD: ver=%d, sector_size=%d, capacity=%d read_bl_len=%d\n",
283                 card->csd.csd_ver,
284                 card->csd.sector_size, card->csd.capacity, card->csd.read_block_len);
285     }
286     if (print_scr) {
287         fprintf(stream, "SCR: sd_spec=%d, bus_width=%d\n", card->scr.sd_spec, card->scr.bus_width);
288     }
289 }
290 
sdmmc_fix_host_flags(sdmmc_card_t * card)291 esp_err_t sdmmc_fix_host_flags(sdmmc_card_t* card)
292 {
293     const uint32_t width_1bit = SDMMC_HOST_FLAG_1BIT;
294     const uint32_t width_4bit = SDMMC_HOST_FLAG_4BIT;
295     const uint32_t width_8bit = SDMMC_HOST_FLAG_8BIT;
296     const uint32_t width_mask = width_1bit | width_4bit | width_8bit;
297 
298     int slot_bit_width = card->host.get_bus_width(card->host.slot);
299     if (slot_bit_width == 1 &&
300             (card->host.flags & (width_4bit | width_8bit))) {
301         card->host.flags &= ~width_mask;
302         card->host.flags |= width_1bit;
303     } else if (slot_bit_width == 4 && (card->host.flags & width_8bit)) {
304         if ((card->host.flags & width_4bit) == 0) {
305             ESP_LOGW(TAG, "slot width set to 4, but host flags don't have 4 line mode enabled; using 1 line mode");
306             card->host.flags &= ~width_mask;
307             card->host.flags |= width_1bit;
308         } else {
309             card->host.flags &= ~width_mask;
310             card->host.flags |= width_4bit;
311         }
312     }
313     return ESP_OK;
314 }
315