1 // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
17 #include <sys/param.h>
19 #include "esp_intr_alloc.h"
20 #include "soc/io_mux_reg.h"
22 #include "driver/gpio.h"
23 #include "driver/sdmmc_host.h"
24 #include "driver/periph_ctrl.h"
25 #include "sdmmc_private.h"
26 #include "freertos/semphr.h"
27 #include "soc/sdmmc_periph.h"
29 #define SDMMC_EVENT_QUEUE_LENGTH 32
32 static void sdmmc_isr(void* arg);
33 static void sdmmc_host_dma_init();
36 static const char* TAG = "sdmmc_periph";
37 static intr_handle_t s_intr_handle;
38 static QueueHandle_t s_event_queue;
39 static SemaphoreHandle_t s_io_intr_event;
41 size_t s_slot_width[2] = {1,1};
43 void sdmmc_host_reset()
46 SDMMC.ctrl.controller_reset = 1;
47 SDMMC.ctrl.dma_reset = 1;
48 SDMMC.ctrl.fifo_reset = 1;
49 // Wait for the reset bits to be cleared by hardware
50 while (SDMMC.ctrl.controller_reset || SDMMC.ctrl.fifo_reset || SDMMC.ctrl.dma_reset) {
55 /* We have two clock divider stages:
56 * - one is the clock generator which drives SDMMC peripheral,
57 * it can be configured using SDMMC.clock register. It can generate
58 * frequencies 160MHz/(N + 1), where 0 < N < 16, I.e. from 10 to 80 MHz.
59 * - 4 clock dividers inside SDMMC peripheral, which can divide clock
60 * from the first stage by 2 * M, where 0 < M < 255
61 * (they can also be bypassed).
63 * For cards which aren't UHS-1 or UHS-2 cards, which we don't support,
64 * maximum bus frequency in high speed (HS) mode is 50 MHz.
65 * Note: for non-UHS-1 cards, HS mode is optional.
66 * Default speed (DS) mode is mandatory, it works up to 25 MHz.
67 * Whether the card supports HS or not can be determined using TRAN_SPEED
68 * field of card's CSD register.
70 * 50 MHz can not be obtained exactly, closest we can get is 53 MHz.
72 * The first stage divider is set to the highest possible value for the given
73 * frequency, and the the second stage dividers are used if division factor
76 * Of the second stage dividers, div0 is used for card 0, and div1 is used
80 static void sdmmc_host_set_clk_div(int div)
82 // Set frequency to 160MHz / div
84 // duty cycle = (h + 1)/(p + 1) (should be = 1/2)
85 assert (div > 1 && div <= 16);
89 SDMMC.clock.div_factor_p = p;
90 SDMMC.clock.div_factor_h = h;
91 SDMMC.clock.div_factor_m = p;
92 // Set phases for in/out clocks
93 SDMMC.clock.phase_dout = 4; // 180 degree phase on the output clock
94 SDMMC.clock.phase_din = 4; // 180 degree phase on the input clock
95 SDMMC.clock.phase_core = 0;
96 // Wait for the clock to propagate
100 static void sdmmc_host_input_clk_disable()
105 static void sdmmc_host_clock_update_command(int slot)
107 // Clock update command (not a real command; just updates CIU registers)
108 sdmmc_hw_cmd_t cmd_val = {
115 sdmmc_host_start_command(slot, cmd_val, 0);
117 // Sending clock update command to the CIU can generate HLE error.
118 // According to the manual, this is okay and we must retry the command.
119 if (SDMMC.rintsts.hle) {
120 SDMMC.rintsts.hle = 1;
124 // When the command is accepted by CIU, start_command bit will be
125 // cleared in SDMMC.cmd register.
126 if (SDMMC.cmd.start_command == 0) {
134 esp_err_t sdmmc_host_set_card_clk(int slot, uint32_t freq_khz)
136 if (!(slot == 0 || slot == 1)) {
137 return ESP_ERR_INVALID_ARG;
139 const int clk40m = 40000;
141 // Disable clock first
142 SDMMC.clkena.cclk_enable &= ~BIT(slot);
143 sdmmc_host_clock_update_command(slot);
145 int host_div = 0; /* clock divider of the host (SDMMC.clock) */
146 int card_div = 0; /* 1/2 of card clock divider (SDMMC.clkdiv) */
148 // Calculate new dividers
149 if (freq_khz >= SDMMC_FREQ_HIGHSPEED) {
150 host_div = 4; // 160 MHz / 4 = 40 MHz
152 } else if (freq_khz == SDMMC_FREQ_DEFAULT) {
153 host_div = 8; // 160 MHz / 8 = 20 MHz
155 } else if (freq_khz == SDMMC_FREQ_PROBING) {
156 host_div = 10; // 160 MHz / 10 / (20 * 2) = 400 kHz
160 card_div = (clk40m + freq_khz * 2 - 1) / (freq_khz * 2); // round up
163 ESP_LOGD(TAG, "slot=%d host_div=%d card_div=%d freq=%dkHz",
164 slot, host_div, card_div,
165 2 * APB_CLK_FREQ / host_div / ((card_div == 0) ? 1 : card_div * 2) / 1000);
167 // Program CLKDIV and CLKSRC, send them to the CIU
170 SDMMC.clksrc.card0 = 0;
171 SDMMC.clkdiv.div0 = card_div;
174 SDMMC.clksrc.card1 = 1;
175 SDMMC.clkdiv.div1 = card_div;
178 sdmmc_host_set_clk_div(host_div);
179 sdmmc_host_clock_update_command(slot);
182 SDMMC.clkena.cclk_enable |= BIT(slot);
183 SDMMC.clkena.cclk_low_power |= BIT(slot);
184 sdmmc_host_clock_update_command(slot);
187 const uint32_t data_timeout_ms = 100;
188 uint32_t data_timeout_cycles = data_timeout_ms * freq_khz;
189 const uint32_t data_timeout_cycles_max = 0xffffff;
190 if (data_timeout_cycles > data_timeout_cycles_max) {
191 data_timeout_cycles = data_timeout_cycles_max;
193 SDMMC.tmout.data = data_timeout_cycles;
194 // always set response timeout to highest value, it's small enough anyway
195 SDMMC.tmout.response = 255;
199 esp_err_t sdmmc_host_start_command(int slot, sdmmc_hw_cmd_t cmd, uint32_t arg) {
200 if (!(slot == 0 || slot == 1)) {
201 return ESP_ERR_INVALID_ARG;
203 if ((SDMMC.cdetect.cards & BIT(slot)) != 0) {
204 return ESP_ERR_NOT_FOUND;
206 if (cmd.data_expected && cmd.rw && (SDMMC.wrtprt.cards & BIT(slot)) != 0) {
207 return ESP_ERR_INVALID_STATE;
209 while (SDMMC.cmd.start_command == 1) {
214 cmd.start_command = 1;
219 esp_err_t sdmmc_host_init()
222 return ESP_ERR_INVALID_STATE;
225 periph_module_enable(PERIPH_SDMMC_MODULE);
227 // Enable clock to peripheral. Use smallest divider first.
228 sdmmc_host_set_clk_div(2);
232 ESP_LOGD(TAG, "peripheral version %x, hardware config %08x", SDMMC.verid, SDMMC.hcon);
234 // Clear interrupt status and set interrupt mask to known state
235 SDMMC.rintsts.val = 0xffffffff;
236 SDMMC.intmask.val = 0;
237 SDMMC.ctrl.int_enable = 0;
239 // Allocate event queue
240 s_event_queue = xQueueCreate(SDMMC_EVENT_QUEUE_LENGTH, sizeof(sdmmc_event_t));
241 if (!s_event_queue) {
242 return ESP_ERR_NO_MEM;
244 s_io_intr_event = xSemaphoreCreateBinary();
245 if (!s_io_intr_event) {
246 vQueueDelete(s_event_queue);
247 s_event_queue = NULL;
248 return ESP_ERR_NO_MEM;
250 // Attach interrupt handler
251 esp_err_t ret = esp_intr_alloc(ETS_SDIO_HOST_INTR_SOURCE, 0, &sdmmc_isr, s_event_queue, &s_intr_handle);
253 vQueueDelete(s_event_queue);
254 s_event_queue = NULL;
255 vSemaphoreDelete(s_io_intr_event);
256 s_io_intr_event = NULL;
262 SDMMC_INTMASK_CMD_DONE |
263 SDMMC_INTMASK_DATA_OVER |
264 SDMMC_INTMASK_RCRC | SDMMC_INTMASK_DCRC |
265 SDMMC_INTMASK_RTO | SDMMC_INTMASK_DTO | SDMMC_INTMASK_HTO |
266 SDMMC_INTMASK_SBE | SDMMC_INTMASK_EBE |
267 SDMMC_INTMASK_RESP_ERR | SDMMC_INTMASK_HLE; //sdio is enabled only when use.
268 SDMMC.ctrl.int_enable = 1;
271 sdmmc_host_dma_init();
273 // Initialize transaction handler
274 ret = sdmmc_host_transaction_handler_init();
276 vQueueDelete(s_event_queue);
277 s_event_queue = NULL;
278 vSemaphoreDelete(s_io_intr_event);
279 s_io_intr_event = NULL;
280 esp_intr_free(s_intr_handle);
281 s_intr_handle = NULL;
288 static void configure_pin(int pin)
290 const int sdmmc_func = 3;
291 const int drive_strength = 3;
293 gpio_pulldown_dis(pin);
295 uint32_t reg = GPIO_PIN_MUX_REG[pin];
296 assert(reg != UINT32_MAX);
297 PIN_INPUT_ENABLE(reg);
298 PIN_FUNC_SELECT(reg, sdmmc_func);
299 PIN_SET_DRV(reg, drive_strength);
302 esp_err_t sdmmc_host_init_slot(int slot, const sdmmc_slot_config_t* slot_config)
304 bool pullup = slot_config->flags & SDMMC_SLOT_FLAG_INTERNAL_PULLUP;
306 sdmmc_host_pullup_en(slot, slot_config->width);
308 if (!s_intr_handle) {
309 return ESP_ERR_INVALID_STATE;
311 if (!(slot == 0 || slot == 1)) {
312 return ESP_ERR_INVALID_ARG;
314 if (slot_config == NULL) {
315 return ESP_ERR_INVALID_ARG;
317 int gpio_cd = slot_config->gpio_cd;
318 int gpio_wp = slot_config->gpio_wp;
319 uint8_t slot_width = slot_config->width;
322 const sdmmc_slot_info_t* pslot = &sdmmc_slot_info[slot];
324 if (slot_width == SDMMC_SLOT_WIDTH_DEFAULT) {
325 slot_width = pslot->width;
327 else if (slot_width > pslot->width) {
328 return ESP_ERR_INVALID_ARG;
330 s_slot_width[slot] = slot_width;
332 configure_pin(pslot->clk_gpio);
333 configure_pin(pslot->cmd_gpio);
334 configure_pin(pslot->d0_gpio);
336 if (slot_width >= 4) {
337 configure_pin(pslot->d1_gpio);
338 configure_pin(pslot->d2_gpio);
339 //force pull-up D3 to make slave detect SD mode. connect to peripheral after width configuration.
340 gpio_config_t gpio_conf = {
341 .pin_bit_mask = BIT(pslot->d3_gpio),
342 .mode = GPIO_MODE_OUTPUT ,
345 .intr_type = GPIO_INTR_DISABLE,
347 gpio_config( &gpio_conf );
348 gpio_set_level( pslot->d3_gpio, 1 );
349 if (slot_width == 8) {
350 configure_pin(pslot->d4_gpio);
351 configure_pin(pslot->d5_gpio);
352 configure_pin(pslot->d6_gpio);
353 configure_pin(pslot->d7_gpio);
357 // SDIO slave interrupt is edge sensitive to ~(int_n | card_int | card_detect)
358 // set this and card_detect to high to enable sdio interrupt
359 gpio_matrix_in(GPIO_FUNC_IN_HIGH, pslot->card_int, false);
361 // Set up Card Detect input
363 if (gpio_cd != SDMMC_SLOT_NO_CD) {
364 ESP_LOGD(TAG, "using GPIO%d as CD pin", gpio_cd);
365 gpio_pad_select_gpio(gpio_cd);
366 gpio_set_direction(gpio_cd, GPIO_MODE_INPUT);
367 matrix_in_cd = gpio_cd;
369 // if not set, default to CD low (card present)
370 matrix_in_cd = GPIO_FUNC_IN_LOW;
372 gpio_matrix_in(matrix_in_cd, pslot->card_detect, false);
374 // Set up Write Protect input
376 if (gpio_wp != SDMMC_SLOT_NO_WP) {
377 ESP_LOGD(TAG, "using GPIO%d as WP pin", gpio_wp);
378 gpio_pad_select_gpio(gpio_wp);
379 gpio_set_direction(gpio_wp, GPIO_MODE_INPUT);
380 matrix_in_wp = gpio_wp;
382 // if not set, default to WP high (not write protected)
383 matrix_in_wp = GPIO_FUNC_IN_HIGH;
385 // WP signal is normally active low, but hardware expects
386 // an active-high signal, so invert it in GPIO matrix
387 gpio_matrix_in(matrix_in_wp, pslot->write_protect, true);
389 // By default, set probing frequency (400kHz) and 1-bit bus
390 esp_err_t ret = sdmmc_host_set_card_clk(slot, 400);
394 ret = sdmmc_host_set_bus_width(slot, 1);
401 esp_err_t sdmmc_host_deinit()
403 if (!s_intr_handle) {
404 return ESP_ERR_INVALID_STATE;
406 esp_intr_free(s_intr_handle);
407 s_intr_handle = NULL;
408 vQueueDelete(s_event_queue);
409 s_event_queue = NULL;
410 vQueueDelete(s_io_intr_event);
411 s_io_intr_event = NULL;
412 sdmmc_host_input_clk_disable();
413 sdmmc_host_transaction_handler_deinit();
414 periph_module_disable(PERIPH_SDMMC_MODULE);
418 esp_err_t sdmmc_host_wait_for_event(int tick_count, sdmmc_event_t* out_event)
421 return ESP_ERR_INVALID_ARG;
423 if (!s_event_queue) {
424 return ESP_ERR_INVALID_STATE;
426 int ret = xQueueReceive(s_event_queue, out_event, tick_count);
427 if (ret == pdFALSE) {
428 return ESP_ERR_TIMEOUT;
433 esp_err_t sdmmc_host_set_bus_width(int slot, size_t width)
435 if (!(slot == 0 || slot == 1)) {
436 return ESP_ERR_INVALID_ARG;
438 if (sdmmc_slot_info[slot].width < width) {
439 return ESP_ERR_INVALID_ARG;
441 const uint16_t mask = BIT(slot);
443 SDMMC.ctype.card_width_8 &= ~mask;
444 SDMMC.ctype.card_width &= ~mask;
445 } else if (width == 4) {
446 SDMMC.ctype.card_width_8 &= ~mask;
447 SDMMC.ctype.card_width |= mask;
448 configure_pin(sdmmc_slot_info[slot].d3_gpio); // D3 was set to GPIO high to force slave into SD 1-bit mode, until 4-bit mode is set
449 } else if (width == 8){
450 SDMMC.ctype.card_width_8 |= mask;
451 configure_pin(sdmmc_slot_info[slot].d3_gpio); // D3 was set to GPIO high to force slave into SD 1-bit mode, until 4-bit mode is set
453 return ESP_ERR_INVALID_ARG;
455 ESP_LOGD(TAG, "slot=%d width=%d", slot, width);
459 size_t sdmmc_host_get_slot_width(int slot)
461 assert( slot == 0 || slot == 1 );
462 return s_slot_width[slot];
465 static void sdmmc_host_dma_init()
467 SDMMC.ctrl.dma_enable = 1;
469 SDMMC.bmod.sw_reset = 1;
470 SDMMC.idinten.ni = 1;
471 SDMMC.idinten.ri = 1;
472 SDMMC.idinten.ti = 1;
476 void sdmmc_host_dma_stop()
478 SDMMC.ctrl.use_internal_dma = 0;
479 SDMMC.ctrl.dma_reset = 1;
481 SDMMC.bmod.enable = 0;
484 void sdmmc_host_dma_prepare(sdmmc_desc_t* desc, size_t block_size, size_t data_size)
486 // Set size of data and DMA descriptor pointer
487 SDMMC.bytcnt = data_size;
488 SDMMC.blksiz = block_size;
491 // Enable everything needed to use DMA
492 SDMMC.ctrl.dma_enable = 1;
493 SDMMC.ctrl.use_internal_dma = 1;
494 SDMMC.bmod.enable = 1;
496 sdmmc_host_dma_resume();
499 void sdmmc_host_dma_resume()
504 esp_err_t sdmmc_host_io_int_enable(int slot)
506 configure_pin(sdmmc_slot_info[slot].d1_gpio);
510 esp_err_t sdmmc_host_io_int_wait(int slot, TickType_t timeout_ticks)
512 /* SDIO interrupts are negedge sensitive ones: the status bit is only set
513 * when first interrupt triggered.
515 * If D1 GPIO is low when entering this function, we know that interrupt
516 * (in SDIO sense) has occurred and we don't need to use SDMMC peripheral
520 SDMMC.intmask.sdio &= ~BIT(slot); /* Disable SDIO interrupt */
521 SDMMC.rintsts.sdio = BIT(slot);
522 if (gpio_get_level(sdmmc_slot_info[slot].d1_gpio) == 0) {
525 /* Otherwise, need to wait for an interrupt. Since D1 was high,
526 * SDMMC peripheral interrupt is guaranteed to trigger on negedge.
528 xSemaphoreTake(s_io_intr_event, 0);
529 SDMMC.intmask.sdio |= BIT(slot); /* Re-enable SDIO interrupt */
531 if (xSemaphoreTake(s_io_intr_event, timeout_ticks) == pdTRUE) {
534 return ESP_ERR_TIMEOUT;
539 * @brief SDMMC interrupt handler
541 * All communication in SD protocol is driven by the master, and the hardware
542 * handles things like stop commands automatically.
543 * So the interrupt handler doesn't need to do much, we just push interrupt
544 * status into a queue, clear interrupt flags, and let the task currently
545 * doing communication figure out what to do next.
546 * This also applies to SDIO interrupts which are generated by the slave.
548 * Card detect interrupts pose a small issue though, because if a card is
549 * plugged in and out a few times, while there is no task to process
550 * the events, event queue can become full and some card detect events
551 * may be dropped. We ignore this problem for now, since the there are no other
552 * interesting events which can get lost due to this.
554 static void sdmmc_isr(void* arg) {
555 QueueHandle_t queue = (QueueHandle_t) arg;
557 int higher_priority_task_awoken = pdFALSE;
559 uint32_t pending = SDMMC.mintsts.val & 0xFFFF;
560 SDMMC.rintsts.val = pending;
561 event.sdmmc_status = pending;
563 uint32_t dma_pending = SDMMC.idsts.val;
564 SDMMC.idsts.val = dma_pending;
565 event.dma_status = dma_pending & 0x1f;
567 if (pending != 0 || dma_pending != 0) {
568 xQueueSendFromISR(queue, &event, &higher_priority_task_awoken);
571 uint32_t sdio_pending = SDMMC.mintsts.sdio;
573 // disable the interrupt (no need to clear here, this is done in sdmmc_host_io_wait_int)
574 SDMMC.intmask.sdio &= ~sdio_pending;
575 xSemaphoreGiveFromISR(s_io_intr_event, &higher_priority_task_awoken);
578 if (higher_priority_task_awoken == pdTRUE) {
579 portYIELD_FROM_ISR();
583 esp_err_t sdmmc_host_pullup_en(int slot, int width)
585 if (width > sdmmc_slot_info[slot].width) {
586 //in esp32 we only support 8 bit in slot 0, note this is occupied by the flash by default
587 return ESP_ERR_INVALID_ARG;
589 //according to the spec, the host control the clk, we don't to pull it up here
590 gpio_pullup_en(sdmmc_slot_info[slot].cmd_gpio);
591 gpio_pullup_en(sdmmc_slot_info[slot].d0_gpio);
593 gpio_pullup_en(sdmmc_slot_info[slot].d1_gpio);
594 gpio_pullup_en(sdmmc_slot_info[slot].d2_gpio);
595 gpio_pullup_en(sdmmc_slot_info[slot].d3_gpio);
598 gpio_pullup_en(sdmmc_slot_info[slot].d4_gpio);
599 gpio_pullup_en(sdmmc_slot_info[slot].d5_gpio);
600 gpio_pullup_en(sdmmc_slot_info[slot].d6_gpio);
601 gpio_pullup_en(sdmmc_slot_info[slot].d7_gpio);