]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A9_Cyclone_V_SoC_DK/Altera_Code/HardwareLibrary/alt_sdmmc.c
Update version number in readiness for V10.3.0 release. Sync SVN with reviewed releas...
[freertos] / FreeRTOS / Demo / CORTEX_A9_Cyclone_V_SoC_DK / Altera_Code / HardwareLibrary / alt_sdmmc.c
1 /******************************************************************************\r
2  *\r
3  * Copyright 2013 Altera Corporation. All Rights Reserved.\r
4  * \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
7  * \r
8  * 1. Redistributions of source code must retain the above copyright notice,\r
9  * this list of conditions and the following disclaimer.\r
10  * \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
14  * \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
17  * \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
28  * \r
29  ******************************************************************************/\r
30 \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
38 #include <stdio.h>\r
39 \r
40 /////\r
41 \r
42 //#define LOGGER\r
43 // NOTE: To enable debugging output, delete the next line and uncomment the\r
44 //   line after.\r
45 //#define dprintf(...)\r
46 #define dprintf(fmt, ...) printf(fmt, ##__VA_ARGS__)\r
47 #ifdef LOGGER\r
48 #endif\r
49 \r
50 /////\r
51 \r
52 #define MIN(a, b) ((a) > (b) ? (b) : (a))\r
53 #define ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0]))\r
54 \r
55 /////\r
56 \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
63 \r
64 #define ALT_SDMMC_DMA_SEGMENT_SIZE      512\r
65 #define ALT_SDMMC_DMA_DESC_COUNT        128\r
66 \r
67 #define ALT_SDMMC_FSM_IDLE              0\r
68 #define ALT_SDMMC_DMA_FSM_IDLE          0\r
69 \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
83 {\r
84     ALT_SDMMC_TMOD_READ          = 0,\r
85     ALT_SDMMC_TMOD_WRITE         = 1,\r
86 } ALT_SDMMC_TMOD_t;\r
87 \r
88 #ifdef LOGGER\r
89 uint32_t log_buffer[1000] = { 0 };\r
90 uint32_t log_index = 0;\r
91 \r
92 #define D_ADD_VALUE(value)({if (log_index < 1000) log_buffer[log_index++] = value;})\r
93 #endif\r
94 \r
95 static alt_freq_t clock_freq;\r
96 \r
97 // Default configurations of used commands\r
98 static ALT_SDMMC_CMD_CONFIG_t cmd_default_cfg[20] = \r
99 {\r
100     {\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
106         .card_number = 0,\r
107         .use_hold_reg = true,\r
108         .wait_prvdata_complete = true\r
109     },\r
110     {\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
115         .card_number = 0,\r
116         .use_hold_reg = true,\r
117         .wait_prvdata_complete = true\r
118     },\r
119     {\r
120         .cmd_index = ALT_SD_SEND_SCR,\r
121         .response_expect = true,\r
122         .data_expected = true,\r
123         .card_number = 0,\r
124         .use_hold_reg = true,\r
125         .wait_prvdata_complete = true\r
126     },\r
127     {\r
128         .cmd_index = ALT_SDMMC_WRITE_BLOCK,\r
129         .response_expect = true,\r
130         .data_expected = true,\r
131         .write_active = true,\r
132         .card_number = 0,\r
133         .use_hold_reg = true,\r
134         .wait_prvdata_complete = true\r
135     },\r
136     {\r
137         .cmd_index = ALT_SDMMC_READ_SINGLE_BLOCK,\r
138         .response_expect = true,\r
139         .data_expected = true,\r
140         .card_number = 0,\r
141         .use_hold_reg = true,\r
142         .wait_prvdata_complete = true\r
143     },\r
144     {\r
145         .cmd_index = ALT_SDMMC_SET_BLOCKLEN,\r
146         .response_expect = true,\r
147         .card_number = 0,\r
148         .use_hold_reg = true,\r
149         .wait_prvdata_complete = true\r
150     },\r
151     {\r
152         .cmd_index = ALT_SDMMC_SEL_DES_CARD,\r
153         .response_expect = true,\r
154         .card_number = 0,\r
155         .use_hold_reg = true,\r
156         .wait_prvdata_complete = true\r
157     },\r
158     {\r
159         .cmd_index = ALT_SDMMC_APP_CMD,\r
160         .response_expect = true,\r
161         .card_number = 0,\r
162         .use_hold_reg = true,\r
163         .wait_prvdata_complete = true\r
164     },\r
165     {\r
166         .cmd_index = ALT_SD_SET_BUS_WIDTH,\r
167         .response_expect = true,\r
168         .card_number = 0,\r
169         .use_hold_reg = true,\r
170         .wait_prvdata_complete = true\r
171     },\r
172     {\r
173         .cmd_index = ALT_SD_SEND_OP_COND,\r
174         .response_expect = true,\r
175         .card_number = 0,\r
176         .use_hold_reg = true,\r
177         .wait_prvdata_complete = true\r
178     },\r
179     {\r
180         .cmd_index = ALT_SDMMC_SEND_OP_COND,\r
181         .response_expect = true,\r
182         .card_number = 0,\r
183         .use_hold_reg = true,\r
184         .wait_prvdata_complete = true\r
185     },\r
186     {\r
187         .cmd_index = ALT_SDMMC_IF_COND,\r
188         .response_expect = true,\r
189         .card_number = 0,\r
190         .use_hold_reg = true,\r
191         .wait_prvdata_complete = true\r
192     },\r
193     {\r
194         .cmd_index = ALT_SDMMC_SET_RELATIVE_ADDR,\r
195         .response_expect = true,\r
196         .card_number = 0,\r
197         .use_hold_reg = true,\r
198         .wait_prvdata_complete = true\r
199     },\r
200     {\r
201         .cmd_index = ALT_SDMMC_SEND_STATUS,\r
202         .response_expect = true,\r
203         .card_number = 0,\r
204         .use_hold_reg = true\r
205     },\r
206     {\r
207         .cmd_index = ALT_SDMMC_ALL_SEND_CID,\r
208         .response_expect = true,\r
209         .response_length_long = true,\r
210         .card_number = 0,\r
211         .use_hold_reg = true,\r
212         .wait_prvdata_complete = true\r
213     },\r
214     {\r
215         .cmd_index = ALT_SDMMC_SEND_CID,\r
216         .response_expect = true,\r
217         .response_length_long = true,\r
218         .card_number = 0,\r
219         .use_hold_reg = true,\r
220         .wait_prvdata_complete = true\r
221     },\r
222     {\r
223         .cmd_index = ALT_SDMMC_SEND_CSD,\r
224         .response_expect = true,\r
225         .response_length_long = true,\r
226         .card_number = 0,\r
227         .use_hold_reg = true,\r
228         .wait_prvdata_complete = true\r
229     },\r
230     {\r
231         .cmd_index = ALT_SDMMC_STOP_TRANSMISSION,\r
232         .stop_abort_cmd = true,\r
233         .card_number = 0,\r
234         .use_hold_reg = true,\r
235         .wait_prvdata_complete = true\r
236     },\r
237     {\r
238         .cmd_index = ALT_SDMMC_GO_IDLE_STATE,\r
239         .send_initialization = true,\r
240         .card_number = 0,\r
241         .use_hold_reg = true,\r
242         .wait_prvdata_complete = true\r
243     }\r
244 };\r
245 \r
246 static ALT_SDMMC_CMD_CONFIG_t cmd_clock_cfg = \r
247 {\r
248     .update_clock_registers_only = true,\r
249     .wait_prvdata_complete = true\r
250 };\r
251 \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
257 \r
258 //\r
259 // Reset sdmmc module by reset manager without deassert\r
260 //\r
261 static ALT_STATUS_CODE alt_sdmmc_rstmgr_set(void)\r
262 {\r
263     alt_setbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_SDMMC_SET_MSK);\r
264 \r
265     return ALT_E_SUCCESS;\r
266 }\r
267 \r
268 //\r
269 // Assert reset sdmmc module by reset manager, wait, deasert\r
270 //\r
271 static ALT_STATUS_CODE alt_sdmmc_rstmgr_strobe(void)\r
272 {\r
273     alt_setbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_SDMMC_SET_MSK);\r
274 \r
275     volatile uint32_t timeout = ALT_SDMMC_RESET_TMO_INIT;\r
276 \r
277     // Wait while sdmmc module is reseting\r
278     while (timeout--)\r
279         ;\r
280 \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
283 \r
284     return ALT_E_SUCCESS;\r
285 }\r
286 \r
287 //\r
288 // Initialize descriptor chain for dma\r
289 //\r
290 static ALT_STATUS_CODE alt_sdmmc_desc_chain_init()\r
291 {\r
292     ALT_SDMMC_DMA_BUF_DESC_t * dma_desc = dma_descriptors;\r
293 \r
294     // Initialising descriptor chain\r
295     for (uint32_t count = 0; count < ALT_SDMMC_DMA_DESC_COUNT; count++)\r
296     {\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
302 \r
303         // Create chain description list\r
304         if (count == (ALT_SDMMC_DMA_DESC_COUNT - 1))\r
305         {\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
308         }\r
309         else\r
310         {\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
313         }\r
314     }\r
315     \r
316     dma_cur_descr = dma_desc;\r
317 \r
318     return ALT_E_SUCCESS;\r
319 }\r
320 \r
321 //\r
322 // Clear descriptors of chain for dma operations\r
323 //\r
324 static ALT_STATUS_CODE alt_sdmmc_desc_chain_clear()\r
325 {\r
326     ALT_SDMMC_DMA_BUF_DESC_t * dma_desc = dma_descriptors;\r
327 \r
328     // Clean descriptions\r
329     for (uint32_t count = 0; count < ALT_SDMMC_DMA_DESC_COUNT; count++)\r
330     {\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
337     }\r
338 \r
339     dma_cur_descr = dma_desc;\r
340 \r
341     return ALT_E_SUCCESS;\r
342 }\r
343 \r
344 //\r
345 // Initialize the specified sdmmc controller instance for use and return a device\r
346 // handle referencing it.\r
347 //\r
348 ALT_STATUS_CODE alt_sdmmc_init()\r
349 {\r
350     if (alt_clk_is_enabled(ALT_CLK_SDMMC) != ALT_E_TRUE)\r
351     {\r
352         return ALT_E_BAD_CLK;\r
353     }\r
354 \r
355     /////\r
356 \r
357     ALT_STATUS_CODE status = ALT_E_SUCCESS;\r
358 \r
359     // Query the SDMMC clock.\r
360     if (status == ALT_E_SUCCESS)\r
361     {\r
362         status = alt_clk_freq_get(ALT_CLK_SDMMC, &clock_freq);\r
363     }\r
364 \r
365     // Reset sdmmc module\r
366     if (status == ALT_E_SUCCESS)\r
367     {\r
368         status = alt_sdmmc_reset();\r
369     }\r
370 \r
371     return status;\r
372 }\r
373 \r
374 //\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
377 //\r
378 ALT_STATUS_CODE alt_sdmmc_reset()\r
379 {\r
380     ALT_STATUS_CODE status = ALT_E_SUCCESS;\r
381 \r
382     bool already_enabled = (alt_sdmmc_card_pwr_is_on() == ALT_E_TRUE);\r
383 \r
384     if (already_enabled)\r
385     {\r
386         // Temporarily power off the card\r
387         status = alt_sdmmc_card_pwr_off();\r
388         if (status != ALT_E_SUCCESS)\r
389         {\r
390             return status;\r
391         }\r
392     }\r
393     \r
394     // Reset sdmmc module by reset manager\r
395     alt_sdmmc_rstmgr_strobe();\r
396     \r
397     if (already_enabled)\r
398     {\r
399         // Re-enable card power\r
400         status = alt_sdmmc_card_pwr_on();\r
401     }\r
402 \r
403     // Relative card address have not readed yet\r
404     rca_number = 0;\r
405     // Init description chain\r
406     alt_sdmmc_desc_chain_init();\r
407 \r
408     if (status == ALT_E_SUCCESS)\r
409     {\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
413     }\r
414 \r
415     return status;\r
416 }\r
417 \r
418 //\r
419 // Uninitialize the sdmmc controller referenced by the sdmmc_dev handle.\r
420 //\r
421 ALT_STATUS_CODE alt_sdmmc_uninit(void)\r
422 {\r
423     ALT_STATUS_CODE status = ALT_E_SUCCESS;\r
424 \r
425     // Clean descriptor chain\r
426     alt_sdmmc_desc_chain_clear();\r
427 \r
428     // Card power off\r
429     if (status == ALT_E_SUCCESS)\r
430     {\r
431         status = alt_sdmmc_card_pwr_off();\r
432     }\r
433 \r
434     // Reset sdmmc module by reset manager\r
435     if (status == ALT_E_SUCCESS)\r
436     {\r
437         status = alt_sdmmc_rstmgr_set();\r
438     }\r
439 \r
440     return status;\r
441 }\r
442 \r
443 //\r
444 // Power on of the card.\r
445 //\r
446 ALT_STATUS_CODE alt_sdmmc_card_pwr_on(void)\r
447 {\r
448     alt_setbits_word(ALT_SDMMC_PWREN_ADDR, \r
449                      ALT_SDMMC_PWREN_POWER_EN_SET_MSK);\r
450 \r
451     return ALT_E_SUCCESS;\r
452 }\r
453 \r
454 //\r
455 //Power off of the card.\r
456 //\r
457 ALT_STATUS_CODE alt_sdmmc_card_pwr_off(void)\r
458 {\r
459     //If sdmmc controller is enabled, return with sucess\r
460     if (alt_sdmmc_card_pwr_is_on() == ALT_E_FALSE)\r
461     {\r
462         return ALT_E_SUCCESS;\r
463     }\r
464 \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
468     \r
469     // Clear interrupt status\r
470     alt_sdmmc_int_clear(ALT_SDMMC_INT_STATUS_ALL);\r
471 \r
472     // Relative card address have not readed yet\r
473     rca_number = 0;\r
474     // Reset state of card stack\r
475     return ALT_E_SUCCESS;\r
476 }\r
477 \r
478 //\r
479 // Check whether sdmmc controller is enable\r
480 //\r
481 bool alt_sdmmc_card_pwr_is_on(void)\r
482 {\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
485     {\r
486         return true;\r
487     }\r
488     else\r
489     {\r
490         return false;\r
491     }\r
492 }\r
493 \r
494 //\r
495 // Returns ALT_E_TRUE if the sdmmc controller is busy\r
496 //\r
497 static ALT_STATUS_CODE alt_sdmmc_is_busy(void)\r
498 {\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
501     {\r
502         return ALT_E_TRUE;\r
503     }\r
504     else\r
505     {\r
506         return ALT_E_FALSE;\r
507     }\r
508 }\r
509 \r
510 //\r
511 // Returns ALT_E_TRUE if the sdmmc and iddmac controller is in idle state\r
512 //\r
513 static ALT_STATUS_CODE alt_sdmmc_is_idle(void)\r
514 {\r
515     uint32_t mmc_state = ALT_SDMMC_STAT_CMD_FSM_STATES_GET(alt_read_word(ALT_SDMMC_STAT_ADDR));\r
516     \r
517     uint32_t dma_state = ALT_SDMMC_IDSTS_FSM_GET(alt_read_word(ALT_SDMMC_IDSTS_ADDR));\r
518     \r
519     if ((mmc_state != ALT_SDMMC_FSM_IDLE) || (dma_state != ALT_SDMMC_DMA_FSM_IDLE))\r
520     {\r
521 #ifdef LOGGER\r
522         dprintf("\nstate %x dma_state %x\n", (int)mmc_state, (int)dma_state);\r
523 #endif\r
524         return ALT_E_FALSE;\r
525     }\r
526     else\r
527     {\r
528         return ALT_E_TRUE;\r
529     }\r
530 }\r
531 \r
532 //\r
533 // Get config clock parameters\r
534 //\r
535 uint32_t alt_sdmmc_card_clk_div_get(void)\r
536 {\r
537     return ALT_SDMMC_CLKDIV_CLK_DIVR0_GET(alt_read_word(ALT_SDMMC_CLKDIV_ADDR));\r
538 }\r
539 \r
540 //\r
541 // Set config clock parameters (7.2.3 Clock Programming)\r
542 //\r
543 ALT_STATUS_CODE alt_sdmmc_card_clk_div_set(const uint32_t clk_div)\r
544 {\r
545     if (alt_sdmmc_is_busy() == ALT_E_TRUE)\r
546     {\r
547         return ALT_E_ERROR;\r
548     }\r
549 \r
550     alt_write_word(ALT_SDMMC_CLKDIV_ADDR, ALT_SDMMC_CLKDIV_CLK_DIVR0_SET(clk_div));\r
551 \r
552     return alt_sdmmc_command_send(ALT_SDMMC_CLK_INDEX, 0x0, NULL);\r
553 }\r
554 \r
555 uint32_t alt_sdmmc_card_speed_get(void)\r
556 {\r
557     uint32_t clk_div = alt_sdmmc_card_clk_div_get();\r
558 \r
559     uint32_t speed_bps = clock_freq / (2 * clk_div);\r
560 \r
561     return speed_bps;\r
562 }\r
563 \r
564 ALT_STATUS_CODE alt_sdmmc_card_speed_set(uint32_t xfer_speed)\r
565 {\r
566     uint32_t clk_div = clock_freq / (2 * xfer_speed);\r
567 \r
568     return alt_sdmmc_card_clk_div_set(clk_div);\r
569 }\r
570 \r
571 ALT_STATUS_CODE alt_sdmmc_card_clk_disable(void)\r
572 {\r
573     if (alt_sdmmc_is_busy() == ALT_E_TRUE)\r
574     {\r
575         return ALT_E_ERROR;\r
576     }\r
577 \r
578     alt_write_word(ALT_SDMMC_CLKENA_ADDR, ALT_SDMMC_CLKENA_CCLK_EN_SET(false));\r
579 \r
580     return alt_sdmmc_command_send(ALT_SDMMC_CLK_INDEX, 0x0, NULL);\r
581 }\r
582 \r
583 //\r
584 // Enables the card clock (sdmmc_cclk_out).\r
585 //\r
586 ALT_STATUS_CODE alt_sdmmc_card_clk_enable(const bool use_low_pwr_mode)\r
587 {\r
588     if (alt_sdmmc_is_busy() == ALT_E_TRUE)\r
589     {\r
590         return ALT_E_ERROR;\r
591     }\r
592 \r
593     // Enable clock\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
596 \r
597     return alt_sdmmc_command_send(ALT_SDMMC_CLK_INDEX, 0x0, NULL);\r
598 }\r
599 \r
600 //\r
601 // Returns true if the card clock (sdmmc_cclk_out) is enabled otherwise returns\r
602 //\r
603 bool alt_sdmmc_card_clk_is_enabled(void)\r
604 {\r
605     return ALT_SDMMC_CLKENA_CCLK_EN_GET(alt_read_word(ALT_SDMMC_CLKENA_ADDR));\r
606 }\r
607 \r
608 //\r
609 // Get sdmmc bus width\r
610 //\r
611 static ALT_SDMMC_BUS_WIDTH_t alt_sdmmc_bus_width_get(void)\r
612 {\r
613     uint32_t ctype_register = alt_read_word(ALT_SDMMC_CTYPE_ADDR);\r
614 \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
617 \r
618     if (card_width1 == ALT_SDMMC_CTYPE_CARD_WIDTH1_E_MOD8BIT)\r
619     {\r
620         return ALT_SDMMC_BUS_WIDTH_8;\r
621     }\r
622     else if (card_width2 == ALT_SDMMC_CTYPE_CARD_WIDTH2_E_MOD4BIT)\r
623     {\r
624         return ALT_SDMMC_BUS_WIDTH_4;\r
625     }\r
626     else\r
627     {\r
628         return ALT_SDMMC_BUS_WIDTH_1;\r
629     }\r
630 }\r
631 \r
632 //\r
633 // Set sdmmc bus width\r
634 //\r
635 static ALT_STATUS_CODE alt_sdmmc_bus_width_set(const ALT_SDMMC_BUS_WIDTH_t width)\r
636 {\r
637     // Set config parameters to appropriate registers\r
638     switch (width)\r
639     {\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
644         break;\r
645 \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
653         break;\r
654 \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
662         break;\r
663 \r
664     default:\r
665         return ALT_E_BAD_ARG;\r
666     }\r
667 \r
668     return ALT_E_SUCCESS;\r
669 }\r
670 \r
671 //\r
672 // Get block size\r
673 //\r
674 inline static uint16_t alt_sdmmc_block_size_get(void)\r
675 {\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
678 }\r
679 \r
680 //\r
681 // Set block size\r
682 //\r
683 inline static ALT_STATUS_CODE alt_sdmmc_block_size_set(uint16_t block_size)\r
684 {\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
688 \r
689     return ALT_E_SUCCESS;\r
690 }\r
691 \r
692 //\r
693 // Set byte count\r
694 //\r
695 inline static ALT_STATUS_CODE alt_sdmmc_byte_count_set(uint32_t count)\r
696 {\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
700 \r
701     return ALT_E_SUCCESS;\r
702 }\r
703 \r
704 //\r
705 // Get sdmmc timeouts for command response and data sending\r
706 //\r
707 ALT_STATUS_CODE alt_sdmmc_card_misc_get(ALT_SDMMC_CARD_MISC_t *card_misc_cfg)\r
708 {\r
709     uint32_t tmout_register = alt_read_word(ALT_SDMMC_TMOUT_ADDR);\r
710 \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
713 \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
716 \r
717     card_misc_cfg->debounce_count = ALT_SDMMC_DEBNCE_DEBOUNCE_COUNT_GET(alt_read_word(ALT_SDMMC_DEBNCE_ADDR));\r
718 \r
719     return ALT_E_SUCCESS;\r
720 }\r
721 \r
722 //\r
723 //Set sdmmc timeouts for command response and data sending\r
724 //\r
725 ALT_STATUS_CODE alt_sdmmc_card_misc_set(const ALT_SDMMC_CARD_MISC_t *card_misc_cfg)\r
726 {\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
729 \r
730     alt_write_word(ALT_SDMMC_TMOUT_ADDR, tmout_value);\r
731 \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
735 \r
736     ALT_STATUS_CODE status = ALT_E_SUCCESS;\r
737 \r
738     if (status == ALT_E_SUCCESS)\r
739     {\r
740         status = alt_sdmmc_bus_width_set(card_misc_cfg->card_width);\r
741     }\r
742 \r
743     if (status == ALT_E_SUCCESS)\r
744     {\r
745         status = alt_sdmmc_block_size_set(card_misc_cfg->block_size);\r
746     }\r
747 \r
748     return status;\r
749 }\r
750 \r
751 //\r
752 // Starts the SD/MMC internal DMA transfer with the specified\r
753 // descriptor an bus mode transfer configuration.\r
754 //\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
759 {\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
763 \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
767 \r
768     alt_replbits_word(ALT_SDMMC_BMOD_ADDR, bmod_set_mask, bmod_set_value);\r
769 \r
770     // Set start address of descriptor chain\r
771     alt_write_word(ALT_SDMMC_DBADDR_ADDR, (uint32_t)buf_desc_list);\r
772 \r
773     return ALT_E_SUCCESS;\r
774 }\r
775 \r
776 //\r
777 // Enables the sdmmc write protect.\r
778 //\r
779 bool alt_sdmmc_card_is_write_protected(void)\r
780 {\r
781     alt_setbits_word(ALT_SDMMC_WRTPRT_ADDR, \r
782                      ALT_SDMMC_WRTPRT_WR_PROTECT_SET_MSK);\r
783 \r
784     return ALT_E_SUCCESS;\r
785 }\r
786 \r
787 //\r
788 // FIFO reset\r
789 //\r
790 ALT_STATUS_CODE alt_sdmmc_fifo_reset(void)\r
791 {\r
792     uint32_t timeout = ALT_SDMMC_MAX_T_POLL_COUNT;\r
793 \r
794     // Activate fifo reset\r
795     alt_setbits_word(ALT_SDMMC_CTL_ADDR, ALT_SDMMC_CTL_FIFO_RST_SET_MSK);\r
796     \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
799                                                 && --timeout)\r
800         ;\r
801 \r
802     // If fifo reset still are active, return timeout error\r
803     if (timeout == 0)\r
804     {\r
805         return ALT_E_TMO;\r
806     }\r
807 \r
808     return ALT_E_SUCCESS;\r
809 }\r
810     \r
811 //\r
812 // DMA reset\r
813 //\r
814 ALT_STATUS_CODE alt_sdmmc_dma_reset(void)\r
815 {\r
816     uint32_t timeout = ALT_SDMMC_MAX_T_POLL_COUNT;\r
817 \r
818     //Activate dma reset\r
819     alt_setbits_word(ALT_SDMMC_CTL_ADDR, ALT_SDMMC_CTL_DMA_RST_SET_MSK);\r
820     \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
823                                                 && --timeout)\r
824         ;\r
825 \r
826     // If dma reset still are active, return timeout error\r
827     if (timeout == 0)\r
828     {\r
829         return ALT_E_TMO;\r
830     }\r
831 \r
832     return ALT_E_SUCCESS;\r
833 }\r
834         \r
835 \r
836 //\r
837 // Returns ALT_E_TRUE if the sdmmc controller is present depend on cdata_in.\r
838 //\r
839 bool alt_sdmmc_card_is_detected(void)\r
840 {\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
845     {\r
846         return true;\r
847     }\r
848     else\r
849     {\r
850         return false;\r
851     }\r
852 }\r
853 \r
854 //\r
855 //Set command configuration\r
856 //\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
859                                          bool start_cmd)\r
860 {\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
882 \r
883     alt_write_word(ALT_SDMMC_CMD_ADDR, cmd_register);\r
884 \r
885 #ifdef LOGGER\r
886     dprintf("\ncommand = %X\n", (int)cmd_register);\r
887 #endif\r
888 \r
889     return ALT_E_SUCCESS;\r
890 }\r
891 \r
892 //\r
893 // Set command argument\r
894 //\r
895 inline static ALT_STATUS_CODE alt_sdmmc_cmd_arg_set(uint32_t cmdarg)\r
896 {\r
897     alt_write_word(ALT_SDMMC_CMDARG_ADDR, cmdarg);\r
898 \r
899     return ALT_E_SUCCESS;\r
900 }\r
901 \r
902 //\r
903 // Get response previous command.\r
904 //\r
905 inline static ALT_STATUS_CODE alt_sdmmc_read_short_response(uint32_t *response)\r
906 {\r
907     uint32_t resp0 = alt_read_word(ALT_SDMMC_RESP0_ADDR);\r
908     *response = (uint32_t)(ALT_SDMMC_RESP0_RESPONSE0_GET(resp0));\r
909 \r
910     return ALT_E_SUCCESS;\r
911 }\r
912 \r
913 //\r
914 // Get long response of previous command.\r
915 //\r
916 ALT_STATUS_CODE alt_sdmmc_read_long_response(ALT_SDMMC_RESPONSE_t *response)\r
917 {\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
922 \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
927 \r
928     return ALT_E_SUCCESS;\r
929 }\r
930 \r
931 //\r
932 //This function reads a single data byte from the receive FIFO.\r
933 //\r
934 ALT_STATUS_CODE alt_sdmmc_fifo_read(void *dest, const size_t size)\r
935 {\r
936     uint32_t * dest_ptr = dest;\r
937     for (int counter = 0; counter < size / 4; counter++)\r
938     {\r
939         dest_ptr[counter] = (uint32_t)(ALT_SDMMC_DATA_VALUE_GET(alt_read_word(ALT_SDMMC_DATA_ADDR)));\r
940     }\r
941     \r
942     if (size & 0x3)\r
943     {\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
946     \r
947         for (int counter = 0; counter < (size & 0x3); counter++)\r
948         {\r
949             add_dest_ptr[counter] = (uint8_t)word_notfull;\r
950             word_notfull = word_notfull >> 8;\r
951         }\r
952     }\r
953 \r
954     return ALT_E_SUCCESS;\r
955 }\r
956 \r
957 //\r
958 // This function writes a single data byte to the transmit FIFO.\r
959 //\r
960 ALT_STATUS_CODE alt_sdmmc_fifo_write(const void *src, const size_t size)\r
961 {\r
962     const uint32_t * src_ptr = src;\r
963     for (int counter = 0; counter < size / 4; counter++)\r
964     {\r
965         alt_write_word(ALT_SDMMC_DATA_ADDR, ALT_SDMMC_DATA_VALUE_SET(src_ptr[counter]));\r
966     }\r
967 \r
968     if (size & 0x3)\r
969     {\r
970         const uint8_t *add_src_ptr = (uint8_t*)src + (size / 4);\r
971         uint32_t word_notfull = 0;\r
972 \r
973         for (int counter = 0; counter < (size & 0x3); counter++)\r
974         {\r
975             word_notfull |= (uint32_t)add_src_ptr[counter] << (8 * counter);\r
976         }\r
977 \r
978         alt_write_word(ALT_SDMMC_DATA_ADDR, ALT_SDMMC_DATA_VALUE_SET(word_notfull));\r
979     }\r
980     \r
981     return ALT_E_SUCCESS;\r
982 }\r
983 \r
984 //\r
985 // Returns the current sdmmc controller interrupt status conditions.\r
986 //\r
987 uint32_t alt_sdmmc_int_status_get(void)\r
988 {\r
989     return alt_read_word(ALT_SDMMC_MINTSTS_ADDR);\r
990 }\r
991 \r
992 //\r
993 // Returns the sdmmc controller raw interrupt status conditions irrespective of\r
994 // the interrupt status condition enablement state.\r
995 //\r
996 uint32_t alt_sdmmc_int_mask_get(void)\r
997 {\r
998     return alt_read_word(ALT_SDMMC_INTMSK_ADDR);\r
999 }\r
1000 \r
1001 //\r
1002 // Clears the specified sdmmc controller interrupt status conditions identified\r
1003 // in the mask.\r
1004 //\r
1005 ALT_STATUS_CODE alt_sdmmc_int_clear(const uint32_t mask)\r
1006 {\r
1007     alt_write_word(ALT_SDMMC_RINTSTS_ADDR, mask);\r
1008 \r
1009     return ALT_E_SUCCESS;\r
1010 }\r
1011 \r
1012 //\r
1013 // Disable the specified sdmmc controller interrupt status conditions identified in\r
1014 // the mask.\r
1015 //\r
1016 ALT_STATUS_CODE alt_sdmmc_int_disable(const uint32_t mask)\r
1017 {\r
1018     alt_clrbits_word(ALT_SDMMC_INTMSK_ADDR, mask);\r
1019 \r
1020     return ALT_E_SUCCESS;\r
1021 }\r
1022 \r
1023 //\r
1024 // Enable the specified sdmmc controller interrupt status conditions identified in\r
1025 // the mask.\r
1026 //\r
1027 ALT_STATUS_CODE alt_sdmmc_int_enable(const uint32_t mask)\r
1028 {\r
1029     if (mask & 0x0001ffff)\r
1030     {\r
1031         alt_setbits_word(ALT_SDMMC_CTL_ADDR, \r
1032                      ALT_SDMMC_CTL_INT_EN_SET_MSK);\r
1033 \r
1034         alt_setbits_word(ALT_SDMMC_INTMSK_ADDR, mask);\r
1035     }\r
1036     return ALT_E_SUCCESS;\r
1037 }\r
1038 \r
1039 //\r
1040 //Returns true if SD/MMC controller FIFO has reached the receive watermark level\r
1041 //otherwise returns false.\r
1042 //\r
1043 bool alt_sdmmc_fifo_is_rx_wtrmk_reached(void)\r
1044 {\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
1047     {\r
1048         return true;\r
1049     }\r
1050     else\r
1051     {\r
1052         return false;\r
1053     }\r
1054 }\r
1055 \r
1056 //\r
1057 //Returns true if SD/MMC controller FIFO has reached the transmit watermark level\r
1058 //otherwise returns false.\r
1059 //\r
1060 bool alt_sdmmc_fifo_is_tx_wtrmk_reached(void)\r
1061 {\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
1064     {\r
1065         return true;\r
1066     }\r
1067     else\r
1068     {\r
1069         return false;\r
1070     }\r
1071 }\r
1072 \r
1073 //\r
1074 // Returns ALT_E_TRUE when the receive FIFO is empty.\r
1075 //\r
1076 bool alt_sdmmc_fifo_is_empty(void)\r
1077 {\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
1080     {\r
1081         return true;\r
1082     }\r
1083     else\r
1084     {\r
1085         return false;\r
1086     }\r
1087 }\r
1088 \r
1089 //\r
1090 // Returns ALT_E_TRUE when the receive FIFO is completely full.\r
1091 //\r
1092 bool alt_sdmmc_fifo_is_full(void)\r
1093 {\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
1096     {\r
1097         return true;\r
1098     }\r
1099     else\r
1100     {\r
1101         return false;\r
1102     }\r
1103 }\r
1104 \r
1105 //\r
1106 // Returns the number of valid entries in the receive FIFO.\r
1107 //\r
1108 int32_t alt_sdmmc_fifo_count(void)\r
1109 {\r
1110     return (int32_t)ALT_SDMMC_STAT_FIFO_COUNT_GET(alt_read_word(ALT_SDMMC_STAT_ADDR));\r
1111 }\r
1112 \r
1113 //\r
1114 // Gets the configured FIFO operational parameter values.\r
1115 //\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
1117 {\r
1118     uint32_t fifoth = alt_read_word(ALT_SDMMC_FIFOTH_ADDR);\r
1119 \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
1123 \r
1124     return ALT_E_SUCCESS;\r
1125 }\r
1126 \r
1127 //\r
1128 // Sets the configured FIFO operational parameter values.\r
1129 //\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
1131 {\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
1135     \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
1139                             \r
1140     alt_replbits_word(ALT_SDMMC_FIFOTH_ADDR,\r
1141                       fifoth_set_mask,\r
1142                       fifoth_set_value);\r
1143 \r
1144     return ALT_E_SUCCESS;\r
1145 }\r
1146 \r
1147 //\r
1148 // Card reset\r
1149 //\r
1150 ALT_STATUS_CODE alt_sdmmc_card_reset(void)\r
1151 {\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
1155 \r
1156     volatile uint32_t timeout = ALT_SDMMC_RESET_TMO_INIT;\r
1157 \r
1158     // Wait while card reset\r
1159     while (timeout--)\r
1160         ;\r
1161 \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
1165 \r
1166     return ALT_E_SUCCESS;\r
1167 }\r
1168 \r
1169 //\r
1170 // Enables the sdmmc Internal DMA Controller.\r
1171 //\r
1172 ALT_STATUS_CODE alt_sdmmc_dma_enable(void)\r
1173 {\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
1178 \r
1179     return ALT_E_SUCCESS;\r
1180 }\r
1181 \r
1182 //\r
1183 // Disables the sdmmc Internal DMA Controller\r
1184 //\r
1185 ALT_STATUS_CODE alt_sdmmc_dma_disable(void)\r
1186 {\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
1191 \r
1192     return ALT_E_SUCCESS;\r
1193 }\r
1194 \r
1195 //\r
1196 // Enables the sdmmc Internal DMA Controller.\r
1197 //\r
1198 ALT_STATUS_CODE alt_sdmmc_is_dma_enabled(void)\r
1199 {\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
1202     {\r
1203         return ALT_E_TRUE;\r
1204     }\r
1205     else\r
1206     {\r
1207         return ALT_E_FALSE;\r
1208     }\r
1209 }\r
1210 \r
1211 //\r
1212 // Returns the current sdmmc controller interrupt IDMAC status conditions.\r
1213 //\r
1214 uint32_t alt_sdmmc_dma_int_status_get(void)\r
1215 {\r
1216     return alt_read_word(ALT_SDMMC_IDSTS_ADDR);\r
1217 }\r
1218 \r
1219 //\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
1222 //\r
1223 uint32_t alt_sdmmc_dma_int_mask_get(void)\r
1224 {\r
1225     return alt_read_word(ALT_SDMMC_IDINTEN_ADDR);\r
1226 }\r
1227 \r
1228 //\r
1229 // Clears the specified sdmmc controller interrupt status IDMAC conditions identified\r
1230 // in the mask.\r
1231 //\r
1232 ALT_STATUS_CODE alt_sdmmc_dma_int_clear(const uint32_t mask)\r
1233 {\r
1234     alt_write_word(ALT_SDMMC_IDSTS_ADDR, mask);\r
1235 \r
1236     return ALT_E_SUCCESS;\r
1237 }\r
1238 \r
1239 //\r
1240 // Disable the specified sdmmc controller interrupt IDMAC status conditions identified in\r
1241 // the mask.\r
1242 //\r
1243 ALT_STATUS_CODE alt_sdmmc_dma_int_disable(const uint32_t mask)\r
1244 {\r
1245     alt_clrbits_word(ALT_SDMMC_IDINTEN_ADDR, mask);\r
1246 \r
1247     return ALT_E_SUCCESS;\r
1248 }\r
1249 \r
1250 //\r
1251 // Enable the specified sdmmc controller interrupt status conditions identified in\r
1252 // the mask.\r
1253 //\r
1254 ALT_STATUS_CODE alt_sdmmc_dma_int_enable(const uint32_t mask)\r
1255 {\r
1256     alt_setbits_word(ALT_SDMMC_IDINTEN_ADDR, mask);\r
1257 \r
1258     return ALT_E_SUCCESS;\r
1259 }\r
1260 \r
1261 //\r
1262 // Sets value into this register for the IDMAC FSM to resume normal descriptor fetch operation.\r
1263 //\r
1264 ALT_STATUS_CODE alt_sdmmc_poll_demand_set(const uint32_t value)\r
1265 {\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
1269 \r
1270     return ALT_E_SUCCESS;\r
1271 }\r
1272 \r
1273 //\r
1274 // Disable Card Read Threshold .\r
1275 //\r
1276 ALT_STATUS_CODE alt_sdmmc_card_rd_threshold_disable(void)\r
1277 {\r
1278     alt_clrbits_word(ALT_SDMMC_CARDTHRCTL_ADDR,\r
1279                      ALT_SDMMC_CARDTHRCTL_CARDRDTHREN_SET_MSK);\r
1280 \r
1281     return ALT_E_SUCCESS;\r
1282 }\r
1283 \r
1284 \r
1285 //\r
1286 // Enable Card Read Threshold .\r
1287 //\r
1288 ALT_STATUS_CODE alt_sdmmc_card_rd_threshold_enable(const uint32_t threshold)\r
1289 {\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
1295 \r
1296     return ALT_E_SUCCESS;\r
1297 }\r
1298 \r
1299 //\r
1300 // This function return ALT_E_ERROR if interrupt error was detected\r
1301 //\r
1302 static ALT_STATUS_CODE alt_sdmmc_error_status_detect(void)\r
1303 {\r
1304     ALT_STATUS_CODE status = ALT_E_SUCCESS;\r
1305     uint32_t int_status = 0;\r
1306 \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
1317 \r
1318     int_status = alt_sdmmc_int_status_get();\r
1319     if (status != ALT_E_SUCCESS)\r
1320     {\r
1321         return status;\r
1322     }\r
1323     \r
1324     // Checking on errors\r
1325     if (int_status & err)\r
1326     {\r
1327         status = ALT_E_ERROR;\r
1328     }\r
1329 \r
1330     return status;\r
1331 }\r
1332 \r
1333 //\r
1334 // Read/write all data from/to buffer\r
1335 //\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
1339 {\r
1340 #ifdef LOGGER\r
1341     dprintf("\nalt_sdmmc_transfer_helper\n");\r
1342 #endif\r
1343 \r
1344     ALT_STATUS_CODE status = ALT_E_SUCCESS;\r
1345 \r
1346     uint32_t data_size = size;\r
1347     bool read_freeze  = false;\r
1348     bool write_freeze = false;\r
1349     \r
1350     while (data_size > 0)\r
1351     {\r
1352 #ifdef LOGGER\r
1353         dprintf("\ndata_size = %x\n", (int)data_size);\r
1354         // Error handling\r
1355 #endif\r
1356         // Error checking\r
1357         status = alt_sdmmc_error_status_detect();\r
1358 \r
1359         if (status != ALT_E_SUCCESS)\r
1360         {\r
1361             break;\r
1362         }\r
1363 \r
1364         uint32_t timeout = ALT_SDMMC_TMO_WAITER;\r
1365 \r
1366         do\r
1367         {\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
1372 #ifdef LOGGER\r
1373             dprintf("\nread_freeze = %x write_freeze = %x\n", (int)read_freeze, (int)write_freeze);\r
1374 #endif\r
1375             if (--timeout == 0)\r
1376             {\r
1377                 status = ALT_E_TMO;\r
1378                 return status;\r
1379             }\r
1380         }\r
1381         while (read_freeze || write_freeze);\r
1382         \r
1383         uint32_t level = alt_sdmmc_fifo_count();\r
1384 \r
1385 #ifdef LOGGER\r
1386         dprintf("\nfifo level = %x\n", (int)level);\r
1387 #endif\r
1388 \r
1389         // Top up the TX FIFO with read issues\r
1390 \r
1391         if (transfer_mode == ALT_SDMMC_TMOD_WRITE)\r
1392         {\r
1393             uint32_t free_space = ALT_SDMMC_FIFO_NUM_ENTRIES - level;\r
1394             free_space = MIN(data_size / 4, free_space);\r
1395 \r
1396             for (uint32_t i = 0; i < free_space; i++)\r
1397             {\r
1398                 alt_write_word(ALT_SDMMC_DATA_ADDR, *buffer);\r
1399                 ++buffer;\r
1400             }\r
1401             data_size -= free_space * 4;\r
1402         }\r
1403 \r
1404         // Read out the resulting received data as they come in.\r
1405 \r
1406         if (transfer_mode == ALT_SDMMC_TMOD_READ)\r
1407         {\r
1408             level = MIN(data_size / 4, level);\r
1409 \r
1410             for (uint32_t i = 0; i < level; i++)\r
1411             {\r
1412                 *buffer = ALT_SDMMC_DATA_VALUE_GET(alt_read_word(ALT_SDMMC_DATA_ADDR));\r
1413                 ++buffer;\r
1414             }\r
1415 \r
1416             data_size -= level * 4;\r
1417         }\r
1418     }\r
1419 \r
1420     return status;\r
1421 }\r
1422 \r
1423 //\r
1424 // Fill descriptors\r
1425 //\r
1426 static ALT_STATUS_CODE alt_sdmmc_dma_trans_helper(uint32_t * buffer,\r
1427                                                   size_t buf_len)\r
1428 {\r
1429 #ifdef LOGGER\r
1430     dprintf("\nalt_sdmmc_dma_trans_helper: buf_len = %d\n",\r
1431                                                 (int)buf_len);\r
1432 #endif\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
1436 \r
1437     uint32_t cur_buffer = (uint32_t)buffer;\r
1438     uint32_t len_left = buf_len;\r
1439 \r
1440     while (len_left > 0)\r
1441     {\r
1442         //Error checking\r
1443         status = alt_sdmmc_error_status_detect();\r
1444         if (status != ALT_E_SUCCESS)\r
1445         {\r
1446             status = ALT_E_ERROR;\r
1447             break;\r
1448         }\r
1449         //If current descriptor is free then fill it\r
1450         if (cur_dma_desc->des0.fld.own == 0)\r
1451         {\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
1461 \r
1462 #ifdef LOGGER\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
1465 #endif\r
1466 \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
1476         }\r
1477 \r
1478         uint32_t idmac_status = alt_sdmmc_dma_int_status_get();\r
1479 \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
1482         {\r
1483             alt_sdmmc_poll_demand_set(0xFFFF);\r
1484             alt_sdmmc_dma_int_clear(ALT_SDMMC_DMA_INT_STATUS_ALL);\r
1485         }\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
1488         {\r
1489             status = ALT_E_ERROR;\r
1490             break;\r
1491         }\r
1492 \r
1493     }\r
1494 \r
1495     return status;\r
1496 \r
1497 }\r
1498 \r
1499 //\r
1500 // Waiter of data transfer complete\r
1501 //\r
1502 static ALT_STATUS_CODE alt_sdmmc_data_done_waiter(void)\r
1503 {\r
1504     ALT_STATUS_CODE status = ALT_E_TMO;\r
1505     uint32_t timeout = ALT_SDMMC_TMO_WAITER;\r
1506 \r
1507     while (--timeout)\r
1508     {\r
1509         uint32_t int_status;\r
1510         int_status = alt_sdmmc_int_status_get();\r
1511 \r
1512         // Error checking\r
1513         if (alt_sdmmc_error_status_detect() != ALT_E_SUCCESS)\r
1514         {\r
1515             status = ALT_E_ERROR;\r
1516             break;\r
1517         }\r
1518 \r
1519         uint32_t idmac_status = alt_sdmmc_dma_int_status_get();\r
1520 \r
1521         // If DMA status is abnormal then transfer complete with error\r
1522         if (idmac_status & ALT_SDMMC_DMA_INT_STATUS_AI)\r
1523         {\r
1524             status = ALT_E_ERROR;\r
1525             break;\r
1526         }\r
1527         // Data transfer over caused by complete transfer operation\r
1528         if (int_status & ALT_SDMMC_INT_STATUS_DTO)\r
1529         {\r
1530             alt_sdmmc_int_clear(ALT_SDMMC_INT_STATUS_DTO);\r
1531             status = ALT_E_SUCCESS;\r
1532             break;\r
1533         }\r
1534     }\r
1535 \r
1536     timeout = ALT_SDMMC_TMO_WAITER;\r
1537     while (!alt_sdmmc_is_idle() && timeout--)\r
1538         ;\r
1539     if (timeout == 0)\r
1540     {\r
1541         status = ALT_E_TMO;\r
1542     }\r
1543 \r
1544     return status;\r
1545 }\r
1546 \r
1547 \r
1548 //\r
1549 // Waiter of clock command complete\r
1550 //\r
1551 static ALT_STATUS_CODE alt_sdmmc_clock_waiter(void)\r
1552 {\r
1553     ALT_STATUS_CODE status = ALT_E_TMO;\r
1554     uint32_t timeout = ALT_SDMMC_TMO_WAITER;\r
1555     \r
1556     while (--timeout)\r
1557     {\r
1558         uint32_t cmd_register = alt_read_word(ALT_SDMMC_CMD_ADDR);\r
1559         \r
1560         // Error checking\r
1561         if (alt_sdmmc_error_status_detect() != ALT_E_SUCCESS)\r
1562         {\r
1563             status = ALT_E_ERROR;\r
1564             break;\r
1565         }\r
1566 \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
1569         {\r
1570             status = ALT_E_SUCCESS;\r
1571             break;\r
1572         }\r
1573     }\r
1574     return status;\r
1575 }\r
1576 \r
1577 //\r
1578 // Waiter of command complete\r
1579 //\r
1580 static ALT_STATUS_CODE alt_sdmmc_cmd_waiter(void)\r
1581 {\r
1582     ALT_STATUS_CODE status = ALT_E_TMO;\r
1583     uint32_t timeout = ALT_SDMMC_TMO_WAITER;\r
1584     \r
1585     while (--timeout)\r
1586     {\r
1587         uint32_t int_status;\r
1588         int_status = alt_sdmmc_int_status_get();\r
1589 \r
1590         // Error checking\r
1591         if (alt_sdmmc_error_status_detect() != ALT_E_SUCCESS)\r
1592         {\r
1593             status = ALT_E_ERROR;\r
1594             break;\r
1595         }\r
1596         \r
1597         //Check command done\r
1598         if (int_status & ALT_SDMMC_INT_STATUS_CMD)\r
1599         {\r
1600             alt_sdmmc_int_clear(ALT_SDMMC_INT_STATUS_CMD);\r
1601             status = ALT_E_SUCCESS;\r
1602             break;\r
1603         }\r
1604     }\r
1605     return status;\r
1606 }\r
1607 \r
1608 //\r
1609 // Read SRC register from card and read supported bus width\r
1610 //\r
1611 static ALT_STATUS_CODE alt_sdmmc_card_scr_get(uint64_t *scr_reg)\r
1612 {\r
1613     ALT_STATUS_CODE status = ALT_E_SUCCESS;\r
1614 #ifdef LOGGER\r
1615     uint32_t response = 0;\r
1616 #endif\r
1617     \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
1623 \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
1627     {\r
1628         return status;\r
1629     }\r
1630 \r
1631 #ifdef LOGGER\r
1632     alt_sdmmc_read_short_response(&response);\r
1633     dprintf("\nALT_SDMMC_APP_CMD response = %x\n", (int)response);\r
1634 #endif\r
1635     \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
1639     {\r
1640         return status;\r
1641     }\r
1642     \r
1643 #ifdef LOGGER\r
1644     alt_sdmmc_read_short_response(&response);\r
1645     dprintf("\nALT_SD_SEND_SCR responce = %x\n", (int)response);\r
1646 #endif\r
1647 \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
1651     {\r
1652         return status;\r
1653     }\r
1654 \r
1655     // Transfer complete\r
1656     status = alt_sdmmc_data_done_waiter();\r
1657     if (status != ALT_E_SUCCESS)\r
1658     {\r
1659         return status;\r
1660     }\r
1661 \r
1662 #ifdef LOGGER\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
1666     {\r
1667         dprintf("%02x", scr_buf_8[count]);\r
1668     }\r
1669     dprintf("\n");\r
1670 #endif\r
1671 \r
1672     // Re-change block size\r
1673     alt_sdmmc_block_size_set(prev_blk_size);\r
1674 \r
1675     return status;\r
1676 }\r
1677 \r
1678 //\r
1679 // Set sdmmc card width\r
1680 //\r
1681 ALT_STATUS_CODE alt_sdmmc_card_bus_width_set(const ALT_SDMMC_BUS_WIDTH_t width)\r
1682 {\r
1683     ALT_STATUS_CODE status = ALT_E_SUCCESS;\r
1684 \r
1685     uint64_t scr_reg;\r
1686     \r
1687     // Read SRC register\r
1688     status = alt_sdmmc_card_scr_get(&scr_reg);\r
1689     if (status != ALT_E_SUCCESS)\r
1690     {\r
1691         return status;\r
1692     }\r
1693 \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
1697 \r
1698 #ifdef LOGGER\r
1699     dprintf("\nbus_width_supported = %02x\n", (int)supported_bus_width);\r
1700 #endif\r
1701 \r
1702     if ((supported_bus_width & width) == 0)\r
1703     {\r
1704         return ALT_E_BAD_ARG;\r
1705     }\r
1706 \r
1707     uint32_t set_width_arg;\r
1708     switch (width)\r
1709     {\r
1710     case ALT_SDMMC_BUS_WIDTH_8:\r
1711         set_width_arg = 0x3;\r
1712         break;\r
1713     case ALT_SDMMC_BUS_WIDTH_4:\r
1714         set_width_arg = 0x2;\r
1715         break;\r
1716     case ALT_SDMMC_BUS_WIDTH_1:\r
1717         set_width_arg = 0x0;\r
1718         break;\r
1719     default:\r
1720         return ALT_E_BAD_ARG;\r
1721     }\r
1722 \r
1723 #ifdef LOGGER\r
1724     uint32_t response = 0;\r
1725 #endif\r
1726 \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
1730     {\r
1731         return status;\r
1732     }\r
1733 \r
1734 #ifdef LOGGER\r
1735     alt_sdmmc_read_short_response(&response);\r
1736     dprintf("\nALT_SDMMC_APP_CMD response = %x\n", (int)response);\r
1737 #endif\r
1738     \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
1742     {\r
1743         return status;\r
1744     }\r
1745 \r
1746 #ifdef LOGGER\r
1747     alt_sdmmc_read_short_response(&response);\r
1748     dprintf("\nALT_SD_SET_BUS_WIDTH responce = %x\n", (int)response);\r
1749 #endif\r
1750     \r
1751     // Set new bus width in controller register\r
1752     alt_sdmmc_bus_width_set(width);\r
1753     \r
1754     return status;\r
1755 }\r
1756 \r
1757 //\r
1758 // Set block size\r
1759 //\r
1760 ALT_STATUS_CODE alt_sdmmc_card_block_size_set(const uint16_t block_size)\r
1761 {\r
1762     ALT_STATUS_CODE status = ALT_E_SUCCESS;\r
1763     \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
1767     {\r
1768         return status;\r
1769     }\r
1770 \r
1771 #ifdef LOGGER\r
1772     uint32_t response;\r
1773 \r
1774     alt_sdmmc_read_short_response(&response);\r
1775     dprintf("\nALT_SDMMC_SET_BLOCKLEN response = %x\n", (int)response);\r
1776 #endif\r
1777 \r
1778     // Set new block size in controller register\r
1779     alt_sdmmc_block_size_set(block_size);\r
1780 \r
1781     return status;\r
1782 }\r
1783 \r
1784 //\r
1785 // Enumerated Card Stack ident sdio io only\r
1786 //\r
1787 static ALT_STATUS_CODE alt_sdmmc_card_ident_io_only(ALT_SDMMC_CARD_INFO_t *card_info)\r
1788 {\r
1789 #ifdef LOGGER\r
1790     dprintf("\nalt_sdmmc_card_ident_io_only\n");\r
1791 #endif\r
1792     ALT_STATUS_CODE status = ALT_E_SUCCESS;\r
1793 \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
1800     {\r
1801         int_status = alt_sdmmc_int_status_get();\r
1802         if (int_status & ALT_SDMMC_INT_STATUS_RTO)\r
1803         {\r
1804             return ALT_E_SUCCESS;\r
1805         }\r
1806         else\r
1807         {\r
1808             return status;\r
1809         }\r
1810     }\r
1811 \r
1812 #ifdef LOGGER\r
1813     alt_sdmmc_read_short_response(&response);\r
1814     dprintf("\nALT_SDMMC_SEND_OP_COND_1 = %x\n", (int)response);\r
1815 #endif\r
1816 \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
1820     {\r
1821         int_status = alt_sdmmc_int_status_get();\r
1822         if (int_status & ALT_SDMMC_INT_STATUS_RTO)\r
1823         {\r
1824             return ALT_E_SUCCESS;\r
1825         }\r
1826         else\r
1827         {\r
1828             return status;\r
1829         }\r
1830     }\r
1831     \r
1832 #ifdef LOGGER\r
1833     dprintf("\nALT_SDMMC_SEND_OP_COND_2 response = %x\n", (int)response);\r
1834 #endif\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
1840 \r
1841     return ALT_E_SUCCESS;\r
1842 }\r
1843 \r
1844 //\r
1845 // Enumerated Card Stack ident sdhc type\r
1846 //\r
1847 static ALT_STATUS_CODE alt_sdmmc_card_ident_sdhc(ALT_SDMMC_CARD_INFO_t *card_info)\r
1848 {\r
1849 #ifdef LOGGER\r
1850     dprintf("\nalt_sdmmc_card_ident_sdhc\n");\r
1851 #endif\r
1852     ALT_STATUS_CODE status = ALT_E_SUCCESS;\r
1853 \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
1859     {\r
1860         int_status = alt_sdmmc_int_status_get();\r
1861         if (int_status & ALT_SDMMC_INT_STATUS_RTO)\r
1862         {\r
1863             return ALT_E_SUCCESS;\r
1864         }\r
1865         else\r
1866         {\r
1867             return status;\r
1868         }\r
1869     }\r
1870     \r
1871 #ifdef LOGGER\r
1872     alt_sdmmc_read_short_response(&response);\r
1873     dprintf("\nALT_SDMMC_GO_IDLE_STATE response = %x\n", (int)response);\r
1874 #endif\r
1875     \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
1880     {\r
1881         int_status = alt_sdmmc_int_status_get();\r
1882         if (int_status & ALT_SDMMC_INT_STATUS_RTO)\r
1883         {\r
1884             return ALT_E_SUCCESS;\r
1885         }\r
1886         else\r
1887         {\r
1888             return status;\r
1889         }\r
1890     }\r
1891     \r
1892     alt_sdmmc_read_short_response(&response);\r
1893 #ifdef LOGGER\r
1894     dprintf("\nALT_SDMMC_IF_COND response = %x\n", (int)response);\r
1895 #endif\r
1896     \r
1897     if (response != 0x1AA)\r
1898     {\r
1899         return ALT_E_ERROR;\r
1900     }\r
1901 \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
1907     {\r
1908         int_status = alt_sdmmc_int_status_get();\r
1909         if (int_status & ALT_SDMMC_INT_STATUS_RTO)\r
1910         {\r
1911             return ALT_E_SUCCESS;\r
1912         }\r
1913         else\r
1914         {\r
1915             return status;\r
1916         }\r
1917     }\r
1918 \r
1919 #ifdef LOGGER\r
1920     alt_sdmmc_read_short_response(&response);\r
1921     dprintf("\nALT_SDMMC_APP_CMD response = %x\n", (int)response);\r
1922 #endif\r
1923     \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
1927     // line. \r
1928     status = alt_sdmmc_command_send(ALT_SD_SEND_OP_COND, 0x40FF8000, &response);\r
1929     if (status != ALT_E_SUCCESS)\r
1930     {\r
1931         int_status = alt_sdmmc_int_status_get();\r
1932         if (int_status & ALT_SDMMC_INT_STATUS_RTO)\r
1933         {\r
1934             return ALT_E_SUCCESS;\r
1935         }\r
1936         else\r
1937         {\r
1938             return status;\r
1939         }\r
1940     }\r
1941 \r
1942 #ifdef LOGGER\r
1943     alt_sdmmc_read_short_response(&response);\r
1944     dprintf("\nALT_SD_SEND_OP_COND responce = %x\n", (int)response);\r
1945 #endif\r
1946     \r
1947     //Enumerated Card Stack p.3d\r
1948     card_info->card_type = ALT_SDMMC_CARD_TYPE_SDHC;\r
1949 \r
1950     return status;\r
1951 }\r
1952 \r
1953 //\r
1954 //Enumerated Card Stack ident sd type\r
1955 //\r
1956 static ALT_STATUS_CODE alt_sdmmc_card_ident_sd(ALT_SDMMC_CARD_INFO_t *card_info)\r
1957 {\r
1958 #ifdef LOGGER\r
1959     dprintf("\nalt_sdmmc_card_ident_sd\n");\r
1960 #endif\r
1961     ALT_STATUS_CODE status = ALT_E_SUCCESS;\r
1962 \r
1963     uint32_t int_status = 0;\r
1964 #ifdef LOGGER\r
1965     uint32_t response = 0;\r
1966 #endif\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
1973     {\r
1974         int_status = alt_sdmmc_int_status_get();\r
1975         if (int_status & ALT_SDMMC_INT_STATUS_RTO)\r
1976         {\r
1977             return ALT_E_SUCCESS;\r
1978         }\r
1979         else\r
1980         {\r
1981             return status;\r
1982         }\r
1983     }\r
1984 \r
1985 #ifdef LOGGER\r
1986     alt_sdmmc_read_short_response(&response);\r
1987     dprintf("\nALT_SDMMC_APP_CMD response = %x\n", (int)response);\r
1988 #endif\r
1989     \r
1990     // Asks the accessed card to send its operating condition \r
1991     // register (OCR) con tent in the response on the CMD \r
1992     // line. \r
1993     status = alt_sdmmc_command_send(ALT_SD_SEND_OP_COND, 0x00FF8000, NULL);\r
1994     if (status != ALT_E_SUCCESS)\r
1995     {\r
1996         int_status = alt_sdmmc_int_status_get();\r
1997         if (int_status & ALT_SDMMC_INT_STATUS_RTO)\r
1998         {\r
1999             return ALT_E_SUCCESS;\r
2000         }\r
2001         else\r
2002         {\r
2003             return status;\r
2004         }\r
2005     }\r
2006     \r
2007 #ifdef LOGGER\r
2008     alt_sdmmc_read_short_response(&response);\r
2009     dprintf("\nALT_SD_SEND_OP_COND responce = %x\n", (int)response);\r
2010 #endif\r
2011     \r
2012     // Enumerated Card Stack p.3f\r
2013     card_info->card_type = ALT_SDMMC_CARD_TYPE_SD;\r
2014 \r
2015     return status;\r
2016 }\r
2017 \r
2018 //\r
2019 // Enumerated Card Stack enumarete sd cart type\r
2020 //\r
2021 static ALT_STATUS_CODE alt_sdmmc_card_enum_sd(ALT_SDMMC_CARD_INFO_t *card_info)\r
2022 {\r
2023 #ifdef LOGGER\r
2024     dprintf("\nalt_sdmmc_card_enum_sd\n");\r
2025 #endif\r
2026     ALT_STATUS_CODE status = ALT_E_SUCCESS;\r
2027 \r
2028     uint32_t clk_div = clock_freq / (2 * 400000);\r
2029 \r
2030     status = alt_sdmmc_card_clk_div_set(clk_div);\r
2031     if (status != ALT_E_SUCCESS)\r
2032     {\r
2033         return status;\r
2034     }\r
2035     status = alt_sdmmc_card_clk_enable(false);\r
2036     if (status != ALT_E_SUCCESS)\r
2037     {\r
2038         return status;\r
2039     }\r
2040     \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
2045     {\r
2046         return status;\r
2047     }\r
2048     \r
2049 #ifdef LOGGER\r
2050     alt_sdmmc_read_short_response(&response);\r
2051     dprintf("\nALT_SDMMC_GO_IDLE_STATE response = %x\n", (int)response);\r
2052 #endif\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
2056     {\r
2057         return status;\r
2058     }\r
2059 \r
2060 #ifdef LOGGER\r
2061     alt_sdmmc_read_short_response(&response);\r
2062     dprintf("\nALT_SDMMC_IF_COND response = %x\n", (int)response);\r
2063 #endif\r
2064 \r
2065 /*    OCR Bit VDD Voltage Window \r
2066            0-3          Reserved \r
2067             4             1.6-1.7 \r
2068             5             1.7-1.8 \r
2069             6             1.8-1.9 \r
2070             7             1.9-2.0 \r
2071             8             2.0-2.1 \r
2072             9             2.1-2.2 \r
2073             10           2.2-2.3 \r
2074             11           2.3-2.4 \r
2075             12           2.4-2.5 \r
2076             13           2.5-2.6 \r
2077             14           2.6-2.7 \r
2078             15           2.7-2.8 \r
2079             16           2.8-2.9 \r
2080             17           2.9-3.0 \r
2081             18           3.0-3.1 \r
2082             19           3.1-3.2 \r
2083             20           3.2-3.3 \r
2084             21           3.3-3.4 \r
2085             22           3.4-3.5 \r
2086             23           3.5-3.6 \r
2087           24-29       Reserved \r
2088             30          High capacity card\r
2089             31          Card power up status bit (busy)\r
2090 */\r
2091     uint32_t ocr_reg = 0xFF8000;\r
2092 \r
2093     if (card_info->card_type == ALT_SDMMC_CARD_TYPE_SDHC)\r
2094     {\r
2095         ocr_reg |= (1 << 30);\r
2096     }\r
2097 \r
2098     do\r
2099     {\r
2100         status = alt_sdmmc_command_send(ALT_SDMMC_APP_CMD, 0x0, &response);\r
2101         if (status != ALT_E_SUCCESS)\r
2102         {\r
2103             return status;\r
2104         }\r
2105 \r
2106 #ifdef LOGGER\r
2107         alt_sdmmc_read_short_response(&response);\r
2108         dprintf("\nALT_SDMMC_APP_CMD response = %x\n", (int)response);\r
2109 #endif\r
2110         \r
2111         volatile uint32_t timeout = 1000000;\r
2112 \r
2113         // Wait while sdmmc module is reseting\r
2114         while (timeout--)\r
2115             ;\r
2116         status = alt_sdmmc_command_send(ALT_SD_SEND_OP_COND, 0x40FF8000, &response);\r
2117         if (status != ALT_E_SUCCESS)\r
2118         {\r
2119             return status;\r
2120         }\r
2121 \r
2122         alt_sdmmc_read_short_response(&response);\r
2123 #ifdef LOGGER\r
2124         dprintf("\nALT_SD_SEND_OP_COND response = %x\n", (int)response);\r
2125 #endif\r
2126     }\r
2127     while ((response & (1UL << 31)) == 0);\r
2128     \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
2133     {\r
2134         return status;\r
2135     }\r
2136 \r
2137 #ifdef LOGGER\r
2138     alt_sdmmc_read_short_response(&response);\r
2139     dprintf("\nALT_SDMMC_ALL_SEND_CID response = %x\n", (int)response);\r
2140 #endif\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
2144     {\r
2145         return status;\r
2146     }\r
2147 \r
2148     alt_sdmmc_read_short_response(&response);\r
2149 #ifdef LOGGER\r
2150     dprintf("\nALT_SDMMC_SET_RELATIVE_ADDR responce = %x\n", (int)response);\r
2151 #endif\r
2152     \r
2153     uint32_t RCA_number = response & 0xFFFF0000;\r
2154     rca_number = RCA_number;\r
2155 \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
2159     {\r
2160         return status;\r
2161     }\r
2162 \r
2163 #ifdef LOGGER\r
2164     alt_sdmmc_read_short_response(&response);\r
2165     dprintf("\nALT_SDMMC_SEND_CID responce = %x\n", (int)response);\r
2166 #endif\r
2167 \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
2172     {\r
2173         return status;\r
2174     }\r
2175 \r
2176 #ifdef LOGGER\r
2177     alt_sdmmc_read_short_response(&response);\r
2178     dprintf("\nALT_SDMMC_SEND_CSD responce = %x\n", (int)response);\r
2179 #endif\r
2180 \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
2194     {\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
2198     }\r
2199     else\r
2200     {\r
2201         return ALT_E_ERROR;\r
2202     }\r
2203 \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
2209     {\r
2210         return status;\r
2211     }\r
2212 \r
2213 #ifdef LOGGER\r
2214     alt_sdmmc_read_short_response(&response);\r
2215     dprintf("\nALT_SDMMC_SEL_DES_CARD responce = %x\n", (int)response);\r
2216 #endif\r
2217 \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
2221     {\r
2222         return status;\r
2223     }\r
2224 \r
2225 #ifdef LOGGER\r
2226     alt_sdmmc_read_short_response(&response);\r
2227     dprintf("\nALT_SDMMC_SEND_STATUS responce = %x\n", (int)response);\r
2228 #endif\r
2229 \r
2230     return status;\r
2231 }\r
2232 \r
2233 //\r
2234 // Enumerated Card Stack\r
2235 //\r
2236 ALT_STATUS_CODE alt_sdmmc_card_identify(ALT_SDMMC_CARD_INFO_t *card_info)\r
2237 {\r
2238 #ifdef LOGGER\r
2239     dprintf("\nalt_sdmmc_card_identify\n");\r
2240 #endif\r
2241     ALT_STATUS_CODE status = ALT_E_SUCCESS;\r
2242     card_info->card_type = ALT_SDMMC_CARD_TYPE_NOTDETECT;\r
2243 \r
2244     //Enumerated Card Stack p.1\r
2245     alt_sdmmc_bus_width_set(ALT_SDMMC_BUS_WIDTH_1);\r
2246 \r
2247     if (status == ALT_E_SUCCESS)\r
2248     {\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
2252         {\r
2253             return status;\r
2254         }\r
2255     }\r
2256     if (status == ALT_E_SUCCESS)\r
2257     {\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
2260         {\r
2261             // If card is identified as SDHC then prepare it\r
2262             status = alt_sdmmc_card_enum_sd(card_info);\r
2263             return status;\r
2264         }\r
2265     }\r
2266     if (status != ALT_E_SUCCESS)\r
2267     {\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
2270         {\r
2271             // If card is identified as SD card then prepare it\r
2272             status = alt_sdmmc_card_enum_sd(card_info);\r
2273             return status;\r
2274         }\r
2275     }\r
2276 \r
2277     return status;\r
2278 }\r
2279 \r
2280 //\r
2281 // Send the a command and command argument to the card and optionally return the\r
2282 // command response.\r
2283 //\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
2286 {\r
2287     const ALT_SDMMC_CMD_CONFIG_t * cmd_cfg = NULL;\r
2288 \r
2289     bool found = false;\r
2290 \r
2291     if (command == ALT_SDMMC_CLK_INDEX)\r
2292     {\r
2293         cmd_cfg = &cmd_clock_cfg;\r
2294         found = true;\r
2295     }\r
2296 \r
2297     for (uint32_t counter = 0; counter < ARRAY_COUNT(cmd_default_cfg); counter++)\r
2298     {\r
2299         if (found == true)\r
2300         {\r
2301             break;\r
2302         }\r
2303         if (cmd_default_cfg[counter].cmd_index == command)\r
2304         {\r
2305             cmd_cfg = &cmd_default_cfg[counter];\r
2306             found = true;\r
2307         }\r
2308     }\r
2309 \r
2310     if (found == false)\r
2311     {\r
2312         return ALT_E_BAD_ARG;\r
2313     }\r
2314 \r
2315     if (cmd_cfg->wait_prvdata_complete)\r
2316     {\r
2317         uint32_t timeout = ALT_SDMMC_TMO_WAITER;\r
2318         while (alt_sdmmc_is_busy() && timeout--)\r
2319             ;\r
2320     }\r
2321 \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
2328 \r
2329     if (cmd_cfg->data_expected == true)\r
2330     {\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
2337         \r
2338         if (cmd_cfg->write_active == ALT_SDMMC_TMOD_WRITE)\r
2339         {\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
2342         }\r
2343         else\r
2344         {\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
2347         }\r
2348         \r
2349     }\r
2350     \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
2358 \r
2359     // Set command configuraions\r
2360     alt_sdmmc_cmd_set(command, cmd_cfg, false);\r
2361     // Send commnd\r
2362     alt_sdmmc_cmd_set(command, cmd_cfg, true);\r
2363 \r
2364 #ifdef LOGGER\r
2365     uint32_t state = (uint32_t)ALT_SDMMC_STAT_CMD_FSM_STATES_GET(alt_read_word(ALT_SDMMC_STAT_ADDR));\r
2366     \r
2367     uint32_t dma_state = (uint32_t)ALT_SDMMC_IDSTS_FSM_GET(alt_read_word(ALT_SDMMC_IDSTS_ADDR));\r
2368 \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
2371 #endif\r
2372 \r
2373     ALT_STATUS_CODE status = 0;\r
2374     if (cmd_cfg->update_clock_registers_only == true)\r
2375     {\r
2376         //Wait for complete clock update command\r
2377         status = alt_sdmmc_clock_waiter();\r
2378 #ifdef LOGGER\r
2379         if (status == ALT_E_TMO)\r
2380         {\r
2381             dprintf("\nTIMEOUT\n");\r
2382         }\r
2383 #endif\r
2384         return status;\r
2385     }\r
2386 \r
2387     //Wait for complete\r
2388     if (   alt_sdmmc_is_dma_enabled() == ALT_E_FALSE\r
2389         || cmd_cfg->data_expected == false)\r
2390     {\r
2391         status = alt_sdmmc_cmd_waiter();\r
2392     }\r
2393 #ifdef LOGGER\r
2394     if (status == ALT_E_TMO)\r
2395     {\r
2396         dprintf("\nTIMEOUT\n");\r
2397     }\r
2398 #endif\r
2399     if (status == ALT_E_SUCCESS)\r
2400     {\r
2401         alt_sdmmc_read_short_response(response);\r
2402     }\r
2403     \r
2404     return status;\r
2405 }\r
2406 \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
2411 {\r
2412     if (buf_len == 0)\r
2413     {\r
2414         return ALT_E_SUCCESS;\r
2415     }\r
2416 \r
2417     if (!alt_sdmmc_is_idle())\r
2418     {\r
2419         return ALT_E_ERROR;\r
2420     }\r
2421 \r
2422     uint16_t block_size = alt_sdmmc_block_size_get();\r
2423 \r
2424     if (   (start_addr % block_size != 0) \r
2425         || (buf_len    % block_size != 0))\r
2426     {\r
2427         return ALT_E_BAD_ARG;\r
2428     }\r
2429 \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
2435 \r
2436     // reset FIFO\r
2437     status = alt_sdmmc_fifo_reset();\r
2438     if (status != ALT_E_SUCCESS)\r
2439     {\r
2440         return status;\r
2441     }\r
2442     \r
2443     // reset DMA\r
2444     status = alt_sdmmc_dma_reset();\r
2445     if (status != ALT_E_SUCCESS)\r
2446     {\r
2447         return status;\r
2448     }\r
2449 \r
2450     alt_sdmmc_byte_count_set(byte_count);\r
2451     alt_sdmmc_card_rd_threshold_enable(0x80);\r
2452 \r
2453     uint32_t cmd_index = 0;\r
2454     if (buf_len == block_size)\r
2455     {\r
2456         cmd_index = (transfer_mode == ALT_SDMMC_TMOD_READ) \r
2457                                         ? ALT_SDMMC_READ_SINGLE_BLOCK \r
2458                                         : ALT_SDMMC_WRITE_BLOCK;\r
2459     }\r
2460     else\r
2461     {\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
2465     }\r
2466 \r
2467     if (alt_sdmmc_is_dma_enabled())\r
2468     {\r
2469         // Clean descriptor chain\r
2470         alt_sdmmc_desc_chain_clear();\r
2471         \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
2476     }\r
2477     if (status != ALT_E_SUCCESS)\r
2478     {\r
2479         return status;\r
2480     }\r
2481 \r
2482 #ifdef LOGGER\r
2483     dprintf("\nstart_addr = %d\n", (int)start_addr);\r
2484 #endif\r
2485 \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
2489     {\r
2490         return status;\r
2491     }\r
2492 \r
2493     //Send or read data\r
2494     if (alt_sdmmc_is_dma_enabled())\r
2495     {\r
2496         //Fill descriptors\r
2497         status = alt_sdmmc_dma_trans_helper(buffer, byte_count);\r
2498     }\r
2499     else\r
2500     {\r
2501         status = alt_sdmmc_transfer_helper(buffer, byte_count, transfer_mode);\r
2502     }\r
2503 \r
2504     if (status != ALT_E_SUCCESS)\r
2505     {\r
2506         return status;\r
2507     }\r
2508 \r
2509     //Wait for data transfer complete\r
2510     status = alt_sdmmc_data_done_waiter();\r
2511 \r
2512     return status;\r
2513 }\r
2514 \r
2515 //\r
2516 // This function performs SDMMC write.\r
2517 //\r
2518 ALT_STATUS_CODE alt_sdmmc_write(void *dest, void *src, const size_t size)\r
2519 {\r
2520     return alt_sdmmc_transfer((uint32_t)dest, src, size, ALT_SDMMC_TMOD_WRITE);\r
2521 }\r
2522 \r
2523 //\r
2524 // This function performs SDMMC read.\r
2525 //\r
2526 ALT_STATUS_CODE alt_sdmmc_read(void *dest, void *src, const size_t size)\r
2527 {\r
2528     return alt_sdmmc_transfer((uint32_t)src, dest, size, ALT_SDMMC_TMOD_READ);\r
2529 }\r