1 /******************************************************************************
\r
3 * Copyright 2013 Altera Corporation. All Rights Reserved.
\r
5 * Redistribution and use in source and binary forms, with or without
\r
6 * modification, are permitted provided that the following conditions are met:
\r
8 * 1. Redistributions of source code must retain the above copyright notice,
\r
9 * this list of conditions and the following disclaimer.
\r
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
\r
12 * this list of conditions and the following disclaimer in the documentation
\r
13 * and/or other materials provided with the distribution.
\r
15 * 3. The name of the author may not be used to endorse or promote products
\r
16 * derived from this software without specific prior written permission.
\r
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR
\r
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
\r
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO
\r
21 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
\r
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
\r
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
\r
24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
\r
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
\r
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
\r
27 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
29 ******************************************************************************/
\r
31 #include "alt_sdmmc.h"
\r
32 #include "alt_clock_manager.h"
\r
33 #include "alt_reset_manager.h"
\r
34 #include "socal/alt_sdmmc.h"
\r
35 #include "socal/alt_rstmgr.h"
\r
36 #include "socal/hps.h"
\r
37 #include "socal/socal.h"
\r
43 // NOTE: To enable debugging output, delete the next line and uncomment the
\r
45 //#define dprintf(...)
\r
46 #define dprintf(fmt, ...) printf(fmt, ##__VA_ARGS__)
\r
52 #define MIN(a, b) ((a) > (b) ? (b) : (a))
\r
53 #define ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0]))
\r
57 // Timeout for reset manager
\r
58 #define ALT_SDMMC_RESET_TMO_INIT 8192
\r
59 // Timeout for disable device
\r
60 #define ALT_SDMMC_MAX_T_POLL_COUNT 8192
\r
61 // Timeout for waiting event
\r
62 #define ALT_SDMMC_TMO_WAITER 1000000
\r
64 #define ALT_SDMMC_DMA_SEGMENT_SIZE 512
\r
65 #define ALT_SDMMC_DMA_DESC_COUNT 128
\r
67 #define ALT_SDMMC_FSM_IDLE 0
\r
68 #define ALT_SDMMC_DMA_FSM_IDLE 0
\r
70 #define ALT_SDMMC_CSD_MAX_R_BLK_MSK 0x000F0000
\r
71 #define ALT_SDMMC_CSD_MAX_W_BLK_MSK 0x03C00000
\r
72 #define ALT_SDMMC_CSD_PART_R_ALLOW_MSK 0x00008000
\r
73 #define ALT_SDMMC_CSD_PART_W_ALLOW_MSK 0x00200000
\r
74 #define ALT_SDMMC_CSD_SPEED_RATE_MSK 0x00000007
\r
75 #define ALT_SDMMC_CSD_SPEED_TIME_MSK 0x00000078
\r
76 #define ALT_SDMMC_CSD_MAX_R_BLK_GET(val) ((val & ALT_SDMMC_CSD_MAX_R_BLK_MSK) >> 16)
\r
77 #define ALT_SDMMC_CSD_MAX_W_BLK_GET(val) ((val & ALT_SDMMC_CSD_MAX_W_BLK_MSK) >> 22)
\r
78 #define ALT_SDMMC_CSD_PART_R_ALLOW_GET(val) ((val & ALT_SDMMC_CSD_PART_R_ALLOW_MSK) >> 15)
\r
79 #define ALT_SDMMC_CSD_PART_W_ALLOW_GET(val) ((val & ALT_SDMMC_CSD_PART_W_ALLOW_MSK) >> 21)
\r
80 #define ALT_SDMMC_CSD_SPEED_RATE_GET(val) ((val & ALT_SDMMC_CSD_SPEED_RATE_MSK) >> 0)
\r
81 #define ALT_SDMMC_CSD_SPEED_TIME_GET(val) ((val & ALT_SDMMC_CSD_SPEED_TIME_MSK) >> 3)
\r
82 typedef enum ALT_SDMMC_TMOD_e
\r
84 ALT_SDMMC_TMOD_READ = 0,
\r
85 ALT_SDMMC_TMOD_WRITE = 1,
\r
89 uint32_t log_buffer[1000] = { 0 };
\r
90 uint32_t log_index = 0;
\r
92 #define D_ADD_VALUE(value)({if (log_index < 1000) log_buffer[log_index++] = value;})
\r
95 static alt_freq_t clock_freq;
\r
97 // Default configurations of used commands
\r
98 static ALT_SDMMC_CMD_CONFIG_t cmd_default_cfg[20] =
\r
101 .cmd_index = ALT_SDMMC_WRITE_MULTIPLE_BLOCK,
\r
102 .send_auto_stop = true,
\r
103 .response_expect = true,
\r
104 .data_expected = 1,
\r
105 .write_active = true,
\r
107 .use_hold_reg = true,
\r
108 .wait_prvdata_complete = true
\r
111 .cmd_index = ALT_SDMMC_READ_MULTIPLE_BLOCK,
\r
112 .send_auto_stop = true,
\r
113 .response_expect = true,
\r
114 .data_expected = 1,
\r
116 .use_hold_reg = true,
\r
117 .wait_prvdata_complete = true
\r
120 .cmd_index = ALT_SD_SEND_SCR,
\r
121 .response_expect = true,
\r
122 .data_expected = true,
\r
124 .use_hold_reg = true,
\r
125 .wait_prvdata_complete = true
\r
128 .cmd_index = ALT_SDMMC_WRITE_BLOCK,
\r
129 .response_expect = true,
\r
130 .data_expected = true,
\r
131 .write_active = true,
\r
133 .use_hold_reg = true,
\r
134 .wait_prvdata_complete = true
\r
137 .cmd_index = ALT_SDMMC_READ_SINGLE_BLOCK,
\r
138 .response_expect = true,
\r
139 .data_expected = true,
\r
141 .use_hold_reg = true,
\r
142 .wait_prvdata_complete = true
\r
145 .cmd_index = ALT_SDMMC_SET_BLOCKLEN,
\r
146 .response_expect = true,
\r
148 .use_hold_reg = true,
\r
149 .wait_prvdata_complete = true
\r
152 .cmd_index = ALT_SDMMC_SEL_DES_CARD,
\r
153 .response_expect = true,
\r
155 .use_hold_reg = true,
\r
156 .wait_prvdata_complete = true
\r
159 .cmd_index = ALT_SDMMC_APP_CMD,
\r
160 .response_expect = true,
\r
162 .use_hold_reg = true,
\r
163 .wait_prvdata_complete = true
\r
166 .cmd_index = ALT_SD_SET_BUS_WIDTH,
\r
167 .response_expect = true,
\r
169 .use_hold_reg = true,
\r
170 .wait_prvdata_complete = true
\r
173 .cmd_index = ALT_SD_SEND_OP_COND,
\r
174 .response_expect = true,
\r
176 .use_hold_reg = true,
\r
177 .wait_prvdata_complete = true
\r
180 .cmd_index = ALT_SDMMC_SEND_OP_COND,
\r
181 .response_expect = true,
\r
183 .use_hold_reg = true,
\r
184 .wait_prvdata_complete = true
\r
187 .cmd_index = ALT_SDMMC_IF_COND,
\r
188 .response_expect = true,
\r
190 .use_hold_reg = true,
\r
191 .wait_prvdata_complete = true
\r
194 .cmd_index = ALT_SDMMC_SET_RELATIVE_ADDR,
\r
195 .response_expect = true,
\r
197 .use_hold_reg = true,
\r
198 .wait_prvdata_complete = true
\r
201 .cmd_index = ALT_SDMMC_SEND_STATUS,
\r
202 .response_expect = true,
\r
204 .use_hold_reg = true
\r
207 .cmd_index = ALT_SDMMC_ALL_SEND_CID,
\r
208 .response_expect = true,
\r
209 .response_length_long = true,
\r
211 .use_hold_reg = true,
\r
212 .wait_prvdata_complete = true
\r
215 .cmd_index = ALT_SDMMC_SEND_CID,
\r
216 .response_expect = true,
\r
217 .response_length_long = true,
\r
219 .use_hold_reg = true,
\r
220 .wait_prvdata_complete = true
\r
223 .cmd_index = ALT_SDMMC_SEND_CSD,
\r
224 .response_expect = true,
\r
225 .response_length_long = true,
\r
227 .use_hold_reg = true,
\r
228 .wait_prvdata_complete = true
\r
231 .cmd_index = ALT_SDMMC_STOP_TRANSMISSION,
\r
232 .stop_abort_cmd = true,
\r
234 .use_hold_reg = true,
\r
235 .wait_prvdata_complete = true
\r
238 .cmd_index = ALT_SDMMC_GO_IDLE_STATE,
\r
239 .send_initialization = true,
\r
241 .use_hold_reg = true,
\r
242 .wait_prvdata_complete = true
\r
246 static ALT_SDMMC_CMD_CONFIG_t cmd_clock_cfg =
\r
248 .update_clock_registers_only = true,
\r
249 .wait_prvdata_complete = true
\r
252 static uint32_t rca_number; /*!< Relative card address. */
\r
253 static ALT_SDMMC_DMA_BUF_DESC_t dma_descriptors[ALT_SDMMC_DMA_DESC_COUNT];
\r
254 /*!< Array of dma descriptors. */
\r
255 static ALT_SDMMC_DMA_BUF_DESC_t *dma_cur_descr;
\r
256 /*!< Current decriptor. */
\r
259 // Reset sdmmc module by reset manager without deassert
\r
261 static ALT_STATUS_CODE alt_sdmmc_rstmgr_set(void)
\r
263 alt_setbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_SDMMC_SET_MSK);
\r
265 return ALT_E_SUCCESS;
\r
269 // Assert reset sdmmc module by reset manager, wait, deasert
\r
271 static ALT_STATUS_CODE alt_sdmmc_rstmgr_strobe(void)
\r
273 alt_setbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_SDMMC_SET_MSK);
\r
275 volatile uint32_t timeout = ALT_SDMMC_RESET_TMO_INIT;
\r
277 // Wait while sdmmc module is reseting
\r
281 // Deassert the appropriate sdmmc module reset signal via the Reset Manager Peripheral Reset register.
\r
282 alt_clrbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_SDMMC_SET_MSK);
\r
284 return ALT_E_SUCCESS;
\r
288 // Initialize descriptor chain for dma
\r
290 static ALT_STATUS_CODE alt_sdmmc_desc_chain_init()
\r
292 ALT_SDMMC_DMA_BUF_DESC_t * dma_desc = dma_descriptors;
\r
294 // Initialising descriptor chain
\r
295 for (uint32_t count = 0; count < ALT_SDMMC_DMA_DESC_COUNT; count++)
\r
297 dma_desc[count].des0.fld.own = 0;
\r
298 dma_desc[count].des0.fld.ch = 1;
\r
299 dma_desc[count].des0.fld.er = 0;
\r
300 dma_desc[count].des1.fld.bs1 = 0;
\r
301 dma_desc[count].des2.fld.bap1 = 0;
\r
303 // Create chain description list
\r
304 if (count == (ALT_SDMMC_DMA_DESC_COUNT - 1))
\r
306 // If it is latest element set pointer to the ring head.
\r
307 dma_desc[count].des3.fld.bap2_or_next = (uint32_t) dma_desc;
\r
311 // Set pointer to the next element in the ring
\r
312 dma_desc[count].des3.fld.bap2_or_next = (uint32_t) (&dma_desc[count + 1]);
\r
316 dma_cur_descr = dma_desc;
\r
318 return ALT_E_SUCCESS;
\r
322 // Clear descriptors of chain for dma operations
\r
324 static ALT_STATUS_CODE alt_sdmmc_desc_chain_clear()
\r
326 ALT_SDMMC_DMA_BUF_DESC_t * dma_desc = dma_descriptors;
\r
328 // Clean descriptions
\r
329 for (uint32_t count = 0; count < ALT_SDMMC_DMA_DESC_COUNT; count++)
\r
331 dma_desc[count].des0.fld.own = 0;
\r
332 dma_desc[count].des0.fld.dic = 0;
\r
333 dma_desc[count].des0.fld.ld = 0;
\r
334 dma_desc[count].des0.fld.fs = 0;
\r
335 dma_desc[count].des1.fld.bs1 = 0;
\r
336 dma_desc[count].des2.fld.bap1 = 0;
\r
339 dma_cur_descr = dma_desc;
\r
341 return ALT_E_SUCCESS;
\r
345 // Initialize the specified sdmmc controller instance for use and return a device
\r
346 // handle referencing it.
\r
348 ALT_STATUS_CODE alt_sdmmc_init()
\r
350 if (alt_clk_is_enabled(ALT_CLK_SDMMC) != ALT_E_TRUE)
\r
352 return ALT_E_BAD_CLK;
\r
357 ALT_STATUS_CODE status = ALT_E_SUCCESS;
\r
359 // Query the SDMMC clock.
\r
360 if (status == ALT_E_SUCCESS)
\r
362 status = alt_clk_freq_get(ALT_CLK_SDMMC, &clock_freq);
\r
365 // Reset sdmmc module
\r
366 if (status == ALT_E_SUCCESS)
\r
368 status = alt_sdmmc_reset();
\r
375 //Reset the SD/MMC controller by stopping any data transfers in progress and
\r
376 //putting the controller into reset and reinit it after reset complete.
\r
378 ALT_STATUS_CODE alt_sdmmc_reset()
\r
380 ALT_STATUS_CODE status = ALT_E_SUCCESS;
\r
382 bool already_enabled = (alt_sdmmc_card_pwr_is_on() == ALT_E_TRUE);
\r
384 if (already_enabled)
\r
386 // Temporarily power off the card
\r
387 status = alt_sdmmc_card_pwr_off();
\r
388 if (status != ALT_E_SUCCESS)
\r
394 // Reset sdmmc module by reset manager
\r
395 alt_sdmmc_rstmgr_strobe();
\r
397 if (already_enabled)
\r
399 // Re-enable card power
\r
400 status = alt_sdmmc_card_pwr_on();
\r
403 // Relative card address have not readed yet
\r
405 // Init description chain
\r
406 alt_sdmmc_desc_chain_init();
\r
408 if (status == ALT_E_SUCCESS)
\r
410 //Enable default clock for working alt_sdmmc_command_send
\r
411 alt_write_word(ALT_SDMMC_CLKENA_ADDR, ALT_SDMMC_CLKENA_CCLK_EN_SET(true));
\r
412 status = alt_sdmmc_command_send(ALT_SDMMC_CLK_INDEX, 0x0, NULL);
\r
419 // Uninitialize the sdmmc controller referenced by the sdmmc_dev handle.
\r
421 ALT_STATUS_CODE alt_sdmmc_uninit(void)
\r
423 ALT_STATUS_CODE status = ALT_E_SUCCESS;
\r
425 // Clean descriptor chain
\r
426 alt_sdmmc_desc_chain_clear();
\r
429 if (status == ALT_E_SUCCESS)
\r
431 status = alt_sdmmc_card_pwr_off();
\r
434 // Reset sdmmc module by reset manager
\r
435 if (status == ALT_E_SUCCESS)
\r
437 status = alt_sdmmc_rstmgr_set();
\r
444 // Power on of the card.
\r
446 ALT_STATUS_CODE alt_sdmmc_card_pwr_on(void)
\r
448 alt_setbits_word(ALT_SDMMC_PWREN_ADDR,
\r
449 ALT_SDMMC_PWREN_POWER_EN_SET_MSK);
\r
451 return ALT_E_SUCCESS;
\r
455 //Power off of the card.
\r
457 ALT_STATUS_CODE alt_sdmmc_card_pwr_off(void)
\r
459 //If sdmmc controller is enabled, return with sucess
\r
460 if (alt_sdmmc_card_pwr_is_on() == ALT_E_FALSE)
\r
462 return ALT_E_SUCCESS;
\r
465 //Else clear enable bit of sdmmc_enable register
\r
466 alt_clrbits_word(ALT_SDMMC_PWREN_ADDR,
\r
467 ALT_SDMMC_PWREN_POWER_EN_SET_MSK);
\r
469 // Clear interrupt status
\r
470 alt_sdmmc_int_clear(ALT_SDMMC_INT_STATUS_ALL);
\r
472 // Relative card address have not readed yet
\r
474 // Reset state of card stack
\r
475 return ALT_E_SUCCESS;
\r
479 // Check whether sdmmc controller is enable
\r
481 bool alt_sdmmc_card_pwr_is_on(void)
\r
483 if (ALT_SDMMC_PWREN_POWER_EN_GET(alt_read_word(ALT_SDMMC_PWREN_ADDR)) ==
\r
484 ALT_SDMMC_PWREN_POWER_EN_E_ON)
\r
495 // Returns ALT_E_TRUE if the sdmmc controller is busy
\r
497 static ALT_STATUS_CODE alt_sdmmc_is_busy(void)
\r
499 if (ALT_SDMMC_STAT_DATA_BUSY_GET(alt_read_word(ALT_SDMMC_STAT_ADDR)) ==
\r
500 ALT_SDMMC_STAT_DATA_BUSY_E_CARDBUSY)
\r
506 return ALT_E_FALSE;
\r
511 // Returns ALT_E_TRUE if the sdmmc and iddmac controller is in idle state
\r
513 static ALT_STATUS_CODE alt_sdmmc_is_idle(void)
\r
515 uint32_t mmc_state = ALT_SDMMC_STAT_CMD_FSM_STATES_GET(alt_read_word(ALT_SDMMC_STAT_ADDR));
\r
517 uint32_t dma_state = ALT_SDMMC_IDSTS_FSM_GET(alt_read_word(ALT_SDMMC_IDSTS_ADDR));
\r
519 if ((mmc_state != ALT_SDMMC_FSM_IDLE) || (dma_state != ALT_SDMMC_DMA_FSM_IDLE))
\r
522 dprintf("\nstate %x dma_state %x\n", (int)mmc_state, (int)dma_state);
\r
524 return ALT_E_FALSE;
\r
533 // Get config clock parameters
\r
535 uint32_t alt_sdmmc_card_clk_div_get(void)
\r
537 return ALT_SDMMC_CLKDIV_CLK_DIVR0_GET(alt_read_word(ALT_SDMMC_CLKDIV_ADDR));
\r
541 // Set config clock parameters (7.2.3 Clock Programming)
\r
543 ALT_STATUS_CODE alt_sdmmc_card_clk_div_set(const uint32_t clk_div)
\r
545 if (alt_sdmmc_is_busy() == ALT_E_TRUE)
\r
547 return ALT_E_ERROR;
\r
550 alt_write_word(ALT_SDMMC_CLKDIV_ADDR, ALT_SDMMC_CLKDIV_CLK_DIVR0_SET(clk_div));
\r
552 return alt_sdmmc_command_send(ALT_SDMMC_CLK_INDEX, 0x0, NULL);
\r
555 uint32_t alt_sdmmc_card_speed_get(void)
\r
557 uint32_t clk_div = alt_sdmmc_card_clk_div_get();
\r
559 uint32_t speed_bps = clock_freq / (2 * clk_div);
\r
564 ALT_STATUS_CODE alt_sdmmc_card_speed_set(uint32_t xfer_speed)
\r
566 uint32_t clk_div = clock_freq / (2 * xfer_speed);
\r
568 return alt_sdmmc_card_clk_div_set(clk_div);
\r
571 ALT_STATUS_CODE alt_sdmmc_card_clk_disable(void)
\r
573 if (alt_sdmmc_is_busy() == ALT_E_TRUE)
\r
575 return ALT_E_ERROR;
\r
578 alt_write_word(ALT_SDMMC_CLKENA_ADDR, ALT_SDMMC_CLKENA_CCLK_EN_SET(false));
\r
580 return alt_sdmmc_command_send(ALT_SDMMC_CLK_INDEX, 0x0, NULL);
\r
584 // Enables the card clock (sdmmc_cclk_out).
\r
586 ALT_STATUS_CODE alt_sdmmc_card_clk_enable(const bool use_low_pwr_mode)
\r
588 if (alt_sdmmc_is_busy() == ALT_E_TRUE)
\r
590 return ALT_E_ERROR;
\r
594 alt_write_word(ALT_SDMMC_CLKENA_ADDR, ALT_SDMMC_CLKENA_CCLK_EN_SET(true)
\r
595 | ALT_SDMMC_CLKENA_CCLK_LOW_POWER_SET(use_low_pwr_mode));
\r
597 return alt_sdmmc_command_send(ALT_SDMMC_CLK_INDEX, 0x0, NULL);
\r
601 // Returns true if the card clock (sdmmc_cclk_out) is enabled otherwise returns
\r
603 bool alt_sdmmc_card_clk_is_enabled(void)
\r
605 return ALT_SDMMC_CLKENA_CCLK_EN_GET(alt_read_word(ALT_SDMMC_CLKENA_ADDR));
\r
609 // Get sdmmc bus width
\r
611 static ALT_SDMMC_BUS_WIDTH_t alt_sdmmc_bus_width_get(void)
\r
613 uint32_t ctype_register = alt_read_word(ALT_SDMMC_CTYPE_ADDR);
\r
615 uint16_t card_width1 = ALT_SDMMC_CTYPE_CARD_WIDTH1_GET(ctype_register);
\r
616 uint16_t card_width2 = ALT_SDMMC_CTYPE_CARD_WIDTH2_GET(ctype_register);
\r
618 if (card_width1 == ALT_SDMMC_CTYPE_CARD_WIDTH1_E_MOD8BIT)
\r
620 return ALT_SDMMC_BUS_WIDTH_8;
\r
622 else if (card_width2 == ALT_SDMMC_CTYPE_CARD_WIDTH2_E_MOD4BIT)
\r
624 return ALT_SDMMC_BUS_WIDTH_4;
\r
628 return ALT_SDMMC_BUS_WIDTH_1;
\r
633 // Set sdmmc bus width
\r
635 static ALT_STATUS_CODE alt_sdmmc_bus_width_set(const ALT_SDMMC_BUS_WIDTH_t width)
\r
637 // Set config parameters to appropriate registers
\r
640 case ALT_SDMMC_BUS_WIDTH_8:
\r
641 alt_replbits_word(ALT_SDMMC_CTYPE_ADDR,
\r
642 ALT_SDMMC_CTYPE_CARD_WIDTH1_SET_MSK,
\r
643 ALT_SDMMC_CTYPE_CARD_WIDTH1_SET(ALT_SDMMC_CTYPE_CARD_WIDTH1_E_MOD8BIT));
\r
646 case ALT_SDMMC_BUS_WIDTH_4:
\r
647 alt_replbits_word(ALT_SDMMC_CTYPE_ADDR,
\r
648 ALT_SDMMC_CTYPE_CARD_WIDTH1_SET_MSK,
\r
649 ALT_SDMMC_CTYPE_CARD_WIDTH1_SET(ALT_SDMMC_CTYPE_CARD_WIDTH1_E_NON8BIT));
\r
650 alt_replbits_word(ALT_SDMMC_CTYPE_ADDR,
\r
651 ALT_SDMMC_CTYPE_CARD_WIDTH2_SET_MSK,
\r
652 ALT_SDMMC_CTYPE_CARD_WIDTH2_SET(ALT_SDMMC_CTYPE_CARD_WIDTH2_E_MOD4BIT));
\r
655 case ALT_SDMMC_BUS_WIDTH_1:
\r
656 alt_replbits_word(ALT_SDMMC_CTYPE_ADDR,
\r
657 ALT_SDMMC_CTYPE_CARD_WIDTH1_SET_MSK,
\r
658 ALT_SDMMC_CTYPE_CARD_WIDTH1_SET(ALT_SDMMC_CTYPE_CARD_WIDTH1_E_NON8BIT));
\r
659 alt_replbits_word(ALT_SDMMC_CTYPE_ADDR,
\r
660 ALT_SDMMC_CTYPE_CARD_WIDTH2_SET_MSK,
\r
661 ALT_SDMMC_CTYPE_CARD_WIDTH2_SET(ALT_SDMMC_CTYPE_CARD_WIDTH2_E_MOD1BIT));
\r
665 return ALT_E_BAD_ARG;
\r
668 return ALT_E_SUCCESS;
\r
674 inline static uint16_t alt_sdmmc_block_size_get(void)
\r
676 uint32_t blksiz_register = alt_read_word(ALT_SDMMC_BLKSIZ_ADDR);
\r
677 return ALT_SDMMC_BLKSIZ_BLOCK_SIZE_GET(blksiz_register);
\r
683 inline static ALT_STATUS_CODE alt_sdmmc_block_size_set(uint16_t block_size)
\r
685 alt_replbits_word(ALT_SDMMC_BLKSIZ_ADDR,
\r
686 ALT_SDMMC_BLKSIZ_BLOCK_SIZE_SET_MSK,
\r
687 ALT_SDMMC_BLKSIZ_BLOCK_SIZE_SET(block_size));
\r
689 return ALT_E_SUCCESS;
\r
695 inline static ALT_STATUS_CODE alt_sdmmc_byte_count_set(uint32_t count)
\r
697 alt_replbits_word(ALT_SDMMC_BYTCNT_ADDR,
\r
698 ALT_SDMMC_BYTCNT_BYTE_COUNT_SET_MSK,
\r
699 ALT_SDMMC_BYTCNT_BYTE_COUNT_SET(count));
\r
701 return ALT_E_SUCCESS;
\r
705 // Get sdmmc timeouts for command response and data sending
\r
707 ALT_STATUS_CODE alt_sdmmc_card_misc_get(ALT_SDMMC_CARD_MISC_t *card_misc_cfg)
\r
709 uint32_t tmout_register = alt_read_word(ALT_SDMMC_TMOUT_ADDR);
\r
711 card_misc_cfg->response_timeout = ALT_SDMMC_TMOUT_RESPONSE_TMO_GET(tmout_register);
\r
712 card_misc_cfg->data_timeout = ALT_SDMMC_TMOUT_DATA_TMO_GET(tmout_register);
\r
714 card_misc_cfg->card_width = alt_sdmmc_bus_width_get();
\r
715 card_misc_cfg->block_size = alt_sdmmc_block_size_get();
\r
717 card_misc_cfg->debounce_count = ALT_SDMMC_DEBNCE_DEBOUNCE_COUNT_GET(alt_read_word(ALT_SDMMC_DEBNCE_ADDR));
\r
719 return ALT_E_SUCCESS;
\r
723 //Set sdmmc timeouts for command response and data sending
\r
725 ALT_STATUS_CODE alt_sdmmc_card_misc_set(const ALT_SDMMC_CARD_MISC_t *card_misc_cfg)
\r
727 uint32_t tmout_value = ALT_SDMMC_TMOUT_RESPONSE_TMO_SET(card_misc_cfg->response_timeout)
\r
728 | ALT_SDMMC_TMOUT_DATA_TMO_SET(card_misc_cfg->data_timeout);
\r
730 alt_write_word(ALT_SDMMC_TMOUT_ADDR, tmout_value);
\r
732 alt_replbits_word(ALT_SDMMC_DEBNCE_ADDR,
\r
733 ALT_SDMMC_DEBNCE_DEBOUNCE_COUNT_SET_MSK,
\r
734 ALT_SDMMC_DEBNCE_DEBOUNCE_COUNT_SET(card_misc_cfg->debounce_count));
\r
736 ALT_STATUS_CODE status = ALT_E_SUCCESS;
\r
738 if (status == ALT_E_SUCCESS)
\r
740 status = alt_sdmmc_bus_width_set(card_misc_cfg->card_width);
\r
743 if (status == ALT_E_SUCCESS)
\r
745 status = alt_sdmmc_block_size_set(card_misc_cfg->block_size);
\r
752 // Starts the SD/MMC internal DMA transfer with the specified
\r
753 // descriptor an bus mode transfer configuration.
\r
755 ALT_STATUS_CODE alt_sdmmc_dma_start(ALT_SDMMC_DMA_BUF_DESC_t *buf_desc_list,
\r
756 const uint32_t desc_skip_len,
\r
757 const ALT_SDMMC_DMA_PBL_t burst_len,
\r
758 const bool use_fixed_burst)
\r
760 uint32_t bmod_set_value = ALT_SDMMC_BMOD_PBL_SET(burst_len)
\r
761 | ALT_SDMMC_BMOD_FB_SET(use_fixed_burst)
\r
762 | ALT_SDMMC_BMOD_DSL_SET(desc_skip_len);
\r
764 uint32_t bmod_set_mask = ALT_SDMMC_BMOD_PBL_SET_MSK
\r
765 | ALT_SDMMC_BMOD_FB_SET_MSK
\r
766 | ALT_SDMMC_BMOD_DSL_SET_MSK;
\r
768 alt_replbits_word(ALT_SDMMC_BMOD_ADDR, bmod_set_mask, bmod_set_value);
\r
770 // Set start address of descriptor chain
\r
771 alt_write_word(ALT_SDMMC_DBADDR_ADDR, (uint32_t)buf_desc_list);
\r
773 return ALT_E_SUCCESS;
\r
777 // Enables the sdmmc write protect.
\r
779 bool alt_sdmmc_card_is_write_protected(void)
\r
781 alt_setbits_word(ALT_SDMMC_WRTPRT_ADDR,
\r
782 ALT_SDMMC_WRTPRT_WR_PROTECT_SET_MSK);
\r
784 return ALT_E_SUCCESS;
\r
790 ALT_STATUS_CODE alt_sdmmc_fifo_reset(void)
\r
792 uint32_t timeout = ALT_SDMMC_MAX_T_POLL_COUNT;
\r
794 // Activate fifo reset
\r
795 alt_setbits_word(ALT_SDMMC_CTL_ADDR, ALT_SDMMC_CTL_FIFO_RST_SET_MSK);
\r
797 // Wait to complete reset or timeout
\r
798 while (ALT_SDMMC_CTL_FIFO_RST_GET(alt_read_word(ALT_SDMMC_CTL_ADDR))
\r
802 // If fifo reset still are active, return timeout error
\r
808 return ALT_E_SUCCESS;
\r
814 ALT_STATUS_CODE alt_sdmmc_dma_reset(void)
\r
816 uint32_t timeout = ALT_SDMMC_MAX_T_POLL_COUNT;
\r
818 //Activate dma reset
\r
819 alt_setbits_word(ALT_SDMMC_CTL_ADDR, ALT_SDMMC_CTL_DMA_RST_SET_MSK);
\r
821 // Wait to complete reset or timeout
\r
822 while (ALT_SDMMC_CTL_DMA_RST_GET(alt_read_word(ALT_SDMMC_CTL_ADDR))
\r
826 // If dma reset still are active, return timeout error
\r
832 return ALT_E_SUCCESS;
\r
837 // Returns ALT_E_TRUE if the sdmmc controller is present depend on cdata_in.
\r
839 bool alt_sdmmc_card_is_detected(void)
\r
841 if (ALT_SDMMC_STAT_DATA_3_STAT_GET(alt_read_word(ALT_SDMMC_STAT_ADDR)) ==
\r
842 ALT_SDMMC_STAT_DATA_3_STAT_E_CARDPRESENT)
\r
843 // if (ALT_SDMMC_CDETECT_CARD_DETECT_N_GET(alt_read_word(ALT_SDMMC_CDETECT_ADDR))
\r
844 // == ALT_SDMMC_CDETECT_CARD_DETECT_N_E_DETECTED)
\r
855 //Set command configuration
\r
857 static ALT_STATUS_CODE alt_sdmmc_cmd_set(const ALT_SDMMC_CMD_INDEX_t cmd_index,
\r
858 const ALT_SDMMC_CMD_CONFIG_t *cmd_cfg,
\r
861 uint32_t cmd_register = ALT_SDMMC_CMD_CMD_INDEX_SET(cmd_index)
\r
862 | ALT_SDMMC_CMD_RESPONSE_EXPECT_SET(cmd_cfg->response_expect)
\r
863 | ALT_SDMMC_CMD_RESPONSE_LEN_SET(cmd_cfg->response_length_long)
\r
864 | ALT_SDMMC_CMD_CHECK_RESPONSE_CRC_SET(cmd_cfg->check_response_crc)
\r
865 | ALT_SDMMC_CMD_DATA_EXPECTED_SET(cmd_cfg->data_expected)
\r
866 | ALT_SDMMC_CMD_RD_WR_SET(cmd_cfg->write_active)
\r
867 | ALT_SDMMC_CMD_TFR_MOD_SET(cmd_cfg->stream_mode_active)
\r
868 | ALT_SDMMC_CMD_SEND_AUTO_STOP_SET(cmd_cfg->send_auto_stop)
\r
869 | ALT_SDMMC_CMD_WAIT_PRVDATA_COMPLETE_SET(cmd_cfg->wait_prvdata_complete)
\r
870 | ALT_SDMMC_CMD_STOP_ABT_CMD_SET(cmd_cfg->stop_abort_cmd)
\r
871 | ALT_SDMMC_CMD_SEND_INITIALIZATION_SET(cmd_cfg->send_initialization)
\r
872 | ALT_SDMMC_CMD_UPDATE_CLK_REGS_ONLY_SET(cmd_cfg->update_clock_registers_only)
\r
873 | ALT_SDMMC_CMD_RD_CEATA_DEVICE_SET(cmd_cfg->read_ceata_device)
\r
874 | ALT_SDMMC_CMD_CCS_EXPECTED_SET(cmd_cfg->ccs_expected)
\r
875 | ALT_SDMMC_CMD_EN_BOOT_SET(cmd_cfg->enable_boot)
\r
876 | ALT_SDMMC_CMD_EXPECT_BOOT_ACK_SET(cmd_cfg->expect_boot_ack)
\r
877 | ALT_SDMMC_CMD_DIS_BOOT_SET(cmd_cfg->disable_boot)
\r
878 | ALT_SDMMC_CMD_BOOT_MOD_SET(cmd_cfg->boot_mode)
\r
879 | ALT_SDMMC_CMD_VOLT_SWITCH_SET(cmd_cfg->volt_switch)
\r
880 | ALT_SDMMC_CMD_USE_HOLD_REG_SET(cmd_cfg->use_hold_reg)
\r
881 | ALT_SDMMC_CMD_START_CMD_SET(start_cmd);
\r
883 alt_write_word(ALT_SDMMC_CMD_ADDR, cmd_register);
\r
886 dprintf("\ncommand = %X\n", (int)cmd_register);
\r
889 return ALT_E_SUCCESS;
\r
893 // Set command argument
\r
895 inline static ALT_STATUS_CODE alt_sdmmc_cmd_arg_set(uint32_t cmdarg)
\r
897 alt_write_word(ALT_SDMMC_CMDARG_ADDR, cmdarg);
\r
899 return ALT_E_SUCCESS;
\r
903 // Get response previous command.
\r
905 inline static ALT_STATUS_CODE alt_sdmmc_read_short_response(uint32_t *response)
\r
907 uint32_t resp0 = alt_read_word(ALT_SDMMC_RESP0_ADDR);
\r
908 *response = (uint32_t)(ALT_SDMMC_RESP0_RESPONSE0_GET(resp0));
\r
910 return ALT_E_SUCCESS;
\r
914 // Get long response of previous command.
\r
916 ALT_STATUS_CODE alt_sdmmc_read_long_response(ALT_SDMMC_RESPONSE_t *response)
\r
918 uint32_t resp0 = alt_read_word(ALT_SDMMC_RESP0_ADDR);
\r
919 uint32_t resp1 = alt_read_word(ALT_SDMMC_RESP1_ADDR);
\r
920 uint32_t resp2 = alt_read_word(ALT_SDMMC_RESP2_ADDR);
\r
921 uint32_t resp3 = alt_read_word(ALT_SDMMC_RESP3_ADDR);
\r
923 response->resp0 = (uint32_t)(ALT_SDMMC_RESP0_RESPONSE0_GET(resp0));
\r
924 response->resp1 = (uint32_t)(ALT_SDMMC_RESP1_RESPONSE1_GET(resp1));
\r
925 response->resp2 = (uint32_t)(ALT_SDMMC_RESP2_RESPONSE2_GET(resp2));
\r
926 response->resp3 = (uint32_t)(ALT_SDMMC_RESP3_RESPONSE3_GET(resp3));
\r
928 return ALT_E_SUCCESS;
\r
932 //This function reads a single data byte from the receive FIFO.
\r
934 ALT_STATUS_CODE alt_sdmmc_fifo_read(void *dest, const size_t size)
\r
936 uint32_t * dest_ptr = dest;
\r
937 for (int counter = 0; counter < size / 4; counter++)
\r
939 dest_ptr[counter] = (uint32_t)(ALT_SDMMC_DATA_VALUE_GET(alt_read_word(ALT_SDMMC_DATA_ADDR)));
\r
944 uint8_t * add_dest_ptr = (uint8_t*)dest + (size / 4);
\r
945 uint32_t word_notfull = (uint32_t)(ALT_SDMMC_DATA_VALUE_GET(alt_read_word(ALT_SDMMC_DATA_ADDR)));
\r
947 for (int counter = 0; counter < (size & 0x3); counter++)
\r
949 add_dest_ptr[counter] = (uint8_t)word_notfull;
\r
950 word_notfull = word_notfull >> 8;
\r
954 return ALT_E_SUCCESS;
\r
958 // This function writes a single data byte to the transmit FIFO.
\r
960 ALT_STATUS_CODE alt_sdmmc_fifo_write(const void *src, const size_t size)
\r
962 const uint32_t * src_ptr = src;
\r
963 for (int counter = 0; counter < size / 4; counter++)
\r
965 alt_write_word(ALT_SDMMC_DATA_ADDR, ALT_SDMMC_DATA_VALUE_SET(src_ptr[counter]));
\r
970 const uint8_t *add_src_ptr = (uint8_t*)src + (size / 4);
\r
971 uint32_t word_notfull = 0;
\r
973 for (int counter = 0; counter < (size & 0x3); counter++)
\r
975 word_notfull |= (uint32_t)add_src_ptr[counter] << (8 * counter);
\r
978 alt_write_word(ALT_SDMMC_DATA_ADDR, ALT_SDMMC_DATA_VALUE_SET(word_notfull));
\r
981 return ALT_E_SUCCESS;
\r
985 // Returns the current sdmmc controller interrupt status conditions.
\r
987 uint32_t alt_sdmmc_int_status_get(void)
\r
989 return alt_read_word(ALT_SDMMC_MINTSTS_ADDR);
\r
993 // Returns the sdmmc controller raw interrupt status conditions irrespective of
\r
994 // the interrupt status condition enablement state.
\r
996 uint32_t alt_sdmmc_int_mask_get(void)
\r
998 return alt_read_word(ALT_SDMMC_INTMSK_ADDR);
\r
1002 // Clears the specified sdmmc controller interrupt status conditions identified
\r
1005 ALT_STATUS_CODE alt_sdmmc_int_clear(const uint32_t mask)
\r
1007 alt_write_word(ALT_SDMMC_RINTSTS_ADDR, mask);
\r
1009 return ALT_E_SUCCESS;
\r
1013 // Disable the specified sdmmc controller interrupt status conditions identified in
\r
1016 ALT_STATUS_CODE alt_sdmmc_int_disable(const uint32_t mask)
\r
1018 alt_clrbits_word(ALT_SDMMC_INTMSK_ADDR, mask);
\r
1020 return ALT_E_SUCCESS;
\r
1024 // Enable the specified sdmmc controller interrupt status conditions identified in
\r
1027 ALT_STATUS_CODE alt_sdmmc_int_enable(const uint32_t mask)
\r
1029 if (mask & 0x0001ffff)
\r
1031 alt_setbits_word(ALT_SDMMC_CTL_ADDR,
\r
1032 ALT_SDMMC_CTL_INT_EN_SET_MSK);
\r
1034 alt_setbits_word(ALT_SDMMC_INTMSK_ADDR, mask);
\r
1036 return ALT_E_SUCCESS;
\r
1040 //Returns true if SD/MMC controller FIFO has reached the receive watermark level
\r
1041 //otherwise returns false.
\r
1043 bool alt_sdmmc_fifo_is_rx_wtrmk_reached(void)
\r
1045 if (ALT_SDMMC_STAT_FIFO_RX_WATERMARK_GET(alt_read_word(ALT_SDMMC_STAT_ADDR)) ==
\r
1046 ALT_SDMMC_STAT_FIFO_RX_WATERMARK_E_RXWATERMARK)
\r
1057 //Returns true if SD/MMC controller FIFO has reached the transmit watermark level
\r
1058 //otherwise returns false.
\r
1060 bool alt_sdmmc_fifo_is_tx_wtrmk_reached(void)
\r
1062 if (ALT_SDMMC_STAT_FIFO_TX_WATERMARK_GET(alt_read_word(ALT_SDMMC_STAT_ADDR)) ==
\r
1063 ALT_SDMMC_STAT_FIFO_TX_WATERMARK_E_TXWATERMARK)
\r
1074 // Returns ALT_E_TRUE when the receive FIFO is empty.
\r
1076 bool alt_sdmmc_fifo_is_empty(void)
\r
1078 if (ALT_SDMMC_STAT_FIFO_EMPTY_GET(alt_read_word(ALT_SDMMC_STAT_ADDR)) ==
\r
1079 ALT_SDMMC_STAT_FIFO_EMPTY_E_FIFOEMPTY)
\r
1090 // Returns ALT_E_TRUE when the receive FIFO is completely full.
\r
1092 bool alt_sdmmc_fifo_is_full(void)
\r
1094 if (ALT_SDMMC_STAT_FIFO_FULL_GET(alt_read_word(ALT_SDMMC_STAT_ADDR)) ==
\r
1095 ALT_SDMMC_STAT_FIFO_FULL_E_FIFOFULL)
\r
1106 // Returns the number of valid entries in the receive FIFO.
\r
1108 int32_t alt_sdmmc_fifo_count(void)
\r
1110 return (int32_t)ALT_SDMMC_STAT_FIFO_COUNT_GET(alt_read_word(ALT_SDMMC_STAT_ADDR));
\r
1114 // Gets the configured FIFO operational parameter values.
\r
1116 ALT_STATUS_CODE alt_sdmmc_fifo_param_get(uint32_t *rx_wtrmk, uint32_t *tx_wtrmk, ALT_SDMMC_MULT_TRANS_t *mult_trans_size)
\r
1118 uint32_t fifoth = alt_read_word(ALT_SDMMC_FIFOTH_ADDR);
\r
1120 *rx_wtrmk = ALT_SDMMC_FIFOTH_RX_WMARK_GET(fifoth);
\r
1121 *tx_wtrmk = ALT_SDMMC_FIFOTH_TX_WMARK_GET(fifoth);
\r
1122 *mult_trans_size = (ALT_SDMMC_MULT_TRANS_t)ALT_SDMMC_FIFOTH_DW_DMA_MULT_TRANSACTION_SIZE_GET(fifoth);
\r
1124 return ALT_E_SUCCESS;
\r
1128 // Sets the configured FIFO operational parameter values.
\r
1130 ALT_STATUS_CODE alt_sdmmc_fifo_param_set(uint32_t rx_wtrmk, uint32_t tx_wtrmk, ALT_SDMMC_MULT_TRANS_t mult_trans_size)
\r
1132 uint32_t fifoth_set_mask = ALT_SDMMC_FIFOTH_RX_WMARK_SET_MSK
\r
1133 | ALT_SDMMC_FIFOTH_TX_WMARK_SET_MSK
\r
1134 | ALT_SDMMC_FIFOTH_DW_DMA_MULT_TRANSACTION_SIZE_SET_MSK;
\r
1136 uint32_t fifoth_set_value = ALT_SDMMC_FIFOTH_RX_WMARK_SET(rx_wtrmk)
\r
1137 | ALT_SDMMC_FIFOTH_TX_WMARK_SET(tx_wtrmk)
\r
1138 | ALT_SDMMC_FIFOTH_DW_DMA_MULT_TRANSACTION_SIZE_SET(mult_trans_size);
\r
1140 alt_replbits_word(ALT_SDMMC_FIFOTH_ADDR,
\r
1142 fifoth_set_value);
\r
1144 return ALT_E_SUCCESS;
\r
1150 ALT_STATUS_CODE alt_sdmmc_card_reset(void)
\r
1152 // Assert card reset
\r
1153 alt_setbits_word(ALT_SDMMC_RST_N_ADDR,
\r
1154 ALT_SDMMC_RST_N_CARD_RST_SET_MSK);
\r
1156 volatile uint32_t timeout = ALT_SDMMC_RESET_TMO_INIT;
\r
1158 // Wait while card reset
\r
1162 // Deassert the appropriate card reset.
\r
1163 alt_clrbits_word(ALT_SDMMC_RST_N_ADDR,
\r
1164 ALT_SDMMC_RST_N_CARD_RST_SET_MSK);
\r
1166 return ALT_E_SUCCESS;
\r
1170 // Enables the sdmmc Internal DMA Controller.
\r
1172 ALT_STATUS_CODE alt_sdmmc_dma_enable(void)
\r
1174 alt_setbits_word(ALT_SDMMC_CTL_ADDR,
\r
1175 ALT_SDMMC_CTL_USE_INTERNAL_DMAC_SET_MSK);
\r
1176 alt_setbits_word(ALT_SDMMC_BMOD_ADDR,
\r
1177 ALT_SDMMC_BMOD_DE_SET_MSK);
\r
1179 return ALT_E_SUCCESS;
\r
1183 // Disables the sdmmc Internal DMA Controller
\r
1185 ALT_STATUS_CODE alt_sdmmc_dma_disable(void)
\r
1187 alt_clrbits_word(ALT_SDMMC_CTL_ADDR,
\r
1188 ALT_SDMMC_CTL_USE_INTERNAL_DMAC_SET_MSK);
\r
1189 alt_clrbits_word(ALT_SDMMC_BMOD_ADDR,
\r
1190 ALT_SDMMC_BMOD_DE_SET_MSK);
\r
1192 return ALT_E_SUCCESS;
\r
1196 // Enables the sdmmc Internal DMA Controller.
\r
1198 ALT_STATUS_CODE alt_sdmmc_is_dma_enabled(void)
\r
1200 if ( ALT_SDMMC_CTL_USE_INTERNAL_DMAC_GET(alt_read_word(ALT_SDMMC_CTL_ADDR))
\r
1201 && ALT_SDMMC_BMOD_DE_GET(alt_read_word(ALT_SDMMC_BMOD_ADDR)))
\r
1203 return ALT_E_TRUE;
\r
1207 return ALT_E_FALSE;
\r
1212 // Returns the current sdmmc controller interrupt IDMAC status conditions.
\r
1214 uint32_t alt_sdmmc_dma_int_status_get(void)
\r
1216 return alt_read_word(ALT_SDMMC_IDSTS_ADDR);
\r
1220 // Returns the SD/MMC internal DMA controller interrupt mask value which
\r
1221 // reflects the enabled internal DMA controller interrupt status conditions.
\r
1223 uint32_t alt_sdmmc_dma_int_mask_get(void)
\r
1225 return alt_read_word(ALT_SDMMC_IDINTEN_ADDR);
\r
1229 // Clears the specified sdmmc controller interrupt status IDMAC conditions identified
\r
1232 ALT_STATUS_CODE alt_sdmmc_dma_int_clear(const uint32_t mask)
\r
1234 alt_write_word(ALT_SDMMC_IDSTS_ADDR, mask);
\r
1236 return ALT_E_SUCCESS;
\r
1240 // Disable the specified sdmmc controller interrupt IDMAC status conditions identified in
\r
1243 ALT_STATUS_CODE alt_sdmmc_dma_int_disable(const uint32_t mask)
\r
1245 alt_clrbits_word(ALT_SDMMC_IDINTEN_ADDR, mask);
\r
1247 return ALT_E_SUCCESS;
\r
1251 // Enable the specified sdmmc controller interrupt status conditions identified in
\r
1254 ALT_STATUS_CODE alt_sdmmc_dma_int_enable(const uint32_t mask)
\r
1256 alt_setbits_word(ALT_SDMMC_IDINTEN_ADDR, mask);
\r
1258 return ALT_E_SUCCESS;
\r
1262 // Sets value into this register for the IDMAC FSM to resume normal descriptor fetch operation.
\r
1264 ALT_STATUS_CODE alt_sdmmc_poll_demand_set(const uint32_t value)
\r
1266 alt_replbits_word(ALT_SDMMC_PLDMND_ADDR,
\r
1267 ALT_SDMMC_PLDMND_PD_SET_MSK,
\r
1268 ALT_SDMMC_PLDMND_PD_SET(value));
\r
1270 return ALT_E_SUCCESS;
\r
1274 // Disable Card Read Threshold .
\r
1276 ALT_STATUS_CODE alt_sdmmc_card_rd_threshold_disable(void)
\r
1278 alt_clrbits_word(ALT_SDMMC_CARDTHRCTL_ADDR,
\r
1279 ALT_SDMMC_CARDTHRCTL_CARDRDTHREN_SET_MSK);
\r
1281 return ALT_E_SUCCESS;
\r
1286 // Enable Card Read Threshold .
\r
1288 ALT_STATUS_CODE alt_sdmmc_card_rd_threshold_enable(const uint32_t threshold)
\r
1290 alt_replbits_word(ALT_SDMMC_CARDTHRCTL_ADDR,
\r
1291 ALT_SDMMC_CARDTHRCTL_CARDRDTHRESHOLD_SET_MSK
\r
1292 | ALT_SDMMC_CARDTHRCTL_CARDRDTHREN_SET_MSK,
\r
1293 ALT_SDMMC_CARDTHRCTL_CARDRDTHRESHOLD_SET(threshold)
\r
1294 | ALT_SDMMC_CARDTHRCTL_CARDRDTHREN_SET(ALT_SDMMC_CARDTHRCTL_CARDRDTHREN_E_END));
\r
1296 return ALT_E_SUCCESS;
\r
1300 // This function return ALT_E_ERROR if interrupt error was detected
\r
1302 static ALT_STATUS_CODE alt_sdmmc_error_status_detect(void)
\r
1304 ALT_STATUS_CODE status = ALT_E_SUCCESS;
\r
1305 uint32_t int_status = 0;
\r
1307 // All sdmmc interrupt status caused by an error
\r
1308 uint32_t err = ( ALT_SDMMC_INT_STATUS_RE
\r
1309 | ALT_SDMMC_INT_STATUS_RCRC
\r
1310 | ALT_SDMMC_INT_STATUS_DCRC
\r
1311 | ALT_SDMMC_INT_STATUS_RTO
\r
1312 | ALT_SDMMC_INT_STATUS_DRTO
\r
1313 | ALT_SDMMC_INT_STATUS_FRUN
\r
1314 | ALT_SDMMC_INT_STATUS_HLE
\r
1315 | ALT_SDMMC_INT_STATUS_SBE
\r
1316 | ALT_SDMMC_INT_STATUS_EBE);
\r
1318 int_status = alt_sdmmc_int_status_get();
\r
1319 if (status != ALT_E_SUCCESS)
\r
1324 // Checking on errors
\r
1325 if (int_status & err)
\r
1327 status = ALT_E_ERROR;
\r
1334 // Read/write all data from/to buffer
\r
1336 static ALT_STATUS_CODE alt_sdmmc_transfer_helper(uint32_t * buffer,
\r
1337 const size_t size,
\r
1338 ALT_SDMMC_TMOD_t transfer_mode)
\r
1341 dprintf("\nalt_sdmmc_transfer_helper\n");
\r
1344 ALT_STATUS_CODE status = ALT_E_SUCCESS;
\r
1346 uint32_t data_size = size;
\r
1347 bool read_freeze = false;
\r
1348 bool write_freeze = false;
\r
1350 while (data_size > 0)
\r
1353 dprintf("\ndata_size = %x\n", (int)data_size);
\r
1357 status = alt_sdmmc_error_status_detect();
\r
1359 if (status != ALT_E_SUCCESS)
\r
1364 uint32_t timeout = ALT_SDMMC_TMO_WAITER;
\r
1368 read_freeze =(transfer_mode == ALT_SDMMC_TMOD_READ)
\r
1369 && alt_sdmmc_fifo_is_empty() == true;
\r
1370 write_freeze = transfer_mode == ALT_SDMMC_TMOD_WRITE
\r
1371 && alt_sdmmc_fifo_is_full() == true;
\r
1373 dprintf("\nread_freeze = %x write_freeze = %x\n", (int)read_freeze, (int)write_freeze);
\r
1375 if (--timeout == 0)
\r
1377 status = ALT_E_TMO;
\r
1381 while (read_freeze || write_freeze);
\r
1383 uint32_t level = alt_sdmmc_fifo_count();
\r
1386 dprintf("\nfifo level = %x\n", (int)level);
\r
1389 // Top up the TX FIFO with read issues
\r
1391 if (transfer_mode == ALT_SDMMC_TMOD_WRITE)
\r
1393 uint32_t free_space = ALT_SDMMC_FIFO_NUM_ENTRIES - level;
\r
1394 free_space = MIN(data_size / 4, free_space);
\r
1396 for (uint32_t i = 0; i < free_space; i++)
\r
1398 alt_write_word(ALT_SDMMC_DATA_ADDR, *buffer);
\r
1401 data_size -= free_space * 4;
\r
1404 // Read out the resulting received data as they come in.
\r
1406 if (transfer_mode == ALT_SDMMC_TMOD_READ)
\r
1408 level = MIN(data_size / 4, level);
\r
1410 for (uint32_t i = 0; i < level; i++)
\r
1412 *buffer = ALT_SDMMC_DATA_VALUE_GET(alt_read_word(ALT_SDMMC_DATA_ADDR));
\r
1416 data_size -= level * 4;
\r
1424 // Fill descriptors
\r
1426 static ALT_STATUS_CODE alt_sdmmc_dma_trans_helper(uint32_t * buffer,
\r
1430 dprintf("\nalt_sdmmc_dma_trans_helper: buf_len = %d\n",
\r
1433 ALT_STATUS_CODE status = ALT_E_SUCCESS;
\r
1434 //Pointer to current descriptor
\r
1435 ALT_SDMMC_DMA_BUF_DESC_t *cur_dma_desc = dma_cur_descr;
\r
1437 uint32_t cur_buffer = (uint32_t)buffer;
\r
1438 uint32_t len_left = buf_len;
\r
1440 while (len_left > 0)
\r
1443 status = alt_sdmmc_error_status_detect();
\r
1444 if (status != ALT_E_SUCCESS)
\r
1446 status = ALT_E_ERROR;
\r
1449 //If current descriptor is free then fill it
\r
1450 if (cur_dma_desc->des0.fld.own == 0)
\r
1452 int set_len = len_left > ALT_SDMMC_DMA_SEGMENT_SIZE ? ALT_SDMMC_DMA_SEGMENT_SIZE : len_left;
\r
1453 //Disable interrupt after it will be free
\r
1454 cur_dma_desc->des0.fld.dic = 1;//socfpga->dma_cur_pos % 4;
\r
1455 //Set If it is first part of buffer for transfer
\r
1456 cur_dma_desc->des0.fld.fs = (buf_len == len_left) ? 1 : 0;
\r
1457 //Set size of des2
\r
1458 cur_dma_desc->des1.fld.bs1 = set_len;
\r
1459 //Set address of buffer in memory
\r
1460 cur_dma_desc->des2.fld.bap1 = cur_buffer;
\r
1463 dprintf("socfpga_setup_dma_add: des_adrdr %08X des2_paddr %08X des1_len %08X len_left %08X\n",
\r
1464 (int)cur_dma_desc, (int)cur_buffer, (int)set_len, (int)len_left);
\r
1467 //Update address buffer and buffer len
\r
1468 cur_buffer += set_len;
\r
1469 len_left -= set_len;
\r
1470 //Set if it is last part of buffer
\r
1471 cur_dma_desc->des0.fld.ld = (len_left == 0) ? 1 : 0;
\r
1472 //Descriptor could be used
\r
1473 cur_dma_desc->des0.fld.own = 1;
\r
1474 //Currernt descriptor set sa next element
\r
1475 cur_dma_desc = (ALT_SDMMC_DMA_BUF_DESC_t *)cur_dma_desc->des3.fld.bap2_or_next;
\r
1478 uint32_t idmac_status = alt_sdmmc_dma_int_status_get();
\r
1480 // If DMA status is as descriptor unavailable then resume transfer and clean interrupt status
\r
1481 if (idmac_status & ALT_SDMMC_DMA_INT_STATUS_DU)
\r
1483 alt_sdmmc_poll_demand_set(0xFFFF);
\r
1484 alt_sdmmc_dma_int_clear(ALT_SDMMC_DMA_INT_STATUS_ALL);
\r
1486 // If DMA status is another abnormal then break with error
\r
1487 else if (idmac_status & ALT_SDMMC_DMA_INT_STATUS_AI)
\r
1489 status = ALT_E_ERROR;
\r
1500 // Waiter of data transfer complete
\r
1502 static ALT_STATUS_CODE alt_sdmmc_data_done_waiter(void)
\r
1504 ALT_STATUS_CODE status = ALT_E_TMO;
\r
1505 uint32_t timeout = ALT_SDMMC_TMO_WAITER;
\r
1509 uint32_t int_status;
\r
1510 int_status = alt_sdmmc_int_status_get();
\r
1513 if (alt_sdmmc_error_status_detect() != ALT_E_SUCCESS)
\r
1515 status = ALT_E_ERROR;
\r
1519 uint32_t idmac_status = alt_sdmmc_dma_int_status_get();
\r
1521 // If DMA status is abnormal then transfer complete with error
\r
1522 if (idmac_status & ALT_SDMMC_DMA_INT_STATUS_AI)
\r
1524 status = ALT_E_ERROR;
\r
1527 // Data transfer over caused by complete transfer operation
\r
1528 if (int_status & ALT_SDMMC_INT_STATUS_DTO)
\r
1530 alt_sdmmc_int_clear(ALT_SDMMC_INT_STATUS_DTO);
\r
1531 status = ALT_E_SUCCESS;
\r
1536 timeout = ALT_SDMMC_TMO_WAITER;
\r
1537 while (!alt_sdmmc_is_idle() && timeout--)
\r
1541 status = ALT_E_TMO;
\r
1549 // Waiter of clock command complete
\r
1551 static ALT_STATUS_CODE alt_sdmmc_clock_waiter(void)
\r
1553 ALT_STATUS_CODE status = ALT_E_TMO;
\r
1554 uint32_t timeout = ALT_SDMMC_TMO_WAITER;
\r
1558 uint32_t cmd_register = alt_read_word(ALT_SDMMC_CMD_ADDR);
\r
1561 if (alt_sdmmc_error_status_detect() != ALT_E_SUCCESS)
\r
1563 status = ALT_E_ERROR;
\r
1567 // Only for clock command detect complete operation by 0 in start_cmd bit of cmd register
\r
1568 if (ALT_SDMMC_CMD_START_CMD_GET(cmd_register) == ALT_SDMMC_CMD_START_CMD_E_NOSTART)
\r
1570 status = ALT_E_SUCCESS;
\r
1578 // Waiter of command complete
\r
1580 static ALT_STATUS_CODE alt_sdmmc_cmd_waiter(void)
\r
1582 ALT_STATUS_CODE status = ALT_E_TMO;
\r
1583 uint32_t timeout = ALT_SDMMC_TMO_WAITER;
\r
1587 uint32_t int_status;
\r
1588 int_status = alt_sdmmc_int_status_get();
\r
1591 if (alt_sdmmc_error_status_detect() != ALT_E_SUCCESS)
\r
1593 status = ALT_E_ERROR;
\r
1597 //Check command done
\r
1598 if (int_status & ALT_SDMMC_INT_STATUS_CMD)
\r
1600 alt_sdmmc_int_clear(ALT_SDMMC_INT_STATUS_CMD);
\r
1601 status = ALT_E_SUCCESS;
\r
1609 // Read SRC register from card and read supported bus width
\r
1611 static ALT_STATUS_CODE alt_sdmmc_card_scr_get(uint64_t *scr_reg)
\r
1613 ALT_STATUS_CODE status = ALT_E_SUCCESS;
\r
1615 uint32_t response = 0;
\r
1618 uint16_t prev_blk_size = 0;
\r
1619 // Save current block size and change it
\r
1620 prev_blk_size = alt_sdmmc_block_size_get();
\r
1621 alt_sdmmc_block_size_set(8);
\r
1622 alt_sdmmc_byte_count_set(8);
\r
1624 // Activate ACMD commands
\r
1625 status = alt_sdmmc_command_send(ALT_SDMMC_APP_CMD, rca_number, NULL);
\r
1626 if (status != ALT_E_SUCCESS)
\r
1632 alt_sdmmc_read_short_response(&response);
\r
1633 dprintf("\nALT_SDMMC_APP_CMD response = %x\n", (int)response);
\r
1636 // Send request for read SRC register
\r
1637 status = alt_sdmmc_command_send(ALT_SD_SEND_SCR, 0x0, NULL);
\r
1638 if (status != ALT_E_SUCCESS)
\r
1644 alt_sdmmc_read_short_response(&response);
\r
1645 dprintf("\nALT_SD_SEND_SCR responce = %x\n", (int)response);
\r
1648 // Read SRC register
\r
1649 status = alt_sdmmc_transfer_helper((uint32_t*)scr_reg, 8, ALT_SDMMC_TMOD_READ);
\r
1650 if (status != ALT_E_SUCCESS)
\r
1655 // Transfer complete
\r
1656 status = alt_sdmmc_data_done_waiter();
\r
1657 if (status != ALT_E_SUCCESS)
\r
1663 dprintf("\nALT_SD_SEND_SCR data = ");
\r
1664 uint8_t* scr_buf_8 = (uint8_t*)scr_reg;
\r
1665 for (int count = 0; count < 8; count++)
\r
1667 dprintf("%02x", scr_buf_8[count]);
\r
1672 // Re-change block size
\r
1673 alt_sdmmc_block_size_set(prev_blk_size);
\r
1679 // Set sdmmc card width
\r
1681 ALT_STATUS_CODE alt_sdmmc_card_bus_width_set(const ALT_SDMMC_BUS_WIDTH_t width)
\r
1683 ALT_STATUS_CODE status = ALT_E_SUCCESS;
\r
1687 // Read SRC register
\r
1688 status = alt_sdmmc_card_scr_get(&scr_reg);
\r
1689 if (status != ALT_E_SUCCESS)
\r
1694 uint8_t * scr_buf_8 = (uint8_t*)&scr_reg;
\r
1695 // Get supported bus width
\r
1696 uint32_t supported_bus_width = scr_buf_8[1] & 0xF;
\r
1699 dprintf("\nbus_width_supported = %02x\n", (int)supported_bus_width);
\r
1702 if ((supported_bus_width & width) == 0)
\r
1704 return ALT_E_BAD_ARG;
\r
1707 uint32_t set_width_arg;
\r
1710 case ALT_SDMMC_BUS_WIDTH_8:
\r
1711 set_width_arg = 0x3;
\r
1713 case ALT_SDMMC_BUS_WIDTH_4:
\r
1714 set_width_arg = 0x2;
\r
1716 case ALT_SDMMC_BUS_WIDTH_1:
\r
1717 set_width_arg = 0x0;
\r
1720 return ALT_E_BAD_ARG;
\r
1724 uint32_t response = 0;
\r
1727 // Activate ACMD commands
\r
1728 status = alt_sdmmc_command_send(ALT_SDMMC_APP_CMD, rca_number, NULL);
\r
1729 if (status != ALT_E_SUCCESS)
\r
1735 alt_sdmmc_read_short_response(&response);
\r
1736 dprintf("\nALT_SDMMC_APP_CMD response = %x\n", (int)response);
\r
1739 // Send new card bus width
\r
1740 status = alt_sdmmc_command_send(ALT_SD_SET_BUS_WIDTH, set_width_arg, NULL);
\r
1741 if (status != ALT_E_SUCCESS)
\r
1747 alt_sdmmc_read_short_response(&response);
\r
1748 dprintf("\nALT_SD_SET_BUS_WIDTH responce = %x\n", (int)response);
\r
1751 // Set new bus width in controller register
\r
1752 alt_sdmmc_bus_width_set(width);
\r
1760 ALT_STATUS_CODE alt_sdmmc_card_block_size_set(const uint16_t block_size)
\r
1762 ALT_STATUS_CODE status = ALT_E_SUCCESS;
\r
1764 // Send new block size to card
\r
1765 status = alt_sdmmc_command_send(ALT_SDMMC_SET_BLOCKLEN, block_size, NULL);
\r
1766 if (status != ALT_E_SUCCESS)
\r
1772 uint32_t response;
\r
1774 alt_sdmmc_read_short_response(&response);
\r
1775 dprintf("\nALT_SDMMC_SET_BLOCKLEN response = %x\n", (int)response);
\r
1778 // Set new block size in controller register
\r
1779 alt_sdmmc_block_size_set(block_size);
\r
1785 // Enumerated Card Stack ident sdio io only
\r
1787 static ALT_STATUS_CODE alt_sdmmc_card_ident_io_only(ALT_SDMMC_CARD_INFO_t *card_info)
\r
1790 dprintf("\nalt_sdmmc_card_ident_io_only\n");
\r
1792 ALT_STATUS_CODE status = ALT_E_SUCCESS;
\r
1794 uint32_t int_status = 0;
\r
1795 uint32_t response = 0;
\r
1796 // Enumerated Card Stack p.2a - 2b
\r
1797 // Activates the card's initialization process.
\r
1798 status = alt_sdmmc_command_send(ALT_SDMMC_SEND_OP_COND, 0x0, &response);
\r
1799 if (status != ALT_E_SUCCESS)
\r
1801 int_status = alt_sdmmc_int_status_get();
\r
1802 if (int_status & ALT_SDMMC_INT_STATUS_RTO)
\r
1804 return ALT_E_SUCCESS;
\r
1813 alt_sdmmc_read_short_response(&response);
\r
1814 dprintf("\nALT_SDMMC_SEND_OP_COND_1 = %x\n", (int)response);
\r
1817 // Enumerated Card Stack p.2c
\r
1818 status = alt_sdmmc_command_send(ALT_SDMMC_SEND_OP_COND, 0x100000, &response);
\r
1819 if (status != ALT_E_SUCCESS)
\r
1821 int_status = alt_sdmmc_int_status_get();
\r
1822 if (int_status & ALT_SDMMC_INT_STATUS_RTO)
\r
1824 return ALT_E_SUCCESS;
\r
1833 dprintf("\nALT_SDMMC_SEND_OP_COND_2 response = %x\n", (int)response);
\r
1835 // Enumerated Card Stack p.2d
\r
1836 bool is_sdio_combo = response & (1 << 27);
\r
1837 card_info->card_type = (is_sdio_combo)
\r
1838 ? ALT_SDMMC_CARD_TYPE_NOTDETECT
\r
1839 : ALT_SDMMC_CARD_TYPE_SDIOIO;
\r
1841 return ALT_E_SUCCESS;
\r
1845 // Enumerated Card Stack ident sdhc type
\r
1847 static ALT_STATUS_CODE alt_sdmmc_card_ident_sdhc(ALT_SDMMC_CARD_INFO_t *card_info)
\r
1850 dprintf("\nalt_sdmmc_card_ident_sdhc\n");
\r
1852 ALT_STATUS_CODE status = ALT_E_SUCCESS;
\r
1854 uint32_t int_status = 0;
\r
1855 uint32_t response = 0;
\r
1856 // Resets all cards to Idle State
\r
1857 status = alt_sdmmc_command_send(ALT_SDMMC_GO_IDLE_STATE, 0x0, &response);
\r
1858 if (status != ALT_E_SUCCESS)
\r
1860 int_status = alt_sdmmc_int_status_get();
\r
1861 if (int_status & ALT_SDMMC_INT_STATUS_RTO)
\r
1863 return ALT_E_SUCCESS;
\r
1872 alt_sdmmc_read_short_response(&response);
\r
1873 dprintf("\nALT_SDMMC_GO_IDLE_STATE response = %x\n", (int)response);
\r
1876 // Enumerated Card Stack p.3a
\r
1877 // For only SDC V2. Check voltage range.
\r
1878 status = alt_sdmmc_command_send(ALT_SDMMC_IF_COND, 0x1AA, &response);
\r
1879 if (status != ALT_E_SUCCESS)
\r
1881 int_status = alt_sdmmc_int_status_get();
\r
1882 if (int_status & ALT_SDMMC_INT_STATUS_RTO)
\r
1884 return ALT_E_SUCCESS;
\r
1892 alt_sdmmc_read_short_response(&response);
\r
1894 dprintf("\nALT_SDMMC_IF_COND response = %x\n", (int)response);
\r
1897 if (response != 0x1AA)
\r
1899 return ALT_E_ERROR;
\r
1902 // Indicates to the card that the next command is an
\r
1903 // application specific command rather than a
\r
1904 // standard command
\r
1905 status = alt_sdmmc_command_send(ALT_SDMMC_APP_CMD, 0x0, &response);
\r
1906 if (status != ALT_E_SUCCESS)
\r
1908 int_status = alt_sdmmc_int_status_get();
\r
1909 if (int_status & ALT_SDMMC_INT_STATUS_RTO)
\r
1911 return ALT_E_SUCCESS;
\r
1920 alt_sdmmc_read_short_response(&response);
\r
1921 dprintf("\nALT_SDMMC_APP_CMD response = %x\n", (int)response);
\r
1924 // Enumerated Card Stack p.3c
\r
1925 // Asks the accessed card to send its operating condition
\r
1926 // register (OCR) con tent in the response on the CMD
\r
1928 status = alt_sdmmc_command_send(ALT_SD_SEND_OP_COND, 0x40FF8000, &response);
\r
1929 if (status != ALT_E_SUCCESS)
\r
1931 int_status = alt_sdmmc_int_status_get();
\r
1932 if (int_status & ALT_SDMMC_INT_STATUS_RTO)
\r
1934 return ALT_E_SUCCESS;
\r
1943 alt_sdmmc_read_short_response(&response);
\r
1944 dprintf("\nALT_SD_SEND_OP_COND responce = %x\n", (int)response);
\r
1947 //Enumerated Card Stack p.3d
\r
1948 card_info->card_type = ALT_SDMMC_CARD_TYPE_SDHC;
\r
1954 //Enumerated Card Stack ident sd type
\r
1956 static ALT_STATUS_CODE alt_sdmmc_card_ident_sd(ALT_SDMMC_CARD_INFO_t *card_info)
\r
1959 dprintf("\nalt_sdmmc_card_ident_sd\n");
\r
1961 ALT_STATUS_CODE status = ALT_E_SUCCESS;
\r
1963 uint32_t int_status = 0;
\r
1965 uint32_t response = 0;
\r
1967 // Enumerated Card Stack p.3e
\r
1968 // Indicates to the card that the next command is an
\r
1969 // application specific command rather than a
\r
1970 // standard command
\r
1971 status = alt_sdmmc_command_send(ALT_SDMMC_APP_CMD, 0x0, NULL);
\r
1972 if (status != ALT_E_SUCCESS)
\r
1974 int_status = alt_sdmmc_int_status_get();
\r
1975 if (int_status & ALT_SDMMC_INT_STATUS_RTO)
\r
1977 return ALT_E_SUCCESS;
\r
1986 alt_sdmmc_read_short_response(&response);
\r
1987 dprintf("\nALT_SDMMC_APP_CMD response = %x\n", (int)response);
\r
1990 // Asks the accessed card to send its operating condition
\r
1991 // register (OCR) con tent in the response on the CMD
\r
1993 status = alt_sdmmc_command_send(ALT_SD_SEND_OP_COND, 0x00FF8000, NULL);
\r
1994 if (status != ALT_E_SUCCESS)
\r
1996 int_status = alt_sdmmc_int_status_get();
\r
1997 if (int_status & ALT_SDMMC_INT_STATUS_RTO)
\r
1999 return ALT_E_SUCCESS;
\r
2008 alt_sdmmc_read_short_response(&response);
\r
2009 dprintf("\nALT_SD_SEND_OP_COND responce = %x\n", (int)response);
\r
2012 // Enumerated Card Stack p.3f
\r
2013 card_info->card_type = ALT_SDMMC_CARD_TYPE_SD;
\r
2019 // Enumerated Card Stack enumarete sd cart type
\r
2021 static ALT_STATUS_CODE alt_sdmmc_card_enum_sd(ALT_SDMMC_CARD_INFO_t *card_info)
\r
2024 dprintf("\nalt_sdmmc_card_enum_sd\n");
\r
2026 ALT_STATUS_CODE status = ALT_E_SUCCESS;
\r
2028 uint32_t clk_div = clock_freq / (2 * 400000);
\r
2030 status = alt_sdmmc_card_clk_div_set(clk_div);
\r
2031 if (status != ALT_E_SUCCESS)
\r
2035 status = alt_sdmmc_card_clk_enable(false);
\r
2036 if (status != ALT_E_SUCCESS)
\r
2041 uint32_t response = 0;
\r
2042 // Resets all cards to Idle State
\r
2043 status = alt_sdmmc_command_send(ALT_SDMMC_GO_IDLE_STATE, 0x0, &response);
\r
2044 if (status != ALT_E_SUCCESS)
\r
2050 alt_sdmmc_read_short_response(&response);
\r
2051 dprintf("\nALT_SDMMC_GO_IDLE_STATE response = %x\n", (int)response);
\r
2053 // For only SDC V2. Check voltage range.
\r
2054 status = alt_sdmmc_command_send(ALT_SDMMC_IF_COND, 0x1AA, &response);
\r
2055 if (status != ALT_E_SUCCESS)
\r
2061 alt_sdmmc_read_short_response(&response);
\r
2062 dprintf("\nALT_SDMMC_IF_COND response = %x\n", (int)response);
\r
2065 /* OCR Bit VDD Voltage Window
\r
2088 30 High capacity card
\r
2089 31 Card power up status bit (busy)
\r
2091 uint32_t ocr_reg = 0xFF8000;
\r
2093 if (card_info->card_type == ALT_SDMMC_CARD_TYPE_SDHC)
\r
2095 ocr_reg |= (1 << 30);
\r
2100 status = alt_sdmmc_command_send(ALT_SDMMC_APP_CMD, 0x0, &response);
\r
2101 if (status != ALT_E_SUCCESS)
\r
2107 alt_sdmmc_read_short_response(&response);
\r
2108 dprintf("\nALT_SDMMC_APP_CMD response = %x\n", (int)response);
\r
2111 volatile uint32_t timeout = 1000000;
\r
2113 // Wait while sdmmc module is reseting
\r
2116 status = alt_sdmmc_command_send(ALT_SD_SEND_OP_COND, 0x40FF8000, &response);
\r
2117 if (status != ALT_E_SUCCESS)
\r
2122 alt_sdmmc_read_short_response(&response);
\r
2124 dprintf("\nALT_SD_SEND_OP_COND response = %x\n", (int)response);
\r
2127 while ((response & (1UL << 31)) == 0);
\r
2129 //Asks any card to send their CID numbers on the CMD line.
\r
2130 //(Any card that is connected to the host will respond.)
\r
2131 status = alt_sdmmc_command_send(ALT_SDMMC_ALL_SEND_CID, 0x0, &response);
\r
2132 if (status != ALT_E_SUCCESS)
\r
2138 alt_sdmmc_read_short_response(&response);
\r
2139 dprintf("\nALT_SDMMC_ALL_SEND_CID response = %x\n", (int)response);
\r
2141 // Asks the card to publish a new relative address (RCA).
\r
2142 status = alt_sdmmc_command_send(ALT_SDMMC_SET_RELATIVE_ADDR, 0x0, &response);
\r
2143 if (status != ALT_E_SUCCESS)
\r
2148 alt_sdmmc_read_short_response(&response);
\r
2150 dprintf("\nALT_SDMMC_SET_RELATIVE_ADDR responce = %x\n", (int)response);
\r
2153 uint32_t RCA_number = response & 0xFFFF0000;
\r
2154 rca_number = RCA_number;
\r
2156 // Addressed card sends its card identification (CID) on the CMD line.
\r
2157 status = alt_sdmmc_command_send(ALT_SDMMC_SEND_CID, rca_number, &response);
\r
2158 if (status != ALT_E_SUCCESS)
\r
2164 alt_sdmmc_read_short_response(&response);
\r
2165 dprintf("\nALT_SDMMC_SEND_CID responce = %x\n", (int)response);
\r
2168 // Addressed card sends its card-specific data (CSD)
\r
2169 // on the CMD line.
\r
2170 status = alt_sdmmc_command_send(ALT_SDMMC_SEND_CSD, rca_number, &response);
\r
2171 if (status != ALT_E_SUCCESS)
\r
2177 alt_sdmmc_read_short_response(&response);
\r
2178 dprintf("\nALT_SDMMC_SEND_CSD responce = %x\n", (int)response);
\r
2181 ALT_SDMMC_RESPONSE_t response_long;
\r
2182 alt_sdmmc_read_long_response(&response_long);
\r
2183 static const uint32_t tran_speed_mul_x10[] = { 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 };
\r
2184 static const uint32_t freq_unit[] = { 100000, 1000000, 10000000, 100000000 };
\r
2185 // card_info->max_r_blkln = pow(2, ALT_SDMMC_CSD_MAX_R_BLK_GET(response_long.resp2));
\r
2186 // card_info->max_w_blkln = pow(2, ALT_SDMMC_CSD_MAX_W_BLK_GET(response_long.resp0));
\r
2187 card_info->max_r_blkln = 1 << ALT_SDMMC_CSD_MAX_R_BLK_GET(response_long.resp2);
\r
2188 card_info->max_w_blkln = 1 << ALT_SDMMC_CSD_MAX_W_BLK_GET(response_long.resp0);
\r
2189 card_info->partial_r_allowed = ALT_SDMMC_CSD_PART_R_ALLOW_GET(response_long.resp2);
\r
2190 card_info->partial_w_allowed = ALT_SDMMC_CSD_PART_W_ALLOW_GET(response_long.resp0);
\r
2191 uint32_t rate_unit = ALT_SDMMC_CSD_SPEED_RATE_GET(response_long.resp3);
\r
2192 uint32_t time_val = ALT_SDMMC_CSD_SPEED_TIME_GET(response_long.resp3);
\r
2193 if ((time_val != 0) && (rate_unit <= 3))
\r
2195 // uint32_t speed_rate = (rate_unit == 0) ? 100 : pow(10, rate_unit - 1) * 1000;
\r
2196 uint32_t speed_rate = freq_unit[rate_unit];
\r
2197 card_info->xfer_speed = speed_rate * tran_speed_mul_x10[time_val] / 10;
\r
2201 return ALT_E_ERROR;
\r
2204 // Command toggles a card between the Stand-by
\r
2205 // and Transfer states or between the Programming
\r
2206 // and Disconnect state
\r
2207 status = alt_sdmmc_command_send(ALT_SDMMC_SEL_DES_CARD, rca_number, &response);
\r
2208 if (status != ALT_E_SUCCESS)
\r
2214 alt_sdmmc_read_short_response(&response);
\r
2215 dprintf("\nALT_SDMMC_SEL_DES_CARD responce = %x\n", (int)response);
\r
2218 // Addressed card sends its status register
\r
2219 status = alt_sdmmc_command_send(ALT_SDMMC_SEND_STATUS, rca_number, &response);
\r
2220 if (status != ALT_E_SUCCESS)
\r
2226 alt_sdmmc_read_short_response(&response);
\r
2227 dprintf("\nALT_SDMMC_SEND_STATUS responce = %x\n", (int)response);
\r
2234 // Enumerated Card Stack
\r
2236 ALT_STATUS_CODE alt_sdmmc_card_identify(ALT_SDMMC_CARD_INFO_t *card_info)
\r
2239 dprintf("\nalt_sdmmc_card_identify\n");
\r
2241 ALT_STATUS_CODE status = ALT_E_SUCCESS;
\r
2242 card_info->card_type = ALT_SDMMC_CARD_TYPE_NOTDETECT;
\r
2244 //Enumerated Card Stack p.1
\r
2245 alt_sdmmc_bus_width_set(ALT_SDMMC_BUS_WIDTH_1);
\r
2247 if (status == ALT_E_SUCCESS)
\r
2249 status = alt_sdmmc_card_ident_io_only(card_info);
\r
2250 // If card is identified as SDIO IO only or SDIO COMBO then prepare it
\r
2251 if (card_info->card_type != ALT_SDMMC_CARD_TYPE_NOTDETECT && status == ALT_E_SUCCESS)
\r
2256 if (status == ALT_E_SUCCESS)
\r
2258 status = alt_sdmmc_card_ident_sdhc(card_info);
\r
2259 if (card_info->card_type != ALT_SDMMC_CARD_TYPE_NOTDETECT && status == ALT_E_SUCCESS)
\r
2261 // If card is identified as SDHC then prepare it
\r
2262 status = alt_sdmmc_card_enum_sd(card_info);
\r
2266 if (status != ALT_E_SUCCESS)
\r
2268 status = alt_sdmmc_card_ident_sd(card_info);
\r
2269 if (card_info->card_type != ALT_SDMMC_CARD_TYPE_NOTDETECT && status == ALT_E_SUCCESS)
\r
2271 // If card is identified as SD card then prepare it
\r
2272 status = alt_sdmmc_card_enum_sd(card_info);
\r
2281 // Send the a command and command argument to the card and optionally return the
\r
2282 // command response.
\r
2284 ALT_STATUS_CODE alt_sdmmc_command_send(ALT_SDMMC_CMD_INDEX_t command,
\r
2285 uint32_t command_arg, uint32_t *response)
\r
2287 const ALT_SDMMC_CMD_CONFIG_t * cmd_cfg = NULL;
\r
2289 bool found = false;
\r
2291 if (command == ALT_SDMMC_CLK_INDEX)
\r
2293 cmd_cfg = &cmd_clock_cfg;
\r
2297 for (uint32_t counter = 0; counter < ARRAY_COUNT(cmd_default_cfg); counter++)
\r
2299 if (found == true)
\r
2303 if (cmd_default_cfg[counter].cmd_index == command)
\r
2305 cmd_cfg = &cmd_default_cfg[counter];
\r
2310 if (found == false)
\r
2312 return ALT_E_BAD_ARG;
\r
2315 if (cmd_cfg->wait_prvdata_complete)
\r
2317 uint32_t timeout = ALT_SDMMC_TMO_WAITER;
\r
2318 while (alt_sdmmc_is_busy() && timeout--)
\r
2322 // Create interrupt mask by command configurations
\r
2323 uint32_t int_mask = ALT_SDMMC_INT_STATUS_RE // Response error
\r
2324 | ALT_SDMMC_INT_STATUS_RTO // Response timeout
\r
2325 | ALT_SDMMC_INT_STATUS_CD // Card detect (CD) interrupt
\r
2326 | ALT_SDMMC_INT_STATUS_HLE // Hardware Locked Write Error
\r
2327 | ALT_SDMMC_INT_STATUS_CMD; // Command done (CD) interrupt
\r
2329 if (cmd_cfg->data_expected == true)
\r
2331 int_mask |= ALT_SDMMC_INT_STATUS_DTO // Data transfer over
\r
2332 | ALT_SDMMC_INT_STATUS_RCRC // Response CRC error
\r
2333 | ALT_SDMMC_INT_STATUS_DCRC // Data CRC error
\r
2334 | ALT_SDMMC_INT_STATUS_HTO // Data starvation by host timeout
\r
2335 | ALT_SDMMC_INT_STATUS_FRUN // FIFO underrun/overrun error
\r
2336 | ALT_SDMMC_INT_STATUS_EBE; // End-bit error
\r
2338 if (cmd_cfg->write_active == ALT_SDMMC_TMOD_WRITE)
\r
2340 int_mask |= ALT_SDMMC_INT_STATUS_TXDR // Transmit FIFO data request (TXDR)
\r
2341 | ALT_SDMMC_INT_STATUS_HLE; // Hardware locked write error (HLE)
\r
2345 int_mask |= ALT_SDMMC_INT_STATUS_RXDR // Receive FIFO data request (RXDR)
\r
2346 |ALT_SDMMC_INT_STATUS_SBE; // Start-bit error (SBE)
\r
2351 alt_sdmmc_int_disable(ALT_SDMMC_INT_STATUS_ALL);
\r
2352 // Reset all possible interrupts
\r
2353 alt_sdmmc_int_clear(ALT_SDMMC_INT_STATUS_ALL);
\r
2354 // Interrupts enable
\r
2355 alt_sdmmc_int_enable(int_mask);
\r
2356 // Setup the Argument Register and send CMD
\r
2357 alt_sdmmc_cmd_arg_set(command_arg);
\r
2359 // Set command configuraions
\r
2360 alt_sdmmc_cmd_set(command, cmd_cfg, false);
\r
2362 alt_sdmmc_cmd_set(command, cmd_cfg, true);
\r
2365 uint32_t state = (uint32_t)ALT_SDMMC_STAT_CMD_FSM_STATES_GET(alt_read_word(ALT_SDMMC_STAT_ADDR));
\r
2367 uint32_t dma_state = (uint32_t)ALT_SDMMC_IDSTS_FSM_GET(alt_read_word(ALT_SDMMC_IDSTS_ADDR));
\r
2369 dprintf("\nstate %x dma_state %x\n", (int)state, (int)dma_state);
\r
2370 dprintf("\nCMD = %d ARG = %x\n", (int)command, (int)command_arg);
\r
2373 ALT_STATUS_CODE status = 0;
\r
2374 if (cmd_cfg->update_clock_registers_only == true)
\r
2376 //Wait for complete clock update command
\r
2377 status = alt_sdmmc_clock_waiter();
\r
2379 if (status == ALT_E_TMO)
\r
2381 dprintf("\nTIMEOUT\n");
\r
2387 //Wait for complete
\r
2388 if ( alt_sdmmc_is_dma_enabled() == ALT_E_FALSE
\r
2389 || cmd_cfg->data_expected == false)
\r
2391 status = alt_sdmmc_cmd_waiter();
\r
2394 if (status == ALT_E_TMO)
\r
2396 dprintf("\nTIMEOUT\n");
\r
2399 if (status == ALT_E_SUCCESS)
\r
2401 alt_sdmmc_read_short_response(response);
\r
2407 static ALT_STATUS_CODE alt_sdmmc_transfer(uint32_t start_addr,
\r
2408 uint32_t buffer[],
\r
2409 const size_t buf_len,
\r
2410 ALT_SDMMC_TMOD_t transfer_mode)
\r
2414 return ALT_E_SUCCESS;
\r
2417 if (!alt_sdmmc_is_idle())
\r
2419 return ALT_E_ERROR;
\r
2422 uint16_t block_size = alt_sdmmc_block_size_get();
\r
2424 if ( (start_addr % block_size != 0)
\r
2425 || (buf_len % block_size != 0))
\r
2427 return ALT_E_BAD_ARG;
\r
2430 ALT_STATUS_CODE status = ALT_E_SUCCESS;
\r
2431 // Number of block to transfer
\r
2432 uint32_t block_count = buf_len / block_size;
\r
2433 // New count of reading byte
\r
2434 uint32_t byte_count = block_count * block_size;
\r
2437 status = alt_sdmmc_fifo_reset();
\r
2438 if (status != ALT_E_SUCCESS)
\r
2444 status = alt_sdmmc_dma_reset();
\r
2445 if (status != ALT_E_SUCCESS)
\r
2450 alt_sdmmc_byte_count_set(byte_count);
\r
2451 alt_sdmmc_card_rd_threshold_enable(0x80);
\r
2453 uint32_t cmd_index = 0;
\r
2454 if (buf_len == block_size)
\r
2456 cmd_index = (transfer_mode == ALT_SDMMC_TMOD_READ)
\r
2457 ? ALT_SDMMC_READ_SINGLE_BLOCK
\r
2458 : ALT_SDMMC_WRITE_BLOCK;
\r
2462 cmd_index = (transfer_mode == ALT_SDMMC_TMOD_READ)
\r
2463 ? ALT_SDMMC_READ_MULTIPLE_BLOCK
\r
2464 : ALT_SDMMC_WRITE_MULTIPLE_BLOCK;
\r
2467 if (alt_sdmmc_is_dma_enabled())
\r
2469 // Clean descriptor chain
\r
2470 alt_sdmmc_desc_chain_clear();
\r
2472 alt_sdmmc_dma_start(dma_cur_descr, 0x0,
\r
2473 ALT_SDMMC_DMA_PBL_1, false);
\r
2474 //Enable all dma interrupt status
\r
2475 alt_sdmmc_dma_int_enable(ALT_SDMMC_DMA_INT_STATUS_ALL);
\r
2477 if (status != ALT_E_SUCCESS)
\r
2483 dprintf("\nstart_addr = %d\n", (int)start_addr);
\r
2486 //Send transfer command
\r
2487 status = alt_sdmmc_command_send((ALT_SDMMC_CMD_INDEX_t)cmd_index, start_addr / block_size, NULL);
\r
2488 if (status != ALT_E_SUCCESS)
\r
2493 //Send or read data
\r
2494 if (alt_sdmmc_is_dma_enabled())
\r
2496 //Fill descriptors
\r
2497 status = alt_sdmmc_dma_trans_helper(buffer, byte_count);
\r
2501 status = alt_sdmmc_transfer_helper(buffer, byte_count, transfer_mode);
\r
2504 if (status != ALT_E_SUCCESS)
\r
2509 //Wait for data transfer complete
\r
2510 status = alt_sdmmc_data_done_waiter();
\r
2516 // This function performs SDMMC write.
\r
2518 ALT_STATUS_CODE alt_sdmmc_write(void *dest, void *src, const size_t size)
\r
2520 return alt_sdmmc_transfer((uint32_t)dest, src, size, ALT_SDMMC_TMOD_WRITE);
\r
2524 // This function performs SDMMC read.
\r
2526 ALT_STATUS_CODE alt_sdmmc_read(void *dest, void *src, const size_t size)
\r
2528 return alt_sdmmc_transfer((uint32_t)src, dest, size, ALT_SDMMC_TMOD_READ);
\r