1 //*****************************************************************************
2 //
3 //! @file am_hal_card.c
4 //!
5 //! @brief Functions for interfacing with the card host.
6 //!
7 //! @addtogroup card_4p Card Functionality for SD/MMC/eMMC/SDIO
8 //! @ingroup apollo4p_hal
9 //! @{
10 //
11 //*****************************************************************************
12 
13 //*****************************************************************************
14 //
15 // Copyright (c) 2023, Ambiq Micro, Inc.
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are met:
20 //
21 // 1. Redistributions of source code must retain the above copyright notice,
22 // this list of conditions and the following disclaimer.
23 //
24 // 2. Redistributions in binary form must reproduce the above copyright
25 // notice, this list of conditions and the following disclaimer in the
26 // documentation and/or other materials provided with the distribution.
27 //
28 // 3. Neither the name of the copyright holder nor the names of its
29 // contributors may be used to endorse or promote products derived from this
30 // software without specific prior written permission.
31 //
32 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
36 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
37 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 // POSSIBILITY OF SUCH DAMAGE.
43 //
44 // This is part of revision stable-7da8bae71f of the AmbiqSuite Development Package.
45 //
46 //*****************************************************************************
47 
48 #include <stdint.h>
49 #include <stdbool.h>
50 #include <string.h>
51 
52 #include "am_mcu_apollo.h"
53 #include "am_util_stdio.h"
54 #include "am_util_debug.h"
55 #include "am_util_delay.h"
56 
57 //
58 // Private internal functions
59 //
60 
61 //
62 //! CMD0 - go idle
63 //
am_hal_sdmmc_cmd0_go_idle(am_hal_card_t * pCard)64 static inline uint32_t am_hal_sdmmc_cmd0_go_idle(am_hal_card_t *pCard)
65 {
66     am_hal_card_cmd_t cmd;
67     am_hal_card_host_t *pHost = pCard->pHost;
68 
69     memset(&cmd, 0, sizeof(cmd));
70     cmd.ui8Idx   = MMC_CMD_GO_IDLE_STATE;
71     cmd.ui32Arg  = 0x0;
72     cmd.ui32RespType = MMC_RSP_NONE;
73 
74     pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL);
75 
76     return cmd.eError;
77 }
78 
79 //
80 //! CMD1 - send operation condition
81 //
am_hal_sdmmc_cmd1_send_op_cond(am_hal_card_t * pCard)82 static inline uint32_t am_hal_sdmmc_cmd1_send_op_cond(am_hal_card_t *pCard)
83 {
84     uint32_t ui32CardOCR = 0;
85     uint8_t ui8Tries = 100;
86 
87     am_hal_card_cmd_t cmd;
88     am_hal_card_host_t *pHost = pCard->pHost;
89 
90     memset(&cmd, 0, sizeof(cmd));
91     cmd.ui8Idx = MMC_CMD_SEND_OP_COND;
92     cmd.ui32Arg = SECTOR_MODE << 28;
93     cmd.ui32RespType = MMC_RSP_R3;
94 
95     do
96     {
97         pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL);
98 
99         if ( cmd.eError == AM_HAL_CMD_ERR_NONE )
100         {
101             ui32CardOCR = cmd.ui32Resp[0];
102             cmd.ui32Arg |= ui32CardOCR;
103         }
104 
105         if ( ui32CardOCR & CARD_RDY_BIT )
106         {
107             pCard->ui32OCR = ui32CardOCR;
108             break;
109         }
110 
111         am_util_delay_ms(10);
112     } while (--ui8Tries != 0);
113 
114     return ui8Tries == 0x0 ? AM_HAL_CMD_ERR_TIMEOUT : cmd.eError;
115 }
116 
117 //
118 //! CMD2 - send card identification
119 //
am_hal_sdmmc_cmd2_send_cid(am_hal_card_t * pCard)120 static inline uint32_t am_hal_sdmmc_cmd2_send_cid(am_hal_card_t *pCard)
121 {
122     am_hal_card_cmd_t cmd;
123     am_hal_card_host_t *pHost = pCard->pHost;
124 
125     memset(&cmd, 0, sizeof(cmd));
126     cmd.ui8Idx   = MMC_CMD_ALL_SEND_CID;
127     cmd.ui32Arg  = 0x0;
128     cmd.ui32RespType = MMC_RSP_R2;
129 
130     pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL);
131 
132     if ( cmd.eError == AM_HAL_CMD_ERR_NONE )
133     {
134         memcpy((void *)pCard->ui32CID, (void *)&cmd.ui32Resp[0], 16);
135         pCard->bCidValid = 1;
136     }
137 
138     return cmd.eError;
139 }
140 
141 //
142 //! CMD3 - set the relative card address
143 //
am_hal_sdmmc_cmd3_set_rca(am_hal_card_t * pCard,uint32_t ui32RCA)144 static inline uint32_t am_hal_sdmmc_cmd3_set_rca(am_hal_card_t *pCard, uint32_t ui32RCA)
145 {
146     am_hal_card_cmd_t cmd;
147     am_hal_card_host_t *pHost = pCard->pHost;
148 
149     memset(&cmd, 0, sizeof(cmd));
150     cmd.ui8Idx   = MMC_CMD_SET_RELATIVE_ADDR;
151     cmd.ui32Arg  = ui32RCA << 16;
152 
153     if ( (pCard->eType == AM_HAL_CARD_TYPE_EMMC) || (pCard->eType == AM_HAL_CARD_TYPE_MMC) )
154     {
155         cmd.ui32RespType = MMC_RSP_R1;
156     }
157     else
158     {
159         cmd.ui32RespType = MMC_RSP_R6;
160     }
161 
162     pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL);
163 
164     if ( cmd.eError == AM_HAL_CMD_ERR_NONE )
165     {
166         if ( (pCard->eType == AM_HAL_CARD_TYPE_EMMC) || (pCard->eType == AM_HAL_CARD_TYPE_MMC) )
167         {
168             pCard->ui32RCA = ui32RCA;
169         }
170         else
171         {
172             pCard->ui32RCA = cmd.ui32Resp[0] >> 16;
173             AM_HAL_CARD_DEBUG("Get SD card responds with new RCA:0x%x\n", pCard->ui32RCA);
174         }
175     }
176 
177     return cmd.eError;
178 }
179 
180 //
181 //! CMD5 - Sleep/Awake
182 //
am_hal_sdmmc_cmd5(am_hal_card_t * pCard,bool sleep)183 static uint32_t am_hal_sdmmc_cmd5(am_hal_card_t *pCard, bool sleep)
184 {
185     uint32_t ui32Status;
186     am_hal_card_cmd_t cmd;
187     am_hal_card_host_t *pHost = pCard->pHost;
188 
189     memset(&cmd, 0, sizeof(cmd));
190     cmd.ui8Idx   = MMC_CMD_SLEEP_AWAKE;
191     cmd.ui32Arg  = pCard->ui32RCA << 16 | sleep << 15;
192     cmd.ui32RespType = MMC_RSP_R1b;
193     cmd.bCheckBusyCmd = true;
194 
195     if ( (ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL)) != AM_HAL_STATUS_SUCCESS )
196     {
197         return ui32Status;
198     }
199 
200     if ( cmd.eError == AM_HAL_CMD_ERR_NONE )
201     {
202         if ( sleep == true )
203         {
204             pCard->eState = AM_HAL_CARD_STATE_SLP;
205         }
206         else
207         {
208             pCard->eState = AM_HAL_CARD_STATE_STDY;
209         }
210     }
211 
212     if ((ui32Status = pHost->ops->card_busy(pHost->pHandle, 20)) != AM_HAL_STATUS_SUCCESS)
213     {
214         return ui32Status;
215     }
216 
217     return AM_HAL_STATUS_SUCCESS;
218 }
219 
220 //
221 //! CMD7 - select the card
222 //
223 
am_hal_sdmmc_cmd7_card_select(am_hal_card_t * pCard)224 static uint32_t am_hal_sdmmc_cmd7_card_select(am_hal_card_t *pCard)
225 {
226     am_hal_card_cmd_t cmd;
227     am_hal_card_host_t *pHost = pCard->pHost;
228 
229     memset(&cmd, 0, sizeof(cmd));
230     cmd.ui8Idx   = MMC_CMD_SELECT_CARD;
231     cmd.ui32Arg  = pCard->ui32RCA << 16;
232 
233     //
234     // RCA of zero is not valid for a card select, so this
235     // is a card deselect which requires no response
236     //
237     if ( pCard->ui32RCA == 0x0 )
238     {
239         cmd.ui32RespType = MMC_RSP_NONE;
240     }
241     else
242     {
243         cmd.ui32RespType = MMC_RSP_R1;
244     }
245 
246     pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL);
247 
248     if ( cmd.eError == AM_HAL_CMD_ERR_NONE )
249     {
250         //
251         // For a card deselect, the state is stand-by-state
252         //
253         if ( pCard->ui32RCA == 0x0 )
254         {
255             pCard->eState = AM_HAL_CARD_STATE_STDY;
256         }
257         //
258         // for a card select, the state is the transfer state
259         //
260         else
261         {
262             pCard->eState = AM_HAL_CARD_STATE_TRANS;
263         }
264     }
265 
266     return cmd.eError;
267 }
268 
269 //
270 //! CMD7 - select/deselect the card
271 //
am_hal_sdmmc_cmd7_card_deselect(am_hal_card_t * pCard)272 static uint32_t am_hal_sdmmc_cmd7_card_deselect(am_hal_card_t *pCard)
273 {
274     uint32_t ui32RCA = pCard->ui32RCA;
275     uint32_t ui32Status = AM_HAL_STATUS_SUCCESS;
276 
277     pCard->ui32RCA = 0;
278     if ( AM_HAL_CMD_ERR_NONE != am_hal_sdmmc_cmd7_card_select(pCard) )
279     {
280         AM_HAL_CARD_DEBUG("sleep - am_hal_sdmmc_cmd7_card_select Failed\n");
281         ui32Status = AM_HAL_STATUS_FAIL;
282     }
283     pCard->ui32RCA = ui32RCA;
284 
285     return ui32Status;
286 }
287 
288 //
289 //! CMD8 - get the 512 bytes ext csd
290 //
am_hal_sdmmc_cmd8_send_ext_csd(am_hal_card_t * pCard)291 static uint32_t am_hal_sdmmc_cmd8_send_ext_csd(am_hal_card_t *pCard)
292 {
293     am_hal_card_cmd_t cmd;
294     am_hal_card_cmd_data_t cmd_data;
295     am_hal_card_host_t *pHost = pCard->pHost;
296 
297     memset(&cmd, 0x0, sizeof(cmd));
298     memset(&cmd_data, 0x0, sizeof(cmd_data));
299 
300     cmd.ui8Idx   = MMC_CMD_SEND_EXT_CSD;
301     cmd.ui32Arg  = pCard->ui32RCA << 16;
302     cmd.ui32RespType = MMC_RSP_R1;
303 
304     cmd_data.ui8IovCnt = 0;
305     cmd_data.pui8Buf = (uint8_t *)pCard->ui32ExtCSD;
306     cmd_data.ui32BlkCnt = 1;
307     cmd_data.ui32BlkSize = 512;
308     cmd_data.dir = AM_HAL_DATA_DIR_READ;
309 
310     pHost->ops->execute_cmd(pHost->pHandle, &cmd, &cmd_data);
311 
312     if ( cmd.eError == AM_HAL_CMD_ERR_NONE )
313     {
314         pCard->bExtCsdValid = 1;
315     }
316 
317     return cmd.eError;
318 }
319 
320 //
321 //! CMD9 - get the CSD
322 //
am_hal_sdmmc_cmd9_send_csd(am_hal_card_t * pCard)323 static inline uint32_t am_hal_sdmmc_cmd9_send_csd(am_hal_card_t *pCard)
324 {
325     am_hal_card_cmd_t cmd;
326     am_hal_card_host_t *pHost = pCard->pHost;
327 
328     memset(&cmd, 0, sizeof(cmd));
329     cmd.ui8Idx   = MMC_CMD_SEND_CSD;
330     cmd.ui32Arg  = pCard->ui32RCA << 16;
331     cmd.ui32RespType = MMC_RSP_R2;
332 
333     pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL);
334 
335     if ( cmd.eError == AM_HAL_CMD_ERR_NONE )
336     {
337         memcpy((void *)pCard->ui32CSD, (void *)&cmd.ui32Resp[0], 16);
338         pCard->bCsdValid = 1;
339     }
340 
341     return cmd.eError;
342 }
343 
344 //
345 //! CMD5 for SDIO card - send operation condition
346 //
am_hal_sdio_cmd5_io_send_op_cond(am_hal_card_t * pCard,uint32_t ui32OCR)347 static inline uint32_t am_hal_sdio_cmd5_io_send_op_cond(am_hal_card_t *pCard, uint32_t ui32OCR)
348 {
349     am_hal_card_cmd_t cmd;
350     am_hal_card_host_t *pHost = pCard->pHost;
351     uint32_t ui32CardOCR = 0;
352     uint8_t ui8Tries = 100;
353 
354     memset(&cmd, 0, sizeof(cmd));
355     cmd.ui8Idx = SDIO_CMD_IO_SEND_OP_COND;
356     cmd.ui32Arg = ui32OCR & 0x01FFFF00;
357     cmd.ui32RespType = MMC_RSP_R4;
358 
359     do
360     {
361         pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL);
362 
363         if ( cmd.eError == AM_HAL_CMD_ERR_NONE )
364         {
365             ui32CardOCR = cmd.ui32Resp[0];
366         }
367 
368         if ( ui32CardOCR & CARD_RDY_BIT )
369         {
370             pCard->ui32OCR = ui32CardOCR;
371             pCard->ui32FuncNum = (ui32CardOCR >> 28) & 0x7;
372             break;
373         }
374 
375         am_util_delay_ms(10);
376     } while (--ui8Tries != 0);
377 
378     return ui8Tries == 0x0 ? AM_HAL_CMD_ERR_TIMEOUT : cmd.eError;
379 }
380 
381 //
382 //! CMD8 for SD card and SDIO card - send interface condition
383 //
am_hal_sdio_cmd8_send_if_cond(am_hal_card_t * pCard,uint32_t ui32OCR)384 static inline uint32_t am_hal_sdio_cmd8_send_if_cond(am_hal_card_t *pCard, uint32_t ui32OCR)
385 {
386     am_hal_card_cmd_t cmd;
387     am_hal_card_host_t *pHost = pCard->pHost;
388 
389     memset(&cmd, 0, sizeof(cmd));
390     cmd.ui8Idx = SDIO_CMD_SEND_IF_COND;
391     cmd.ui32RespType = MMC_RSP_R7;
392     cmd.ui32Arg = ui32OCR;
393 
394     pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL);
395 
396     if ( cmd.eError == AM_HAL_CMD_ERR_NONE )
397     {
398         if ( (cmd.ui32Resp[0] & 0xFF) != 0xAA )
399         {
400             AM_HAL_CARD_DEBUG("CMD8 response ERROR!\n");
401             return AM_HAL_CMD_ERR_INVALID_RESPONSE;
402         }
403 
404         if ( (cmd.ui32Resp[0] & 0x0F00) == SD_CARD_2P7_3P6_VOLTAGE_SUPPLY )
405         {
406             AM_HAL_CARD_DEBUG("Card support 2.7 ~ 3.6 V\n");
407         }
408         else
409         {
410             AM_HAL_CARD_DEBUG("Card voltage accepted result:0x%x\n", cmd.ui32Resp[0]);
411         }
412     }
413     else if ( cmd.eError == AM_HAL_CMD_ERR_TIMEOUT )
414     {
415         AM_HAL_CARD_DEBUG("Card CMD8 no resp, voltage mismatch or Ver1.X SD or not SD\r\n");
416     }
417     else if ( cmd.eError == AM_HAL_CMD_ERR_CRC )
418     {
419         AM_HAL_CARD_DEBUG("Card CMD8 crc err\r\n");
420     }
421 
422     return cmd.eError;
423 }
424 
425 //
426 //! CMD52 for SDIO card -  read/write card register and CIS table
427 //
am_hal_sdio_cmd52_io_rw_direct(am_hal_card_t * pCard,uint32_t ui32Func,uint32_t ui32Addr,uint8_t ui8WrData,uint8_t * ui8RdData,bool bRead)428 static inline uint32_t am_hal_sdio_cmd52_io_rw_direct(am_hal_card_t *pCard,
429                                                       uint32_t ui32Func,
430                                                       uint32_t ui32Addr,
431                                                       uint8_t ui8WrData,
432                                                       uint8_t *ui8RdData,
433                                                       bool bRead)
434 {
435     am_hal_card_cmd_t cmd;
436     am_hal_card_host_t *pHost = pCard->pHost;
437 
438     memset(&cmd, 0, sizeof(cmd));
439     cmd.ui8Idx = SDIO_CMD_IO_RW_DIRECT;
440     cmd.ui32RespType = MMC_RSP_R5;
441 
442     if ( bRead )
443     {
444         cmd.ui32Arg = (ui32Func << 28) | (ui32Addr << 9);
445     }
446     else
447     {
448         cmd.ui32Arg = 0x80000000 | (ui32Func << 28) | (ui32Addr << 9) | ui8WrData;
449     }
450 
451     pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL);
452 
453     if ( cmd.eError != AM_HAL_CMD_ERR_NONE )
454     {
455         AM_HAL_CARD_DEBUG("SDIO card CMD52 ERROR!\n");
456     }
457 
458     if ( ui8RdData )
459     {
460         *ui8RdData = cmd.ui32Resp[0] & 0xFF;
461     }
462 
463     return cmd.eError;
464 }
465 
466 //
467 //! CMD53 for SDIO card - read/write data from/to card's SQU memory
468 //
am_hal_sdio_cmd53_io_rw_extended(am_hal_card_t * pCard,uint32_t ui32Func,uint32_t ui32Addr,uint8_t * pui8Buf,uint32_t ui32BlkCnt,uint32_t ui32BlkSize,bool bIncrAddr,bool bRead,bool bASync)469 static inline uint32_t am_hal_sdio_cmd53_io_rw_extended(am_hal_card_t *pCard,
470                                                         uint32_t ui32Func,
471                                                         uint32_t ui32Addr,
472                                                         uint8_t *pui8Buf,
473                                                         uint32_t ui32BlkCnt,
474                                                         uint32_t ui32BlkSize,
475                                                         bool bIncrAddr,
476                                                         bool bRead,
477                                                         bool bASync)
478 {
479     uint32_t ui32Status;
480 
481     am_hal_card_cmd_t cmd;
482     am_hal_card_cmd_data_t cmd_data;
483     am_hal_card_host_t *pHost = pCard->pHost;
484 
485     memset(&cmd, 0, sizeof(cmd));
486     cmd.bASync = bASync;
487     cmd.ui8Idx = SDIO_CMD_IO_RW_EXTENDED;
488     cmd.ui32RespType = MMC_RSP_R5;
489     cmd.ui32Arg = (ui32Func << 28) | (ui32Addr << 9);
490     cmd.ui32Arg |= bRead ? 0x0 : 0x80000000;
491     cmd.ui32Arg |= bIncrAddr ? 0x04000000 : 0x0;
492 
493     if ( ui32BlkCnt == 0 && ui32BlkSize <= 512 )
494     {
495         cmd.ui32Arg |= (ui32BlkSize == 512) ? 0 : ui32BlkSize;
496     }
497     else
498     {
499         cmd.ui32Arg |= 0x08000000 | ui32BlkCnt;
500     }
501 
502     memset((void *)&cmd_data, 0x0, sizeof(cmd_data));
503     cmd_data.ui8IovCnt = 0;
504     cmd_data.pui8Buf = pui8Buf;
505     cmd_data.ui32BlkCnt = ui32BlkCnt;
506     cmd_data.ui32BlkSize = ui32BlkSize;
507     cmd_data.dir = bRead ? AM_HAL_DATA_DIR_READ : AM_HAL_DATA_DIR_WRITE;
508 
509     if ( cmd.bASync )
510     {
511         pHost->AsyncCmd = cmd;
512         pHost->AsyncCmdData = cmd_data;
513     }
514 
515     ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, &cmd_data);
516 
517     return ui32Status;
518 }
519 
520 //
521 //! CMD11 - Switch SD Card signal voltage to 1.8 V
522 //
am_hal_sdcard_cmd11_voltage_switch(am_hal_card_t * pCard)523 static inline uint32_t am_hal_sdcard_cmd11_voltage_switch(am_hal_card_t *pCard)
524 {
525     am_hal_card_cmd_t cmd;
526     am_hal_card_host_t *pHost = pCard->pHost;
527 
528     memset(&cmd, 0, sizeof(cmd));
529     cmd.ui8Idx   = SDIO_CMD_VOLTAGE_SWITCH;
530     cmd.ui32Arg  = 0;
531     cmd.ui32RespType = MMC_RSP_R1;
532 
533     pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL);
534 
535     return cmd.eError;
536 }
537 
538 //
539 //! ACMD6 for SD card - set bus width
540 //
am_hal_sdcard_acmd6_set_bus_width(am_hal_card_t * pCard,am_hal_host_bus_width_e eBusWidth)541 static inline uint32_t am_hal_sdcard_acmd6_set_bus_width(am_hal_card_t *pCard, am_hal_host_bus_width_e eBusWidth)
542 {
543     am_hal_card_cmd_t cmd;
544     am_hal_card_host_t *pHost = pCard->pHost;
545 
546     memset(&cmd, 0, sizeof(cmd));
547     cmd.ui8Idx = MMC_CMD_APP_CMD;
548     cmd.ui32Arg = pCard->ui32RCA << 16;
549     cmd.ui32RespType = MMC_RSP_R1;
550 
551     pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL);
552 
553     if ( cmd.eError != AM_HAL_CMD_ERR_NONE )
554     {
555         AM_HAL_CARD_DEBUG("SD card CMD55 response ERROR!\n");
556         return cmd.eError;
557     }
558 
559     memset(&cmd, 0, sizeof(cmd));
560     cmd.ui8Idx = MMC_CMD_SWITCH;
561 
562     if ( eBusWidth == AM_HAL_HOST_BUS_WIDTH_4 )
563     {
564         cmd.ui32Arg = 2;
565     }
566     else
567     {
568         cmd.ui32Arg = 0;
569     }
570 
571     cmd.ui32RespType = MMC_RSP_R1;
572 
573     pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL);
574 
575     if ( cmd.eError != AM_HAL_CMD_ERR_NONE )
576     {
577         if ( cmd.eError != AM_HAL_CMD_ERR_NONE && cmd.eError != AM_HAL_CMD_ERR_CRC )
578         {
579             AM_HAL_CARD_DEBUG("SD card send CMD6 err:%d\r\n", cmd.eError);
580             return cmd.eError;
581         }
582     }
583 
584     return cmd.eError;
585 }
586 
587 //
588 //! CMD41 for SD card - send host capacity support information
589 //
am_hal_sdcard_acmd41_send_op_cond(am_hal_card_t * pCard,uint32_t ui32Ocr,uint32_t * ui32Resp)590 static inline uint32_t am_hal_sdcard_acmd41_send_op_cond(am_hal_card_t *pCard, uint32_t ui32Ocr, uint32_t *ui32Resp)
591 {
592     am_hal_card_cmd_t cmd;
593     am_hal_card_host_t *pHost = pCard->pHost;
594 
595     memset(&cmd, 0, sizeof(cmd));
596     cmd.ui8Idx = MMC_CMD_APP_CMD;
597     cmd.ui32Arg = 0;
598     cmd.ui32RespType = MMC_RSP_R1;
599 
600     pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL);
601 
602     if ( cmd.eError != AM_HAL_CMD_ERR_NONE )
603     {
604         AM_HAL_CARD_DEBUG("SD card CMD55 response ERROR!\n");
605         return cmd.eError;
606     }
607 
608     memset(&cmd, 0, sizeof(cmd));
609     cmd.ui8Idx = SD_CMD_SEND_OP_COND;
610     cmd.ui32Arg = ui32Ocr;
611     cmd.ui32RespType = MMC_RSP_R3;
612 
613     pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL);
614 
615     if ( cmd.eError != AM_HAL_CMD_ERR_NONE )
616     {
617         AM_HAL_CARD_DEBUG("SD card send CMD41 err:%d\r\n", cmd.eError);
618         return cmd.eError;
619     }
620 
621     *ui32Resp = cmd.ui32Resp[0];
622 
623     return cmd.eError;
624 }
625 
626 //
627 //! Read SDIO card common control registers(CCCR)
628 //
629 static uint32_t
am_hal_sdio_card_read_cccr(am_hal_card_t * pCard)630 am_hal_sdio_card_read_cccr(am_hal_card_t *pCard)
631 {
632     uint32_t ui32Status;
633     uint32_t ui32Func = 0;
634     uint8_t  ui8CccrReg;
635 
636 #ifndef AM_HAL_DISABLE_API_VALIDATION
637 
638     if ( !pCard || !pCard->pHost )
639     {
640         return AM_HAL_STATUS_INVALID_ARG;
641     }
642 
643 #endif // AM_HAL_DISABLE_API_VALIDATION
644 
645     ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, ui32Func, SDIO_CCCR_CCCR_REV, 0, &ui8CccrReg, true);
646     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
647     {
648         AM_HAL_CARD_DEBUG("Fail to read SDIO CCCR revision register \n");
649         return ui32Status;
650     }
651     pCard->cccr.ui8CccrRev = ui8CccrReg & 0x0F;
652 
653     ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, ui32Func, SDIO_CCCR_SD_REV, 0, &ui8CccrReg, true);
654     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
655     {
656         AM_HAL_CARD_DEBUG("Fail to read SD Spec revision register \n");
657         return ui32Status;
658     }
659     pCard->cccr.ui8SdRev = ui8CccrReg & 0x0F;
660 
661     ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, ui32Func, SDIO_CCCR_CARD_CAPAB, 0, &ui8CccrReg, true);
662     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
663     {
664         AM_HAL_CARD_DEBUG("Fail to read SDIO CCCR card capability register \n");
665         return ui32Status;
666     }
667     if ( ui8CccrReg & SDIO_CCCR_CAP_SMB )
668     {
669         pCard->cccr.bMultiBlock = 1;
670     }
671     if ( ui8CccrReg & SDIO_CCCR_CAP_LSC )
672     {
673         pCard->cccr.bFullSpeed = 1;
674     }
675     if ( ui8CccrReg & SDIO_CCCR_CAP_4BLS )
676     {
677         pCard->cccr.bWideBus = 1;
678     }
679 
680     ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, ui32Func, SDIO_CCCR_PWR_CNTRL, 0, &ui8CccrReg, true);
681     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
682     {
683         AM_HAL_CARD_DEBUG("Fail to read SDIO CCCR power control register \n");
684         return ui32Status;
685     }
686     if ( ui8CccrReg & SDIO_POWER_SMPC )
687     {
688         pCard->cccr.bHighPower = 1;
689     }
690 
691     ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, ui32Func, SDIO_CCCR_BUS_SPEED_SELECT, 0, &ui8CccrReg, true);
692     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
693     {
694         AM_HAL_CARD_DEBUG("Fail to read SDIO CCCR bus speed select register \n");
695         return ui32Status;
696     }
697     if ( ui8CccrReg & SDIO_SPEED_SHS )
698     {
699         pCard->cccr.bHighSpeed = 1;
700     }
701 
702     AM_HAL_CARD_DEBUG("SDIO Card cccr.ui8CccrRev  = 0x%x \n", pCard->cccr.ui8CccrRev);
703     AM_HAL_CARD_DEBUG("SDIO Card cccr.ui8SdRev    = 0x%x \n", pCard->cccr.ui8SdRev);
704     AM_HAL_CARD_DEBUG("SDIO Card cccr.bMultiBlock = 0x%x \n", pCard->cccr.bMultiBlock);
705     AM_HAL_CARD_DEBUG("SDIO Card cccr.bFullSpeed  = 0x%x \n", pCard->cccr.bFullSpeed);
706     AM_HAL_CARD_DEBUG("SDIO Card cccr.bWideBus    = 0x%x \n", pCard->cccr.bWideBus);
707     AM_HAL_CARD_DEBUG("SDIO Card cccr.bHighPower  = 0x%x \n", pCard->cccr.bHighPower);
708     AM_HAL_CARD_DEBUG("SDIO Card cccr.bHighSpeed  = 0x%x \n", pCard->cccr.bHighSpeed);
709 
710     return AM_HAL_STATUS_SUCCESS;
711 }
712 
713 //
714 //! Read SDIO card information structure (CIS)
715 //
716 static uint32_t
am_hal_sdio_card_read_cis(am_hal_card_t * pCard)717 am_hal_sdio_card_read_cis(am_hal_card_t *pCard)
718 {
719     uint32_t ui32Status;
720     uint32_t ui32Func = 0;
721     uint32_t ui32CisAddr = 0;
722     uint32_t ui32LoopCnt = 512;
723     uint8_t  ui8RdData[4];
724     uint8_t  ui8TupleCode, ui8TupleLink;
725 
726 #ifndef AM_HAL_DISABLE_API_VALIDATION
727 
728     if ( !pCard || !pCard->pHost )
729     {
730         return AM_HAL_STATUS_INVALID_ARG;
731     }
732 
733 #endif // AM_HAL_DISABLE_API_VALIDATION
734 
735     for ( uint8_t i = 0; i < 3; i++ )
736     {
737         ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, ui32Func, SDIO_CCCR_CIS_PTR1 + i, 0, &ui8RdData[i], true);
738         if ( ui32Status != AM_HAL_STATUS_SUCCESS )
739         {
740             AM_HAL_CARD_DEBUG("Fail to read SDIO common CIS pointer register \n");
741             return ui32Status;
742         }
743         ui32CisAddr |= ui8RdData[i] << ( i * 8);
744     }
745 
746     do
747     {
748         ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, ui32Func, ui32CisAddr, 0, &ui8TupleCode, true);
749         if ( ui32Status != AM_HAL_STATUS_SUCCESS )
750         {
751             AM_HAL_CARD_DEBUG("Fail to read SDIO tuple code \n");
752             return ui32Status;
753         }
754 
755         if ( (ui8TupleCode == SDIO_CIS_TPL_NULL) || (ui8TupleCode == SDIO_CIS_TPL_END) )
756         {
757             AM_HAL_CARD_DEBUG("CIS tuple code is NULL or END \n\n");
758             break;
759         }
760 
761         ui32CisAddr += 1;
762         ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, ui32Func, ui32CisAddr, 0, &ui8TupleLink, true);
763         if ( ui32Status != AM_HAL_STATUS_SUCCESS )
764         {
765             AM_HAL_CARD_DEBUG("Fail to read SDIO tuple link register \n");
766             return ui32Status;
767         }
768 
769         if ( ui8TupleCode == SDIO_CIS_TPL_MANFID )
770         {
771             for ( uint8_t i = 0; i < 4; i++ )
772             {
773                 ui32CisAddr += 1;
774                 ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, ui32Func, ui32CisAddr, 0, &ui8RdData[i], true);
775                 if ( ui32Status != AM_HAL_STATUS_SUCCESS )
776                 {
777                     AM_HAL_CARD_DEBUG("Fail to read SDIO tuple MID register \n");
778                     return ui32Status;
779                 }
780             }
781             pCard->cis.ui32Vendor = (ui8RdData[1] << 8) | ui8RdData[0];
782             pCard->cis.ui32Device = (ui8RdData[3] << 8) | ui8RdData[2];
783 
784         }
785         else if ( ui8TupleCode == SDIO_CIS_TPL_FUNCE )
786         {
787             ui32CisAddr += 1; // Skip TPLFE_TYPE register address
788             for ( uint8_t i = 0; i < 3; i++ )
789             {
790                 ui32CisAddr += 1;
791                 ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, ui32Func, ui32CisAddr, 0, &ui8RdData[i], true);
792                 if ( ui32Status != AM_HAL_STATUS_SUCCESS )
793                 {
794                     AM_HAL_CARD_DEBUG("Fail to read SDIO tuple FUNCE register \n");
795                     return ui32Status;
796                 }
797             }
798             pCard->cis.ui32BlkSize = (ui8RdData[1] << 8) | ui8RdData[0];
799             pCard->cis.ui32MaxSpeed = ui8RdData[2];
800         }
801         ui32CisAddr += (ui8TupleLink + 1);
802     } while (--ui32LoopCnt != 0 );
803 
804     AM_HAL_CARD_DEBUG("SDIO Card cis.ui32Vendor   = 0x%x \n", pCard->cis.ui32Vendor);
805     AM_HAL_CARD_DEBUG("SDIO Card cis.ui32Device   = 0x%x \n", pCard->cis.ui32Device);
806     AM_HAL_CARD_DEBUG("SDIO Card cis.ui32BlkSize  = 0x%x \n", pCard->cis.ui32BlkSize);
807     AM_HAL_CARD_DEBUG("SDIO Card cis.ui32MaxSpeed = 0x%x \n", pCard->cis.ui32MaxSpeed);
808 
809     return ui32LoopCnt == 0 ? AM_HAL_STATUS_FAIL : AM_HAL_STATUS_SUCCESS;
810 }
811 
812 //
813 //! Set SDIO card bus width
814 //
815 static uint32_t
am_hal_sdio_card_set_bus_width(am_hal_card_t * pCard,am_hal_host_bus_width_e eBusWidth)816 am_hal_sdio_card_set_bus_width(am_hal_card_t *pCard, am_hal_host_bus_width_e eBusWidth)
817 {
818     uint32_t ui32Status;
819     uint32_t ui32Func = 0;
820     am_hal_card_host_t *pHost = pCard->pHost;
821 
822 #ifndef AM_HAL_DISABLE_API_VALIDATION
823 
824     if ( !pCard || !pCard->pHost )
825     {
826         return AM_HAL_STATUS_INVALID_ARG;
827     }
828 
829 #endif // AM_HAL_DISABLE_API_VALIDATION
830 
831     switch ( eBusWidth )
832     {
833         case AM_HAL_HOST_BUS_WIDTH_1:
834             ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, ui32Func, SDIO_CCCR_BUS_CNTRL, 0, NULL, false);
835             if ( ui32Status != AM_HAL_STATUS_SUCCESS )
836             {
837                 AM_HAL_CARD_DEBUG("Fail to set SDIO card into 1-bit mode. ERROR!\n");
838                 return ui32Status;
839             }
840             else
841             {
842                 AM_HAL_CARD_DEBUG("SDIO card is set into 1-bit mode\n");
843             }
844             break;
845 
846         case AM_HAL_HOST_BUS_WIDTH_4:
847             ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, ui32Func, SDIO_CCCR_BUS_CNTRL, 2, NULL, false);
848             if ( ui32Status != AM_HAL_STATUS_SUCCESS )
849             {
850                 AM_HAL_CARD_DEBUG("Fail to set SDIO card into 4-bit mode. ERROR!\n");
851                 return ui32Status;
852             }
853             else
854             {
855                 AM_HAL_CARD_DEBUG("SDIO card is set into 4-bit mode\n");
856             }
857             break;
858 
859         case AM_HAL_HOST_BUS_WIDTH_8:
860             AM_HAL_CARD_DEBUG("8 bit width is not supported for SDIO card\n");
861             return AM_HAL_STATUS_INVALID_OPERATION;
862 
863         default:
864             break;
865     }
866 
867     if ( pHost->ops->set_bus_width(pHost->pHandle, eBusWidth) != AM_HAL_STATUS_SUCCESS )
868     {
869         return AM_HAL_STATUS_FAIL;
870     }
871 
872     return AM_HAL_STATUS_SUCCESS;
873 }
874 
875 //
876 //! Set SDIO card clock speed
877 //
878 static uint32_t
am_hal_sdio_card_set_speed(am_hal_card_t * pCard,uint32_t ui32Clock)879 am_hal_sdio_card_set_speed(am_hal_card_t *pCard, uint32_t ui32Clock)
880 {
881     uint32_t ui32Status = 0;
882     uint32_t ui32Func = 0;
883     uint8_t  ui8SpeedReg = 0;
884 
885     am_hal_card_host_t *pHost = pCard->pHost;
886 
887 #ifndef AM_HAL_DISABLE_API_VALIDATION
888 
889     if ( !pCard || !pCard->pHost )
890     {
891         return AM_HAL_STATUS_INVALID_ARG;
892     }
893 
894 #endif // AM_HAL_DISABLE_API_VALIDATION
895 
896     if ( ui32Clock > SDIO_CARD_MAX_SPEED_LIMIT)
897     {
898         AM_HAL_CARD_DEBUG("Clock speed setting is out of range\n");
899         return AM_HAL_STATUS_OUT_OF_RANGE;
900     }
901     else if (ui32Clock > SDIO_CARD_FULL_SPEED_LIMIT)
902     {
903         ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, ui32Func, SDIO_CCCR_BUS_SPEED_SELECT, 0, &ui8SpeedReg, true);
904         if ( ui32Status != AM_HAL_STATUS_SUCCESS )
905         {
906             AM_HAL_CARD_DEBUG("Fail to read SDIO card bus speed register\n");
907             return ui32Status;
908         }
909 
910         if ( ui8SpeedReg & SDIO_HIGHSPEED_SUPPORT )
911         {
912             //
913             // Set SDIO card into High Speed mode. Write 1 to SDIO_BUS_SPEED_SELECT register.
914             //
915             ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, ui32Func, SDIO_CCCR_BUS_SPEED_SELECT, 1, NULL, false);
916             if ( ui32Status != AM_HAL_STATUS_SUCCESS )
917             {
918                 AM_HAL_CARD_DEBUG("Fail to set SDIO card into high speed mode\n");
919                 return ui32Status;
920             }
921 
922             ui8SpeedReg = 0;
923             ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, ui32Func, SDIO_CCCR_BUS_SPEED_SELECT, 0, &ui8SpeedReg, true);
924             if ( ui32Status != AM_HAL_STATUS_SUCCESS )
925             {
926                 AM_HAL_CARD_DEBUG("Fail to read SDIO card bus speed register\n");
927                 return ui32Status;
928             }
929 
930             if ( ui8SpeedReg & SDIO_HIGHSPEED_ENABLED )
931             {
932                 AM_HAL_CARD_DEBUG("SDIO card is set into high speed mode\n");
933             }
934             else
935             {
936                 AM_HAL_CARD_DEBUG("SDIO card high speed mode check failed\n");
937                 return AM_HAL_STATUS_FAIL;
938             }
939         }
940         else
941         {
942                 AM_HAL_CARD_DEBUG("This SDIO card does not support high speed mode\n");
943                 return AM_HAL_STATUS_INVALID_OPERATION;
944         }
945     }
946     else
947     {
948         //
949         // Set SDIO card into Full Speed mode. Write 0 to SDIO_BUS_SPEED_SELECT register.
950         //
951         ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, ui32Func, SDIO_CCCR_BUS_SPEED_SELECT, 0, NULL, false);
952         if ( ui32Status != AM_HAL_STATUS_SUCCESS )
953         {
954             AM_HAL_CARD_DEBUG("Fail to set SDIO card into full speed mode\n");
955             return ui32Status;
956         }
957 
958         ui8SpeedReg = 0;
959         ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, ui32Func, SDIO_CCCR_BUS_SPEED_SELECT, 0, &ui8SpeedReg, true);
960         if ( ui32Status != AM_HAL_STATUS_SUCCESS )
961         {
962             AM_HAL_CARD_DEBUG("Fail to read SDIO card bus speed register\n");
963             return ui32Status;
964         }
965 
966         if ( ((ui8SpeedReg >> 1) & 0x1) == SDIO_FULLSPEED_ENABLED )
967         {
968             AM_HAL_CARD_DEBUG("SDIO card is set into full speed mode\n");
969         }
970         else
971         {
972             AM_HAL_CARD_DEBUG("SDIO card full speed mode check failed\n");
973             return AM_HAL_STATUS_FAIL;
974         }
975     }
976 
977     //
978     // Set SDIO host controller clock speed.
979     //
980     if ( pHost->ops->set_bus_clock(pHost->pHandle, ui32Clock) != AM_HAL_STATUS_SUCCESS )
981     {
982         return AM_HAL_STATUS_FAIL;
983     }
984     else
985     {
986         AM_HAL_CARD_DEBUG("SDIO clock frequency is %dHz\n", ui32Clock);
987     }
988 
989     return AM_HAL_STATUS_SUCCESS;
990 }
991 
992 //
993 //! Enable SDIO card function
994 //
995 uint32_t
am_hal_sdio_card_func_enable(am_hal_card_t * pCard,uint32_t ui32Func)996 am_hal_sdio_card_func_enable(am_hal_card_t *pCard, uint32_t ui32Func)
997 {
998     uint32_t ui32Status;
999     uint8_t  ui8Tries = 0;
1000     uint8_t  ui8RegData = 0;
1001 
1002 #ifndef AM_HAL_DISABLE_API_VALIDATION
1003 
1004     if ( !pCard || !pCard->pHost )
1005     {
1006         return AM_HAL_STATUS_INVALID_ARG;
1007     }
1008 
1009 #endif // AM_HAL_DISABLE_API_VALIDATION
1010 
1011     if ( (ui32Func < 1) || (ui32Func > pCard->ui32FuncNum) )
1012     {
1013         return AM_HAL_STATUS_INVALID_ARG;
1014     }
1015 
1016     ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, 0, SDIO_CCCR_IO_ENABLE, 0, &ui8RegData, true);
1017     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
1018     {
1019         AM_HAL_CARD_DEBUG("Fail to read SDIO card IO Enable register\n");
1020         return ui32Status;
1021     }
1022     else
1023     {
1024         AM_HAL_CARD_DEBUG("Register SDIO_CCCR_IO_ENABLE = 0x%x \n", ui8RegData);
1025     }
1026 
1027     ui8RegData |= (1 << ui32Func);
1028     ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, 0, SDIO_CCCR_IO_ENABLE, ui8RegData, NULL, false);
1029     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
1030     {
1031         AM_HAL_CARD_DEBUG("Fail to write SDIO card IO Enable register\n");
1032         return ui32Status;
1033     }
1034 
1035     do
1036     {
1037         ui8Tries++;
1038         ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, 0, SDIO_CCCR_IO_RDY, 0, &ui8RegData, true);
1039         if ( ui32Status != AM_HAL_STATUS_SUCCESS )
1040         {
1041             AM_HAL_CARD_DEBUG("Fail to read SDIO card IO Ready register. Tried %d times\n", ui8Tries);
1042             return ui32Status;
1043         }
1044         if ( ui8RegData & (1 << ui32Func) )
1045         {
1046             AM_HAL_CARD_DEBUG("SDIO card IO Function %d is ready\n", ui32Func);
1047             break;
1048         }
1049         am_util_delay_ms(10);
1050     } while (ui8Tries < 100);
1051 
1052     return (ui8Tries >= 100) ? AM_HAL_STATUS_TIMEOUT : AM_HAL_STATUS_SUCCESS;
1053 }
1054 
1055 //
1056 //! Disable SDIO card function
1057 //
1058 uint32_t
am_hal_sdio_card_func_disable(am_hal_card_t * pCard,uint32_t ui32Func)1059 am_hal_sdio_card_func_disable(am_hal_card_t *pCard, uint32_t ui32Func)
1060 {
1061     uint32_t ui32Status;
1062     uint8_t  ui8RegData = 0;
1063 
1064 #ifndef AM_HAL_DISABLE_API_VALIDATION
1065 
1066     if ( !pCard || !pCard->pHost )
1067     {
1068         return AM_HAL_STATUS_INVALID_ARG;
1069     }
1070 
1071 #endif // AM_HAL_DISABLE_API_VALIDATION
1072 
1073     if ( (ui32Func < 1) || (ui32Func > pCard->ui32FuncNum) )
1074     {
1075         return AM_HAL_STATUS_INVALID_ARG;
1076     }
1077 
1078     ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, 0, SDIO_CCCR_IO_ENABLE, 0, &ui8RegData, true);
1079     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
1080     {
1081         AM_HAL_CARD_DEBUG("Fail to read SDIO card IO Enable register\n");
1082         return ui32Status;
1083     }
1084     else
1085     {
1086         AM_HAL_CARD_DEBUG("Register SDIO_CCCR_IO_ENABLE = 0x%x \n", ui8RegData);
1087     }
1088 
1089     ui8RegData &= ~(1 << ui32Func);
1090     ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, 0, SDIO_CCCR_IO_ENABLE, ui8RegData, NULL, false);
1091     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
1092     {
1093         AM_HAL_CARD_DEBUG("Fail to Disable SDIO card IO function\n");
1094         return ui32Status;
1095     }
1096     else
1097     {
1098         AM_HAL_CARD_DEBUG("SDIO card IO function %d is disabled\n", ui32Func);
1099     }
1100 
1101     return AM_HAL_STATUS_SUCCESS;
1102 }
1103 
1104 //
1105 //! Enable SDIO card function's interrupt
1106 //
1107 uint32_t
am_hal_sdio_card_func_interrupt_enable(am_hal_card_t * pCard,uint32_t ui32Func)1108 am_hal_sdio_card_func_interrupt_enable(am_hal_card_t *pCard, uint32_t ui32Func)
1109 {
1110     uint32_t ui32Status;
1111     uint8_t  ui8RegData = 0;
1112 
1113 #ifndef AM_HAL_DISABLE_API_VALIDATION
1114 
1115     if ( !pCard || !pCard->pHost )
1116     {
1117         return AM_HAL_STATUS_INVALID_ARG;
1118     }
1119 
1120 #endif // AM_HAL_DISABLE_API_VALIDATION
1121 
1122     if ( (ui32Func < 1) || (ui32Func > pCard->ui32FuncNum) )
1123     {
1124         return AM_HAL_STATUS_INVALID_ARG;
1125     }
1126 
1127     ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, 0, SDIO_CCCR_INT_ENABLE, 0, &ui8RegData, true);
1128     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
1129     {
1130         AM_HAL_CARD_DEBUG("Fail to read SDIO card IO Interrupt Enable register\n");
1131         return ui32Status;
1132     }
1133     else
1134     {
1135         AM_HAL_CARD_DEBUG("Register SDIO_CCCR_INT_ENABLE = 0x%x \n", ui8RegData);
1136     }
1137 
1138     ui8RegData |= ((1 << ui32Func) | 0x1);
1139     ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, 0, SDIO_CCCR_INT_ENABLE, ui8RegData, NULL, false);
1140     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
1141     {
1142         AM_HAL_CARD_DEBUG("Fail to Enable SDIO card IO function's interrupt\n");
1143         return ui32Status;
1144     }
1145     else
1146     {
1147         AM_HAL_CARD_DEBUG("SDIO card IO function %d interrupt is enabled\n", ui32Func);
1148     }
1149 
1150     return AM_HAL_STATUS_SUCCESS;
1151 }
1152 
1153 //
1154 //! Disable SDIO card function's interrupt
1155 //
1156 uint32_t
am_hal_sdio_card_func_interrupt_disable(am_hal_card_t * pCard,uint32_t ui32Func)1157 am_hal_sdio_card_func_interrupt_disable(am_hal_card_t *pCard, uint32_t ui32Func)
1158 {
1159     uint32_t ui32Status;
1160     uint8_t  ui8RegData = 0;
1161 
1162 #ifndef AM_HAL_DISABLE_API_VALIDATION
1163 
1164     if ( !pCard || !pCard->pHost )
1165     {
1166         return AM_HAL_STATUS_INVALID_ARG;
1167     }
1168 
1169 #endif // AM_HAL_DISABLE_API_VALIDATION
1170 
1171     if ( (ui32Func < 1) || (ui32Func > pCard->ui32FuncNum) )
1172     {
1173         return AM_HAL_STATUS_INVALID_ARG;
1174     }
1175 
1176     ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, 0, SDIO_CCCR_INT_ENABLE, 0, &ui8RegData, true);
1177     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
1178     {
1179         AM_HAL_CARD_DEBUG("Fail to read SDIO card IO Interrupt Enable register\n");
1180         return ui32Status;
1181     }
1182     else
1183     {
1184         AM_HAL_CARD_DEBUG("Register SDIO_CCCR_INT_ENABLE = 0x%x \n", ui8RegData);
1185     }
1186 
1187     ui8RegData &= ~(1 << ui32Func);
1188     ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, 0, SDIO_CCCR_INT_ENABLE, ui8RegData, NULL, false);
1189     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
1190     {
1191         AM_HAL_CARD_DEBUG("Fail to disable SDIO card IO function's interrupt\n");
1192         return ui32Status;
1193     }
1194     else
1195     {
1196         AM_HAL_CARD_DEBUG("SDIO card IO function %d interrupt is disabled\n", ui32Func);
1197     }
1198 
1199     return AM_HAL_STATUS_SUCCESS;
1200 }
1201 
1202 //
1203 //! Get SDIO card function block size
1204 //
1205 uint32_t
am_hal_sdio_card_get_block_size(am_hal_card_t * pCard,uint32_t ui32Func,uint32_t * pui32BlkSize)1206 am_hal_sdio_card_get_block_size(am_hal_card_t *pCard, uint32_t ui32Func, uint32_t *pui32BlkSize)
1207 {
1208     uint32_t ui32Status;
1209     uint32_t ui32RegAddr = 0;
1210     uint8_t  ui8RegData = 0;
1211 
1212 #ifndef AM_HAL_DISABLE_API_VALIDATION
1213 
1214     if ( !pCard || !pCard->pHost )
1215     {
1216         return AM_HAL_STATUS_INVALID_ARG;
1217     }
1218 
1219 #endif // AM_HAL_DISABLE_API_VALIDATION
1220 
1221     if ( ui32Func > pCard->ui32FuncNum )
1222     {
1223         return AM_HAL_STATUS_INVALID_ARG;
1224     }
1225 
1226     ui32RegAddr = SDIO_CCCR_FN_BLK_SIZE1 + (ui32Func << 8);
1227     ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, 0, ui32RegAddr, 0, &ui8RegData, true);
1228     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
1229     {
1230         AM_HAL_CARD_DEBUG("Fail to read SDIO card function %d block size low byte\n", ui32Func);
1231         return ui32Status;
1232     }
1233     else
1234     {
1235         *pui32BlkSize = ui8RegData;
1236     }
1237 
1238     ui32RegAddr = SDIO_CCCR_FN_BLK_SIZE2 + (ui32Func << 8);
1239     ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, 0, ui32RegAddr, 0, &ui8RegData, true);
1240     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
1241     {
1242         AM_HAL_CARD_DEBUG("Fail to read SDIO card function %d block size high byte\n", ui32Func);
1243         return ui32Status;
1244     }
1245     else
1246     {
1247         *pui32BlkSize |= (ui8RegData << 8);
1248         AM_HAL_CARD_DEBUG("SDIO card function %d block size = %d\n", ui32Func, *pui32BlkSize);
1249     }
1250 
1251     return AM_HAL_STATUS_SUCCESS;
1252 }
1253 
1254 //
1255 //! Set SDIO card function block size
1256 //
1257 uint32_t
am_hal_sdio_card_set_block_size(am_hal_card_t * pCard,uint32_t ui32Func,uint32_t ui32BlkSize)1258 am_hal_sdio_card_set_block_size(am_hal_card_t *pCard, uint32_t ui32Func, uint32_t ui32BlkSize)
1259 {
1260     uint32_t ui32Status;
1261     uint32_t ui32RegAddr = 0;
1262     uint8_t  ui8WrData = 0;
1263 
1264 #ifndef AM_HAL_DISABLE_API_VALIDATION
1265 
1266     if ( !pCard || !pCard->pHost )
1267     {
1268         return AM_HAL_STATUS_INVALID_ARG;
1269     }
1270 
1271 #endif // AM_HAL_DISABLE_API_VALIDATION
1272 
1273     if ( ui32Func > pCard->ui32FuncNum )
1274     {
1275         return AM_HAL_STATUS_INVALID_ARG;
1276     }
1277 
1278     ui32RegAddr = SDIO_CCCR_FN_BLK_SIZE1 + (ui32Func << 8);
1279     ui8WrData = ui32BlkSize & 0xFF;
1280     ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, 0, ui32RegAddr, ui8WrData, NULL, false);
1281     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
1282     {
1283         AM_HAL_CARD_DEBUG("Fail to write SDIO card function %d block size low byte\n", ui32Func);
1284         return ui32Status;
1285     }
1286 
1287     ui32RegAddr = SDIO_CCCR_FN_BLK_SIZE2 + (ui32Func << 8);
1288     ui8WrData = (ui32BlkSize & 0xFF00) >> 8;
1289     ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, 0, ui32RegAddr, ui8WrData, NULL, false);
1290     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
1291     {
1292         AM_HAL_CARD_DEBUG("Fail to write SDIO card function %d block size high byte\n", ui32Func);
1293         return ui32Status;
1294     }
1295 
1296     AM_HAL_CARD_DEBUG("SDIO card function %d block size is set into %d\n", ui32Func, ui32BlkSize);
1297 
1298     return AM_HAL_STATUS_SUCCESS;
1299 }
1300 
1301 //
1302 //! Set SD card bus width
1303 //
1304 static uint32_t
am_hal_sd_card_set_bus_width(am_hal_card_t * pCard,am_hal_host_bus_width_e eBusWidth)1305 am_hal_sd_card_set_bus_width(am_hal_card_t *pCard, am_hal_host_bus_width_e eBusWidth)
1306 {
1307     uint32_t ui32Status;
1308 
1309     am_hal_card_host_t *pHost = pCard->pHost;
1310 
1311 #ifndef AM_HAL_DISABLE_API_VALIDATION
1312 
1313     if ( !pCard || !pCard->pHost )
1314     {
1315         return AM_HAL_STATUS_INVALID_ARG;
1316     }
1317 
1318 #endif // AM_HAL_DISABLE_API_VALIDATION
1319 
1320     ui32Status = am_hal_sdcard_acmd6_set_bus_width(pCard, eBusWidth);
1321     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
1322     {
1323         return ui32Status;
1324     }
1325 
1326     if ( pHost->ops->set_bus_width(pHost->pHandle, eBusWidth) != AM_HAL_STATUS_SUCCESS )
1327     {
1328         return AM_HAL_STATUS_FAIL;
1329     }
1330 
1331     return AM_HAL_STATUS_SUCCESS;
1332 }
1333 
1334 //
1335 //! Check SD card speed with CMD6
1336 //
1337 static uint32_t
am_hal_sd_card_check_speed(am_hal_card_t * pCard)1338 am_hal_sd_card_check_speed(am_hal_card_t *pCard)
1339 {
1340     am_hal_card_host_t *pHost;
1341     am_hal_card_cmd_t cmd;
1342     am_hal_card_cmd_data_t cmd_data;
1343 
1344     uint32_t ui32Status = 0;
1345     uint8_t ui8Resp[64] = {0};
1346 
1347 #ifndef AM_HAL_DISABLE_API_VALIDATION
1348 
1349     if ( !pCard || !pCard->pHost )
1350     {
1351         return AM_HAL_STATUS_INVALID_ARG;
1352     }
1353 #endif // AM_HAL_DISABLE_API_VALIDATION
1354 
1355     pHost = pCard->pHost;
1356 
1357     memset((void *)&cmd, 0x0, sizeof(cmd));
1358     memset((void *)&cmd_data, 0x0, sizeof(cmd_data));
1359 
1360     cmd.ui8Idx = MMC_CMD_SWITCH;
1361     cmd.ui32Arg = SD_CARD_CHECK_FUNCTION | SD_CARD_SWITCH_ARGUMENT | SD_CARD_CHECK_ALL_SPEED;
1362     cmd.ui32RespType = MMC_RSP_R1;
1363     cmd.bASync = 0;
1364     cmd.bAutoCMD23 = false;
1365 
1366     cmd_data.ui8IovCnt = 0;
1367     cmd_data.pui8Buf = ui8Resp;
1368     cmd_data.ui32BlkCnt = 1;
1369     cmd_data.ui32BlkSize = 64;
1370     cmd_data.dir = AM_HAL_DATA_DIR_READ;
1371 
1372     ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, &cmd_data);
1373     if ( (ui32Status & 0xFFFF) != AM_HAL_CMD_ERR_NONE)
1374     {
1375         return ui32Status;
1376     }
1377 
1378     if ( pCard->sdcard.ui32CurrentVolt == AM_HAL_SD_CARD_1_8_V )
1379     {
1380         if ( ui8Resp[13] & ( 1 << SD_CARD_SDR12 ) )
1381         {
1382             pCard->sdcard.bSupportSDR12 = 1;
1383             AM_HAL_CARD_DEBUG("Card support SDR12 speed\n");
1384         }
1385         else
1386         {
1387             pCard->sdcard.bSupportSDR12 = 0;
1388             AM_HAL_CARD_DEBUG("Card not support SDR12 speed\n");
1389         }
1390 
1391         if ( ui8Resp[13] & ( 1 << SD_CARD_SDR25 ) )
1392         {
1393             pCard->sdcard.bSupportSDR25 = 1;
1394             AM_HAL_CARD_DEBUG("Card support SDR25 speed\n");
1395         }
1396         else
1397         {
1398             pCard->sdcard.bSupportSDR25 = 0;
1399             AM_HAL_CARD_DEBUG("Card not support SDR25 speed\n");
1400         }
1401 
1402         if ( ui8Resp[13] & ( 1 << SD_CARD_SDR50 ) )
1403         {
1404             pCard->sdcard.bSupportSDR50 = 1;
1405             AM_HAL_CARD_DEBUG("Card support SDR50 speed\n");
1406         }
1407         else
1408         {
1409             pCard->sdcard.bSupportSDR50 = 0;
1410             AM_HAL_CARD_DEBUG("Card not support SDR50 speed\n");
1411         }
1412 
1413         if ( ui8Resp[13] & ( 1 << SD_CARD_SDR104 ) )
1414         {
1415             pCard->sdcard.bSupportSDR104 = 1;
1416             AM_HAL_CARD_DEBUG("Card support SDR104 speed\n");
1417         }
1418         else
1419         {
1420             pCard->sdcard.bSupportSDR104 = 0;
1421             AM_HAL_CARD_DEBUG("Card not support SDR104 speed\n");
1422         }
1423 
1424         if ( ui8Resp[13] & ( 1 << SD_CARD_DDR50 ) )
1425         {
1426             pCard->sdcard.bSupportDDR50 = 1;
1427             AM_HAL_CARD_DEBUG("Card support DDR50 speed\n");
1428         }
1429         else
1430         {
1431             pCard->sdcard.bSupportDDR50 = 0;
1432             AM_HAL_CARD_DEBUG("Card not support DDR50 speed\n");
1433         }
1434 
1435     }
1436     else
1437     {
1438         if ( ui8Resp[13] & 0x1 )
1439         {
1440             pCard->sdcard.bSupportDefaultSpeed = 1;
1441             AM_HAL_CARD_DEBUG("Card support Default speed\n");
1442         }
1443         else
1444         {
1445             pCard->sdcard.bSupportDefaultSpeed = 0;
1446             AM_HAL_CARD_DEBUG("Card not support Default speed\n");
1447         }
1448 
1449         if ( ui8Resp[13] & 0x2 )
1450         {
1451             pCard->sdcard.bSupportHighSpeed = 1;
1452             AM_HAL_CARD_DEBUG("Card support High speed\n");
1453         }
1454         else
1455         {
1456             pCard->sdcard.bSupportHighSpeed = 0;
1457             AM_HAL_CARD_DEBUG("Card not support High speed\n");
1458         }
1459     }
1460 
1461     return AM_HAL_STATUS_SUCCESS;
1462 }
1463 
1464 //
1465 //! Set SD card clock speed
1466 //
1467 static uint32_t
am_hal_sd_card_set_speed(am_hal_card_t * pCard,uint32_t ui32Clock)1468 am_hal_sd_card_set_speed(am_hal_card_t *pCard, uint32_t ui32Clock)
1469 {
1470     uint32_t ui32Status = 0;
1471     uint32_t ui32Mode = 0;
1472     uint8_t ui8Resp[64] = {0};
1473     am_hal_card_cmd_t cmd;
1474     am_hal_card_cmd_data_t cmd_data;
1475 
1476     am_hal_card_host_t *pHost = pCard->pHost;
1477 
1478 #ifndef AM_HAL_DISABLE_API_VALIDATION
1479 
1480     if ( !pCard || !pCard->pHost )
1481     {
1482         return AM_HAL_STATUS_INVALID_ARG;
1483     }
1484 
1485 #endif // AM_HAL_DISABLE_API_VALIDATION
1486 
1487     if ( am_hal_sd_card_check_speed(pCard) != AM_HAL_STATUS_SUCCESS )
1488     {
1489         return AM_HAL_STATUS_FAIL;
1490     }
1491 
1492     if ( pCard->sdcard.ui32CurrentVolt == AM_HAL_SD_CARD_3_3_V )
1493     {
1494         if ( (ui32Clock > 25000000) && (pCard->sdcard.bSupportHighSpeed == 0) )
1495         {
1496             AM_HAL_CARD_DEBUG("Setting high speed failed, Card not support High speed\n");
1497             return AM_HAL_STATUS_FAIL;
1498         }
1499         else if ( ui32Clock > 25000000 )
1500         {
1501             ui32Mode |= SD_CARD_HIGH_SPEED;
1502         }
1503         else
1504         {
1505             ui32Mode |= SD_CARD_DEFAULT_SPEED;
1506         }
1507     }
1508     else
1509     {
1510         ui32Mode = pCard->cfg.eUHSMode;
1511         if (((pCard->cfg.eUHSMode == AM_HAL_HOST_UHS_SDR104) &&
1512             (ui32Clock > MMC_HS_MAX_SPEED_LIMIT) &&
1513             (ui32Clock < MMC_HS200_MAX_SPEED_LIMIT)))
1514         {
1515             ui32Mode = AM_HAL_HOST_UHS_SDR50;
1516         }
1517 
1518         if (((pCard->cfg.eUHSMode == AM_HAL_HOST_UHS_SDR104) && (pCard->sdcard.bSupportSDR104 == false)) ||
1519             ((pCard->cfg.eUHSMode == AM_HAL_HOST_UHS_DDR50) && (pCard->sdcard.bSupportDDR50 == false))
1520            )
1521            {
1522                 AM_HAL_CARD_DEBUG(" Card not support USH mode: %x\n", pCard->cfg.eUHSMode);
1523                 return AM_HAL_STATUS_FAIL;
1524            }
1525     }
1526 
1527     //
1528     // Set bus speed used CMD6
1529     //
1530     memset((void *)&cmd, 0x0, sizeof(cmd));
1531     memset((void *)&cmd_data, 0x0, sizeof(cmd_data));
1532 
1533     cmd.ui8Idx = MMC_CMD_SWITCH;
1534     cmd.ui32Arg = SD_CARD_SWITCH_FUNCTION | SD_CARD_SWITCH_ARGUMENT | ui32Mode;
1535     cmd.ui32RespType = MMC_RSP_R1;
1536     cmd.bASync = 0;
1537     cmd.bAutoCMD23 =  false;
1538 
1539     cmd_data.ui8IovCnt = 0;
1540     cmd_data.pui8Buf = ui8Resp;
1541     cmd_data.ui32BlkCnt = 1;
1542     cmd_data.ui32BlkSize = 64;
1543     cmd_data.dir = AM_HAL_DATA_DIR_READ;
1544 
1545     ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, &cmd_data);
1546     if ( (ui32Status & 0xFFFF) != AM_HAL_CMD_ERR_NONE)
1547     {
1548         return ui32Status;
1549     }
1550 
1551     uint8_t ui32AccessMode = ui8Resp[16] & 0xF;
1552 
1553     if ( pCard->sdcard.ui32CurrentVolt == AM_HAL_SD_CARD_3_3_V )
1554     {
1555         if ( ui32AccessMode && ( ui32Clock > 25000000 ) )
1556         {
1557             if ( ui32AccessMode == SD_CARD_HIGH_SPEED )
1558             {
1559                 AM_HAL_CARD_DEBUG("Succeed on Switching High-Speed\n");
1560                 pCard->sdcard.bHighSpeed = 1;
1561             }
1562             else
1563             {
1564                 AM_HAL_CARD_DEBUG("Failed on Switching High-Speed\n"); // Quirk
1565                 return AM_HAL_STATUS_FAIL;
1566             }
1567         }
1568         else
1569         {
1570             if ( ui32AccessMode == SD_CARD_DEFAULT_SPEED )
1571             {
1572                 AM_HAL_CARD_DEBUG("Succeed on Switching Default-Speed\n");
1573                 pCard->sdcard.bHighSpeed = 0;
1574             }
1575             else
1576             {
1577                 AM_HAL_CARD_DEBUG("Failed on Switching Default-Speed\n");
1578                 return AM_HAL_STATUS_FAIL;
1579             }
1580         }
1581     }
1582     else
1583     {
1584         if ( ui32AccessMode == ui32Mode )
1585         {
1586             AM_HAL_CARD_DEBUG("Succeed on Switching Speed: %x\n", ui32Mode);
1587         }
1588         else
1589         {
1590             AM_HAL_CARD_DEBUG("Failed on Switching High-Speed\n"); // Quirk
1591             return AM_HAL_STATUS_FAIL;
1592         }
1593     }
1594 
1595     //
1596     // Set SDIO host controller clock speed.
1597     //
1598     if ( pHost->ops->set_bus_clock(pHost->pHandle, ui32Clock) != AM_HAL_STATUS_SUCCESS )
1599     {
1600         return AM_HAL_STATUS_FAIL;
1601     }
1602     else
1603     {
1604         AM_HAL_CARD_DEBUG("SDIO clock frequency is %dHz\n", ui32Clock);
1605     }
1606 
1607     return AM_HAL_STATUS_SUCCESS;
1608 }
1609 
1610 //
1611 //! Enable SD Card detect function
1612 //
1613 uint32_t
am_hal_sd_card_enable_card_detect(am_hal_card_t * pCard,am_hal_host_event_cb_t pfunCallback)1614 am_hal_sd_card_enable_card_detect(am_hal_card_t *pCard, am_hal_host_event_cb_t pfunCallback)
1615 {
1616     uint32_t ui32Status;
1617 
1618     am_hal_card_host_t *pHost = pCard->pHost;
1619 
1620 #ifndef AM_HAL_DISABLE_API_VALIDATION
1621 
1622     if ( !pCard || !pCard->pHost || !pfunCallback )
1623     {
1624         return AM_HAL_STATUS_INVALID_ARG;
1625     }
1626 
1627 #endif // AM_HAL_DISABLE_API_VALIDATION
1628 
1629     //
1630     // Register card interrupt callback function
1631     //
1632     ui32Status = am_hal_card_register_evt_callback(pCard, pfunCallback);
1633     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
1634     {
1635         return ui32Status;
1636     }
1637 
1638     ui32Status = am_hal_sdhc_intr_signal_enable(pHost->pHandle,  SDIO_INTSIG_CARDREMOVALEN_Msk |
1639                                                                  SDIO_INTSIG_CARDINSERTEN_Msk);
1640     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
1641     {
1642         return ui32Status;
1643     }
1644 
1645     ui32Status = am_hal_sdhc_intr_status_enable(pHost->pHandle, SDIO_INTENABLE_CARDREMOVALSTATUSENABLE_Msk |
1646                                                                 SDIO_INTENABLE_CARDINSERTIONSTATUSENABLE_Msk);
1647     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
1648     {
1649         return ui32Status;
1650     }
1651 
1652     return ui32Status;
1653 }
1654 
1655 //
1656 //! Disable SD Card detect function
1657 //
1658 uint32_t
am_hal_sd_card_disable_card_detect(am_hal_card_t * pCard)1659 am_hal_sd_card_disable_card_detect(am_hal_card_t *pCard)
1660 {
1661     uint32_t ui32Status;
1662 
1663     am_hal_card_host_t *pHost = pCard->pHost;
1664 
1665 #ifndef AM_HAL_DISABLE_API_VALIDATION
1666 
1667     if ( !pCard || !pCard->pHost )
1668     {
1669         return AM_HAL_STATUS_INVALID_ARG;
1670     }
1671 
1672 #endif // AM_HAL_DISABLE_API_VALIDATION
1673 
1674     ui32Status = am_hal_sdhc_intr_signal_disable(pHost->pHandle, SDIO_INTSIG_CARDINTEN_Msk |
1675                                                              SDIO_INTSIG_CARDREMOVALEN_Msk |
1676                                                               SDIO_INTSIG_CARDINSERTEN_Msk);
1677     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
1678     {
1679         return ui32Status;
1680     }
1681 
1682     ui32Status = am_hal_sdhc_intr_status_disable(pHost->pHandle, SDIO_INTENABLE_CARDINTERRUPTSTATUSENABLE_Msk |
1683                                                                    SDIO_INTENABLE_CARDREMOVALSTATUSENABLE_Msk |
1684                                                                  SDIO_INTENABLE_CARDINSERTIONSTATUSENABLE_Msk);
1685     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
1686     {
1687         return ui32Status;
1688     }
1689 
1690     return ui32Status;
1691 }
1692 
1693 //
1694 //! SD Card write protect detect function
1695 //
1696 uint32_t
am_hal_sd_card_write_protect_detect(am_hal_card_t * pCard)1697 am_hal_sd_card_write_protect_detect(am_hal_card_t *pCard)
1698 {
1699     am_hal_card_host_t *pHost;
1700 
1701 #ifndef AM_HAL_DISABLE_API_VALIDATION
1702 
1703     if ( !pCard || !pCard->pHost )
1704     {
1705         return AM_HAL_STATUS_INVALID_ARG;
1706     }
1707 
1708 #endif // AM_HAL_DISABLE_API_VALIDATION
1709 
1710     pHost = pCard->pHost;
1711 
1712     if ( pHost->ops->get_wr_protect(pHost->pHandle) )
1713     {
1714         pCard->sdcard.bWrProtect = false;
1715     }
1716     else
1717     {
1718         pCard->sdcard.bWrProtect = true;
1719     }
1720 
1721     return AM_HAL_STATUS_SUCCESS;
1722 }
1723 
1724 //
1725 //! SD Card set voltage
1726 //
1727 static uint32_t
am_hal_sd_card_set_voltage(am_hal_card_t * pCard,am_hal_host_bus_voltage_e eIoVoltage)1728 am_hal_sd_card_set_voltage(am_hal_card_t *pCard, am_hal_host_bus_voltage_e eIoVoltage)
1729 {
1730     uint32_t ui32RetVal = AM_HAL_STATUS_SUCCESS;
1731 
1732 #ifndef AM_HAL_DISABLE_API_VALIDATION
1733     if ( !pCard || !pCard->pHost )
1734     {
1735         return AM_HAL_STATUS_INVALID_ARG;
1736     }
1737 #endif // AM_HAL_DISABLE_API_VALIDATION
1738 
1739     //
1740     // if current voltage equal to setting voltage, do not power cycle and then return
1741     //
1742     if ( (pCard->sdcard.ui32CurrentVolt == AM_HAL_SD_CARD_3_3_V &&
1743                     eIoVoltage == AM_HAL_HOST_BUS_VOLTAGE_3_3) ||
1744          (pCard->sdcard.ui32CurrentVolt == AM_HAL_SD_CARD_1_8_V &&
1745                     eIoVoltage == AM_HAL_HOST_BUS_VOLTAGE_1_8) )
1746     {
1747         return AM_HAL_STATUS_SUCCESS;
1748     }
1749 
1750     //
1751     // SD card power cycle
1752     //
1753     if ( pCard->pCardPwrCtrlFunc != NULL )
1754     {
1755         pCard->pCardPwrCtrlFunc(AM_HAL_CARD_PWR_CYCLE);
1756     }
1757 
1758     //
1759     // Wait about 74 cycles after powered on
1760     //
1761     am_util_delay_us(200);
1762 
1763     //
1764     // Reset the card
1765     //
1766     if ( am_hal_sdmmc_cmd0_go_idle(pCard) != AM_HAL_CMD_ERR_NONE )
1767     {
1768         AM_HAL_CARD_DEBUG("CMD0 Failed\n");
1769         return AM_HAL_STATUS_FAIL;
1770     }
1771 
1772     //
1773     // Send CMD8 for interface condition.
1774     //
1775     uint32_t ui32OCR = SD_CARD_CHECK_PATTERN | SD_CARD_2P7_3P6_VOLTAGE_SUPPLY;
1776     if ( am_hal_sdio_cmd8_send_if_cond(pCard, ui32OCR) != AM_HAL_CMD_ERR_NONE )
1777     {
1778         AM_HAL_CARD_DEBUG("CMD8 Failed\n");
1779         return AM_HAL_STATUS_FAIL;
1780     }
1781 
1782     //
1783     // need retry more than 1s, a ACMD41 need about 3.2ms
1784     //
1785     uint32_t ui32Retries = 0x200;
1786     uint32_t ui32Resp0;
1787 
1788     while (ui32Retries--)
1789     {
1790         ui32RetVal = am_hal_sdcard_acmd41_send_op_cond(pCard, SD_CARD_DEFAULT_OCR, &ui32Resp0);
1791         if ( ui32RetVal != AM_HAL_CMD_ERR_NONE )
1792         {
1793             AM_HAL_CARD_DEBUG("SD Card CMD55&CMD41 error:%d\n", ui32RetVal);
1794         }
1795 
1796         if ( ui32Resp0 & SD_CARD_OCR_MSK_BUSY )
1797         {
1798             //
1799             // Check the sd card capacity and card type
1800             //
1801             if ( ui32Resp0 & SD_CARD_OCR_MSK_HC )
1802             {
1803                 pCard->bHighCapcity = 1;
1804                 AM_HAL_CARD_DEBUG("High Capacity SD Memory Card\r\n");
1805             }
1806             else
1807             {
1808                 pCard->bHighCapcity = 0;
1809                 AM_HAL_CARD_DEBUG("Standard Capacity SD Memory Card\r\n");
1810             }
1811 
1812             //
1813             // Check the sd card if support 1.8V signaling
1814             //
1815             if ( ui32Resp0 & SD_CARD_1P8V_MSK )
1816             {
1817                 pCard->sdcard.bSupportLowVolt = true;
1818                 AM_HAL_CARD_DEBUG("SD Card Support 1.8v Switching\r\n");
1819             }
1820             else
1821             {
1822                 pCard->sdcard.ui32CurrentVolt = AM_HAL_SD_CARD_3_3_V;
1823                 pCard->sdcard.bSupportLowVolt = false;
1824                 AM_HAL_CARD_DEBUG("SD Card not support 1.8V, working at 3.3V signaling\r\n");
1825             }
1826 
1827             if ( eIoVoltage == AM_HAL_HOST_BUS_VOLTAGE_1_8 && pCard->sdcard.bSupportLowVolt )
1828             {
1829                 //
1830                 // Switch to 1.8V signaling
1831                 //
1832                 ui32RetVal = am_hal_sdcard_cmd11_voltage_switch(pCard);
1833                 if ( ui32RetVal == AM_HAL_CMD_ERR_NONE )
1834                 {
1835                     pCard->pCardPwrCtrlFunc(AM_HAL_CARD_PWR_SWITCH);
1836                     pCard->sdcard.ui32CurrentVolt = AM_HAL_SD_CARD_1_8_V;
1837                     AM_HAL_CARD_DEBUG("SD Card Switch 1.8v Successfully\r\n");
1838                 }
1839                 else
1840                 {
1841                     AM_HAL_CARD_DEBUG("SD Card Switch to 1.8V  failed:%d\n", ui32RetVal);
1842                     return AM_HAL_STATUS_FAIL;
1843                 }
1844             }
1845 
1846             break;
1847         }
1848     }
1849 
1850     if ( !ui32Retries )
1851     {
1852         AM_HAL_CARD_DEBUG("SD Card send cmd55&cmd41 retry time out\r\n");
1853         return AM_HAL_CMD_ERR_TIMEOUT;
1854     }
1855 
1856     AM_HAL_CARD_DEBUG("SD Card send cmd55&cmd41 complete, card is ready\r\n");
1857 
1858     //
1859     // Get CID
1860     //
1861     if ( am_hal_sdmmc_cmd2_send_cid(pCard) != AM_HAL_CMD_ERR_NONE )
1862     {
1863         AM_HAL_CARD_DEBUG("SD Card CMD2 Failed\n");
1864         return AM_HAL_STATUS_FAIL;
1865     }
1866 
1867     //
1868     // Get RCA
1869     //
1870     if ( am_hal_sdmmc_cmd3_set_rca(pCard, 0) != AM_HAL_CMD_ERR_NONE )
1871     {
1872         AM_HAL_CARD_DEBUG("SD Card CMD3 Failed\n");
1873         return AM_HAL_STATUS_FAIL;
1874     }
1875 
1876     //
1877     // Get the card CSD
1878     //
1879     if ( am_hal_sdmmc_cmd9_send_csd(pCard) != AM_HAL_CMD_ERR_NONE )
1880     {
1881         AM_HAL_CARD_DEBUG("SD Card CMD9 Failed\n");
1882         return AM_HAL_STATUS_FAIL;
1883     }
1884 
1885     //
1886     // Select the card as Transfer state
1887     //
1888     if ( am_hal_sdmmc_cmd7_card_select(pCard) != AM_HAL_CMD_ERR_NONE )
1889     {
1890         AM_HAL_CARD_DEBUG("SD Card CMD7 Failed\n");
1891         return AM_HAL_STATUS_FAIL;
1892     }
1893 
1894     //
1895     // Configure the card bus width as 4 in default, only support 4 bit width in 1.8V
1896     //
1897     if ( pCard->sdcard.ui32CurrentVolt == AM_HAL_SD_CARD_1_8_V )
1898     {
1899         if ( am_hal_sd_card_set_bus_width(pCard, AM_HAL_HOST_BUS_WIDTH_4) != AM_HAL_STATUS_SUCCESS )
1900         {
1901             AM_HAL_CARD_DEBUG("Failed to change bus width\n");
1902             return AM_HAL_STATUS_FAIL;
1903         }
1904     }
1905 
1906     AM_HAL_CARD_DEBUG("SD Card sdcard.ui32CurrentVolt  = 0x%x \n", pCard->sdcard.ui32CurrentVolt);
1907     AM_HAL_CARD_DEBUG("SD Card set voltage done\n");
1908 
1909     return AM_HAL_STATUS_SUCCESS;
1910 }
1911 
1912 //
1913 //! SD Card get max block count
1914 //
1915 uint32_t
am_hal_sd_card_get_block_count(am_hal_card_t * pCard)1916 am_hal_sd_card_get_block_count(am_hal_card_t *pCard)
1917 {
1918 #ifndef AM_HAL_DISABLE_API_VALIDATION
1919     if ( !pCard || !pCard->pHost )
1920     {
1921         return AM_HAL_STATUS_INVALID_ARG;
1922     }
1923 #endif // AM_HAL_DISABLE_API_VALIDATION
1924 
1925     uint32_t ui32CSDVersion;
1926     uint32_t ui32MaxBlks;
1927     ui32CSDVersion = am_hal_card_get_csd_field(pCard, 126, 2);
1928     if ( ui32CSDVersion == 0 )
1929     {
1930         uint32_t ui32CSizeMult = am_hal_card_get_csd_field(pCard, 47, 3);
1931         uint32_t ui32CSize = am_hal_card_get_csd_field(pCard, 62, 12);
1932         uint32_t ui32RdBlockLen = am_hal_card_get_csd_field(pCard, 80, 4);
1933 
1934         uint32_t ui32Mult = 1 << ( ui32CSizeMult + 2 );
1935         uint32_t ui32BlockLen = 1 << ui32RdBlockLen;
1936 
1937         //
1938         // CSD 1.0: Memory capacity = ( C_SIZE + 1 ) * ui32Mult * ui32BlockLen.
1939         //
1940         ui32MaxBlks = ( ui32CSize + 1 ) * ui32Mult * ui32BlockLen / 512;
1941     }
1942     else if ( ui32CSDVersion == 1 )
1943     {
1944         uint32_t ui32CSize = am_hal_card_get_csd_field(pCard, 48, 22);
1945 
1946         //
1947         // CSD 2.0: Memory capacity = ( C_SIZE + 1 ) * 512K.
1948         //
1949         ui32MaxBlks = (ui32CSize + 1) * 1024;
1950     }
1951 
1952     return ui32MaxBlks;
1953 }
1954 
1955 //
1956 //! Card Cache Control
1957 //
1958 static uint32_t
am_hal_card_cache_ctrl(am_hal_card_t * pCard,bool bCacheEnable)1959 am_hal_card_cache_ctrl(am_hal_card_t *pCard, bool bCacheEnable)
1960 {
1961     uint32_t ui32Mode;
1962 #ifndef AM_HAL_DISABLE_API_VALIDATION
1963         if ( !pCard || !pCard->pHost )
1964         {
1965             AM_HAL_CARD_DEBUG("This card is not connected to a host\n");
1966             return AM_HAL_STATUS_INVALID_ARG;
1967         }
1968 #endif // AM_HAL_DISABLE_API_VALIDATION
1969 
1970     if (pCard->ui32CacheSize > 0)
1971     {
1972         ui32Mode = MMC_EXT_MODE_WRITE_BYTE | (MMC_EXT_REGS_CACHE_CTRL << 16) | (bCacheEnable ? (1 << 8) : 0);
1973         return am_hal_card_mode_switch(pCard, ui32Mode, DEFAULT_CMD6_TIMEOUT_MS);
1974     }
1975 
1976     return AM_HAL_STATUS_INVALID_OPERATION;
1977 }
1978 
1979 //
1980 //! Card Cache On
1981 //
1982 static inline uint32_t
am_hal_card_cache_on(am_hal_card_t * pCard)1983 am_hal_card_cache_on(am_hal_card_t *pCard)
1984 {
1985     return am_hal_card_cache_ctrl(pCard, true);
1986 }
1987 
1988 //
1989 //! Card Cache Off
1990 //
1991 static inline uint32_t
am_hal_card_cache_off(am_hal_card_t * pCard)1992 am_hal_card_cache_off(am_hal_card_t *pCard)
1993 {
1994     return am_hal_card_cache_ctrl(pCard, false);
1995 }
1996 
1997 //
1998 //! Card Power Notification
1999 //
2000 static uint32_t
am_hal_card_pwr_notification(am_hal_card_t * pCard,uint8_t ui8NotifyType)2001 am_hal_card_pwr_notification(am_hal_card_t *pCard,
2002                              uint8_t ui8NotifyType)
2003 {
2004     uint32_t ui32Mode;
2005     uint32_t ui32Timeout;
2006 
2007 #ifndef AM_HAL_DISABLE_API_VALIDATION
2008         if ( !pCard || !pCard->pHost )
2009         {
2010             AM_HAL_CARD_DEBUG("This card is not connected to a host\n");
2011             return AM_HAL_STATUS_INVALID_ARG;
2012         }
2013 #endif // AM_HAL_DISABLE_API_VALIDATION
2014 
2015     if (pCard->ui8ExtCSDRev < 6)
2016     {
2017         AM_HAL_CARD_DEBUG("this eMMC card type is not supporting notification\n");
2018         return AM_HAL_STATUS_INVALID_OPERATION;
2019     }
2020 
2021     ui32Mode = MMC_EXT_MODE_WRITE_BYTE | MMC_EXT_REGS_PWR_OFF_NOTIFY << 16 | ui8NotifyType << 8;
2022 
2023     //
2024     // Timeout Selection based upon notification type
2025     //
2026     switch (ui8NotifyType)
2027     {
2028         case MMC_EXT_CSD_POWER_OFF_LONG:
2029             ui32Timeout = pCard->ui32PowerOffNotificationLongTimeout;
2030             break;
2031         case MMC_EXT_CSD_SLEEP_NOTIFICATION:
2032             ui32Timeout = pCard->ui32SleepNotificationTimeout;
2033             break;
2034         case MMC_EXT_CSD_POWERED_ON:
2035             ui32Timeout = DEFAULT_CMD6_TIMEOUT_MS;
2036             break;
2037         default:
2038             AM_HAL_CARD_DEBUG("Unknown notification type\n");
2039             return AM_HAL_STATUS_INVALID_ARG;
2040     }
2041 
2042     if (am_hal_card_mode_switch(pCard, ui32Mode, ui32Timeout) != AM_HAL_STATUS_SUCCESS)
2043     {
2044         AM_HAL_CARD_DEBUG("Unknown notification type\n");
2045         return AM_HAL_STATUS_FAIL;
2046     }
2047 
2048     pCard->ui8PowerOffNotification = ui8NotifyType;
2049 
2050     return AM_HAL_STATUS_SUCCESS;
2051 }
2052 
2053 //
2054 //! Card MMC Init
2055 //
2056 static uint32_t
am_hal_card_mmc_init(am_hal_card_t * pCard)2057 am_hal_card_mmc_init(am_hal_card_t *pCard)
2058 {
2059     uint32_t ui32RetVal = AM_HAL_STATUS_SUCCESS;
2060 
2061     //
2062     // Get the CID information of the card
2063     //
2064     if ( am_hal_sdmmc_cmd2_send_cid(pCard) != AM_HAL_CMD_ERR_NONE )
2065     {
2066         AM_HAL_CARD_DEBUG("CMD2 Failed\n");
2067         return AM_HAL_STATUS_FAIL;
2068     }
2069 
2070     //
2071     // Set relative card address to 0x1
2072     //
2073     if ( am_hal_sdmmc_cmd3_set_rca(pCard, 0x1) != AM_HAL_CMD_ERR_NONE )
2074     {
2075         AM_HAL_CARD_DEBUG("CMD3 Failed\n");
2076         return AM_HAL_STATUS_FAIL;
2077     }
2078 
2079     //
2080     // Get the card CSD
2081     //
2082     if ( am_hal_sdmmc_cmd9_send_csd(pCard) != AM_HAL_CMD_ERR_NONE )
2083     {
2084         AM_HAL_CARD_DEBUG("CMD9 Failed\n");
2085         return AM_HAL_STATUS_FAIL;
2086     }
2087 
2088     //
2089     // Select the card
2090     //
2091     if ( am_hal_sdmmc_cmd7_card_select(pCard) != AM_HAL_CMD_ERR_NONE )
2092     {
2093         AM_HAL_CARD_DEBUG("CMD7 Failed\n");
2094         return AM_HAL_STATUS_FAIL;
2095     }
2096 
2097     //
2098     // Get the ext csd
2099     //
2100     if ( am_hal_sdmmc_cmd8_send_ext_csd(pCard) != AM_HAL_CMD_ERR_NONE )
2101     {
2102        AM_HAL_CARD_DEBUG("CMD8 Failed\n");
2103        return AM_HAL_STATUS_FAIL;
2104     }
2105 
2106     //
2107     // Parse the CSD and EXT CSD to know the feature of card
2108     //
2109     uint32_t ui32CSize = am_hal_unstuff_bits(pCard->ui32CSD, 62, 12);
2110     pCard->bHighCapcity = (ui32CSize == 0xFFF) ? true : false;
2111 
2112     //
2113     // High capacity card
2114     //
2115     if ( pCard->bHighCapcity )
2116     {
2117         //
2118         // get blksize and capacity information from the ext csd
2119         //
2120         pCard->ui32BlkSize = am_hal_unstuff_bytes(pCard->ui32ExtCSD, 61, 1) ? 4096 : 512;
2121         pCard->bUseBlkEmulation = am_hal_unstuff_bytes(pCard->ui32ExtCSD, 62, 1) ? false : true;
2122         pCard->ui32NativeBlkSize = am_hal_unstuff_bytes(pCard->ui32ExtCSD, 63, 1) ? 4096 : 512;
2123         pCard->ui16CmdClass = am_hal_unstuff_bits(pCard->ui32CSD, 84, 12);
2124         pCard->ui8SpecVer = am_hal_unstuff_bits(pCard->ui32CSD, 122, 4);
2125         pCard->ui32RpmbSizeMult = am_hal_unstuff_bytes(pCard->ui32ExtCSD, 168, 1);
2126         pCard->ui8ExtCSDRev = am_hal_unstuff_bytes(pCard->ui32ExtCSD, 192, 1);
2127         pCard->ui8DeviceType = am_hal_unstuff_bytes(pCard->ui32ExtCSD, 196, 1);
2128         pCard->ui32MaxBlks = am_hal_unstuff_bytes(pCard->ui32ExtCSD, 212, 4);
2129         pCard->ui32Capacity = pCard->ui32MaxBlks*pCard->ui32BlkSize;
2130         pCard->ui32CacheSize = am_hal_unstuff_bytes(pCard->ui32ExtCSD, 249, 4);
2131         pCard->ui8SecureErase = am_hal_unstuff_bytes(pCard->ui32ExtCSD, 231, 1);
2132         pCard->ui32GenericCmd6Timeout = DEFAULT_CMD6_TIMEOUT_MS;
2133         if (pCard->ui8ExtCSDRev >= 6)
2134         {
2135             pCard->ui32SleepNotificationTimeout = am_hal_unstuff_bytes(pCard->ui32ExtCSD, 216, 1)*10;
2136             pCard->ui32PowerOffNotificationLongTimeout = am_hal_unstuff_bytes(pCard->ui32ExtCSD, 247, 1)*10;
2137             pCard->ui32GenericCmd6Timeout = am_hal_unstuff_bytes(pCard->ui32ExtCSD, 248, 1)*10;
2138         }
2139     }
2140     else
2141     {
2142         //
2143         // non high capacity card gets blksize and capacity information from the CSD
2144         //
2145     }
2146 
2147     //
2148     // Always enable the cache if it's supported
2149     //
2150     ui32RetVal = am_hal_card_cache_on(pCard);
2151     if ( AM_HAL_STATUS_SUCCESS == ui32RetVal )
2152     {
2153         //
2154         // Reread the card to get the updated cache status.
2155         //
2156         ui32RetVal = am_hal_card_get_ext_csd_field(pCard, MMC_EXT_REGS_CACHE_CTRL, 1);
2157         AM_HAL_CARD_DEBUG("\r\nExtCsd CACHE_ON - %s\r\n", ((ui32RetVal == 1) ? "Pass" : "Fail"));
2158     }
2159     else
2160     {
2161         AM_HAL_CARD_DEBUG("\r\am_hal_card_cache_on - status %x\r\n", ui32RetVal);
2162     }
2163 
2164     //
2165     // Always enable the notifcaition if it's supported
2166     //
2167     pCard->ui8PowerOffNotification = MMC_EXT_CSD_NO_POWER_NOTIFICATION;
2168     if (am_hal_card_pwr_notification(pCard, MMC_EXT_CSD_POWERED_ON) == AM_HAL_STATUS_SUCCESS)
2169     {
2170         pCard->ui8PowerOffNotification = MMC_EXT_CSD_POWERED_ON;
2171     }
2172 
2173     return AM_HAL_STATUS_SUCCESS;
2174 }
2175 
2176 //
2177 //! SD Card Init
2178 //
2179 static uint32_t
am_hal_sd_card_init(am_hal_card_t * pCard,am_hal_card_pwr_ctrl_func pCardPwrCtrlFunc)2180 am_hal_sd_card_init(am_hal_card_t *pCard, am_hal_card_pwr_ctrl_func pCardPwrCtrlFunc)
2181 {
2182     uint32_t ui32RetVal = AM_HAL_STATUS_SUCCESS;
2183 
2184     //
2185     // need retry more than 1s, a ACMD41 need about 3.2ms
2186     //
2187     uint32_t ui32Retries = 0x200;
2188     uint32_t ui32Resp0;
2189 
2190     while (ui32Retries--)
2191     {
2192         ui32RetVal = am_hal_sdcard_acmd41_send_op_cond(pCard, SD_CARD_DEFAULT_OCR, &ui32Resp0);
2193         if ( ui32RetVal != AM_HAL_CMD_ERR_NONE )
2194         {
2195             AM_HAL_CARD_DEBUG("SD Card CMD55&CMD41 error:%d\n", ui32RetVal);
2196         }
2197 
2198         if ( ui32Resp0 & SD_CARD_OCR_MSK_BUSY )
2199         {
2200             //
2201             // Check the sd card capacity and card type
2202             //
2203             if ( ui32Resp0 & SD_CARD_OCR_MSK_HC )
2204             {
2205                 pCard->bHighCapcity = 1;
2206                 AM_HAL_CARD_DEBUG("High Capacity SD Memory Card\r\n");
2207             }
2208             else
2209             {
2210                 pCard->bHighCapcity = 0;
2211                 AM_HAL_CARD_DEBUG("Standard Capacity SD Memory Card\r\n");
2212             }
2213 
2214             //
2215             // Check the sd card if support 1.8V signaling
2216             //
2217             if ( ui32Resp0 & SD_CARD_1P8V_MSK )
2218             {
2219                 pCard->sdcard.bSupportLowVolt = true;
2220                 AM_HAL_CARD_DEBUG("SD Card Support 1.8v Switching\r\n");
2221             }
2222             else
2223             {
2224                 pCard->sdcard.bSupportLowVolt = false;
2225                 AM_HAL_CARD_DEBUG("SD Card not support 1.8V, working at 3.3V signaling\r\n");
2226             }
2227 
2228             break;
2229         }
2230     }
2231 
2232     if ( !ui32Retries )
2233     {
2234         AM_HAL_CARD_DEBUG("SD Card send cmd55&cmd41 retry time out\r\n");
2235         return AM_HAL_CMD_ERR_TIMEOUT;
2236     }
2237 
2238     AM_HAL_CARD_DEBUG("SD Card send cmd55&cmd41 complete, card is ready\r\n");
2239 
2240     //
2241     // Init sd card working at 3.3V signaling
2242     //
2243     pCard->sdcard.ui32CurrentVolt = AM_HAL_SD_CARD_3_3_V;
2244 
2245     //
2246     // Get CID
2247     //
2248     if ( am_hal_sdmmc_cmd2_send_cid(pCard) != AM_HAL_CMD_ERR_NONE )
2249     {
2250         AM_HAL_CARD_DEBUG("SD Card CMD2 Failed\n");
2251         return AM_HAL_STATUS_FAIL;
2252     }
2253 
2254     //
2255     // Get RCA
2256     //
2257     if ( am_hal_sdmmc_cmd3_set_rca(pCard, 0) != AM_HAL_CMD_ERR_NONE )
2258     {
2259         AM_HAL_CARD_DEBUG("SD Card CMD3 Failed\n");
2260         return AM_HAL_STATUS_FAIL;
2261     }
2262 
2263     //
2264     // Get the card CSD
2265     //
2266     if ( am_hal_sdmmc_cmd9_send_csd(pCard) != AM_HAL_CMD_ERR_NONE )
2267     {
2268         AM_HAL_CARD_DEBUG("SD Card CMD9 Failed\n");
2269         return AM_HAL_STATUS_FAIL;
2270     }
2271 
2272     //
2273     // Select the card as Transfer state
2274     //
2275     if ( am_hal_sdmmc_cmd7_card_select(pCard) != AM_HAL_CMD_ERR_NONE )
2276     {
2277         AM_HAL_CARD_DEBUG("SD Card CMD7 Failed\n");
2278         return AM_HAL_STATUS_FAIL;
2279     }
2280 
2281     //
2282     // Get CSD version information from sd card SDSC is CSD1.0 SDHC and SDXC is CSD2.0
2283     //
2284     pCard->sdcard.ui32CsdVersion = am_hal_unstuff_bits(pCard->ui32CSD, 126, 2);
2285     if ( pCard->sdcard.ui32CsdVersion == 0)
2286     {
2287         pCard->eType = AM_HAL_CARD_TYPE_SDSC;
2288 
2289         pCard->sdcard.ui32CSizeMult = am_hal_unstuff_bits(pCard->ui32CSD, 47, 3);
2290         pCard->sdcard.ui32CSize = am_hal_unstuff_bits(pCard->ui32CSD, 62, 12);
2291         pCard->sdcard.ui32RdBlockLen = am_hal_unstuff_bits(pCard->ui32CSD, 80, 4);
2292 
2293         uint32_t ui32Mult = 1 << ( pCard->sdcard.ui32CSizeMult + 2 );
2294         uint32_t ui32BlockLen = 1 << pCard->sdcard.ui32RdBlockLen;
2295 
2296         //
2297         // CSD 1.0: Memory capacity = ( C_SIZE + 1 ) * ui32Mult * ui32BlockLen.
2298         //
2299         pCard->ui32MaxBlks = ( pCard->sdcard.ui32CSize + 1 ) * ui32Mult * ui32BlockLen / 512;
2300         pCard->ui32BlkSize = ui32BlockLen;
2301         AM_HAL_CARD_DEBUG("This is a SDSC Card\n");
2302     }
2303     else if ( pCard->sdcard.ui32CsdVersion == 1 )
2304     {
2305         pCard->sdcard.ui32CSize = am_hal_unstuff_bits(pCard->ui32CSD, 48, 22);
2306         uint32_t ui32ReadBlLen  = am_hal_unstuff_bits(pCard->ui32CSD, 80, 4);
2307 
2308         //
2309         // SDHC and SDXC block is 512 byte as spec requirement, ui32ReadBlLen is fixed to 9h.
2310         //
2311         pCard->ui32BlkSize = 1 << ui32ReadBlLen;
2312 
2313         //
2314         // CSD 2.0: Memory capacity = ( C_SIZE + 1 ) * 512K.
2315         //
2316         pCard->ui32MaxBlks = (pCard->sdcard.ui32CSize + 1) * 1024;
2317         if ( pCard->ui32MaxBlks <= SDHC_MAX_BLK_CNT )
2318         {
2319             pCard->eType = AM_HAL_CARD_TYPE_SDHC;
2320             AM_HAL_CARD_DEBUG("This is a SDHC Card\n");
2321         }
2322         else
2323         {
2324             pCard->eType = AM_HAL_CARD_TYPE_SDXC;
2325             AM_HAL_CARD_DEBUG("This is a SDXC Card\n");
2326         }
2327     }
2328     else
2329     {
2330         AM_HAL_CARD_DEBUG("Current driver don't support CSD is Version3.0 or Higher \n");
2331         return AM_HAL_STATUS_FAIL;
2332     }
2333 
2334     if ( pCard->sdcard.ui32CurrentVolt == AM_HAL_SD_CARD_3_3_V )
2335     {
2336         AM_HAL_CARD_DEBUG("SD Card sdcard.bHighSpeed   = 0x%x \n", pCard->sdcard.bHighSpeed);
2337         AM_HAL_CARD_DEBUG("SD Card sdcard.bWrProtect   = 0x%x \n", pCard->sdcard.bWrProtect);
2338     }
2339 
2340     AM_HAL_CARD_DEBUG("SD Card sdcard.ui32CurrentVolt  = 0x%x \n", pCard->sdcard.ui32CurrentVolt);
2341     AM_HAL_CARD_DEBUG("SD Card sdcard.ui32CSize  = 0x%x \n", pCard->sdcard.ui32CSize);
2342     if ( pCard->sdcard.ui32CsdVersion == 0)
2343     {
2344         AM_HAL_CARD_DEBUG("SD Card sdcard.ui32CSizeMult   = 0x%x \n", pCard->sdcard.ui32CSizeMult);
2345         AM_HAL_CARD_DEBUG("SD Card sdcard.ui32RdBlockLen = 0x%x \n", pCard->sdcard.ui32RdBlockLen);
2346     }
2347 
2348     //
2349     // Always enable the cache if it's supported
2350     //
2351     ui32RetVal = am_hal_card_cache_on(pCard);
2352     if ( AM_HAL_STATUS_SUCCESS != ui32RetVal )
2353     {
2354         AM_HAL_CARD_DEBUG("\r\am_hal_card_cache_on - status %x\r\n", ui32RetVal);
2355     }
2356 
2357     AM_HAL_CARD_DEBUG("SD Card initialize is done\n");
2358 
2359     return AM_HAL_STATUS_SUCCESS;
2360 }
2361 
2362 static uint32_t
am_hal_card_sdio_init(am_hal_card_t * pCard)2363 am_hal_card_sdio_init(am_hal_card_t *pCard)
2364 {
2365     uint32_t ui32OCR = 0;
2366 
2367     //
2368     // Send CMD5 again
2369     //
2370     ui32OCR = pCard->ui32OCR;
2371     if ( am_hal_sdio_cmd5_io_send_op_cond(pCard, ui32OCR) != AM_HAL_CMD_ERR_NONE )
2372     {
2373         AM_HAL_CARD_DEBUG("SDIO Second CMD5 Error\n");
2374         return AM_HAL_STATUS_FAIL;
2375     }
2376 
2377     //
2378     // Send CMD3
2379     //
2380     if ( am_hal_sdmmc_cmd3_set_rca(pCard, 0) != AM_HAL_CMD_ERR_NONE )
2381     {
2382         AM_HAL_CARD_DEBUG("SDIO CMD3 Error\n");
2383         return AM_HAL_STATUS_FAIL;
2384     }
2385 
2386     //
2387     // Select the card
2388     //
2389     if ( am_hal_sdmmc_cmd7_card_select(pCard) != AM_HAL_CMD_ERR_NONE )
2390     {
2391         AM_HAL_CARD_DEBUG("SDIO CMD7 Error\n");
2392         return AM_HAL_STATUS_FAIL;
2393     }
2394 
2395     //
2396     // Read CCCR
2397     //
2398     if ( am_hal_sdio_card_read_cccr(pCard) != AM_HAL_CMD_ERR_NONE )
2399     {
2400         AM_HAL_CARD_DEBUG("SDIO read CCCR Failed\n");
2401         return AM_HAL_STATUS_FAIL;
2402     }
2403 
2404     //
2405     // Read CIS
2406     //
2407     if ( am_hal_sdio_card_read_cis(pCard) != AM_HAL_CMD_ERR_NONE )
2408     {
2409         AM_HAL_CARD_DEBUG("SDIO read CIS Failed\n");
2410         return AM_HAL_STATUS_FAIL;
2411     }
2412 
2413     return AM_HAL_STATUS_SUCCESS;
2414 }
2415 
2416 static uint32_t
am_hal_card_sd_init(am_hal_card_t * pCard)2417 am_hal_card_sd_init(am_hal_card_t *pCard)
2418 {
2419     AM_HAL_CARD_DEBUG("card type %d is not supported yet\n", pCard->eType);
2420     return AM_HAL_STATUS_FAIL;
2421 }
2422 
2423 static uint32_t
am_hal_card_type_detect(am_hal_card_t * pCard)2424 am_hal_card_type_detect(am_hal_card_t *pCard)
2425 {
2426     uint32_t ui32RetVal = AM_HAL_STATUS_SUCCESS;
2427 
2428     //
2429     // Wait about 74 cycles after powered on
2430     //
2431     am_util_delay_us(200);
2432 
2433     //
2434     // Reset the card
2435     //
2436     if ( am_hal_sdmmc_cmd0_go_idle(pCard) != AM_HAL_CMD_ERR_NONE )
2437     {
2438         AM_HAL_CARD_DEBUG("CMD0 Failed\n");
2439         return AM_HAL_STATUS_FAIL;
2440     }
2441 
2442     //
2443     // Send CMD8 for interface condition.
2444     //
2445     uint32_t ui32OCR = SD_CARD_CHECK_PATTERN | SD_CARD_2P7_3P6_VOLTAGE_SUPPLY;
2446     ui32RetVal = am_hal_sdio_cmd8_send_if_cond(pCard, ui32OCR);
2447     if ( ui32RetVal == AM_HAL_CMD_ERR_NONE )
2448     {
2449             AM_HAL_CARD_DEBUG("Detected SD Card device\n");
2450             pCard->eType = AM_HAL_CARD_TYPE_SDHC;
2451             return AM_HAL_STATUS_SUCCESS;
2452     }
2453 
2454     //
2455     //  Check for SDIO/MMC Cards
2456     //
2457     ui32OCR = 0;
2458     ui32RetVal = am_hal_sdmmc_cmd1_send_op_cond(pCard);
2459     if ( ui32RetVal == AM_HAL_CMD_ERR_NONE )
2460     {
2461         AM_HAL_CARD_DEBUG("Detected MMC device\n");
2462         pCard->eType = AM_HAL_CARD_TYPE_EMMC;
2463     }
2464     else
2465     {
2466         ui32RetVal = am_hal_sdio_cmd5_io_send_op_cond(pCard, ui32OCR);
2467         if ( ui32RetVal == AM_HAL_CMD_ERR_NONE )
2468         {
2469             AM_HAL_CARD_DEBUG("Detected SDIO Card device\n");
2470             pCard->eType = AM_HAL_CARD_TYPE_SDIO;
2471         }
2472         else
2473         {
2474             AM_HAL_CARD_DEBUG("NO Device Found...\n");
2475             return AM_HAL_STATUS_FAIL;
2476         }
2477     }
2478 
2479     return AM_HAL_STATUS_SUCCESS;
2480 }
2481 
2482 static uint32_t
am_hal_card_set_bus_width(am_hal_card_t * pCard,am_hal_host_bus_width_e eBusWidth)2483 am_hal_card_set_bus_width(am_hal_card_t *pCard, am_hal_host_bus_width_e eBusWidth)
2484 {
2485     uint32_t ui32Mode;
2486     uint32_t ui32Status;
2487 
2488     am_hal_card_host_t *pHost;
2489 
2490 #ifndef AM_HAL_DISABLE_API_VALIDATION
2491 
2492     if ( !pCard || !pCard->pHost )
2493     {
2494         return AM_HAL_STATUS_INVALID_ARG;
2495     }
2496 
2497 #endif // AM_HAL_DISABLE_API_VALIDATION
2498 
2499     pHost = pCard->pHost;
2500     ui32Mode = 0x0;
2501     if ( eBusWidth != pHost->eBusWidth || pHost->eUHSMode != pCard->cfg.eUHSMode)
2502     {
2503         switch ( eBusWidth )
2504         {
2505             case AM_HAL_HOST_BUS_WIDTH_1:
2506                 //
2507                 // 3 << 24 | 183 << 16 | 0 << 8
2508                 // 0x03b70000
2509                 //
2510                 ui32Mode = MMC_EXT_MODE_WRITE_BYTE | MMC_EXT_REGS_BUS_WIDTH | MMC_EXT_SET_BUS_WIDTH1;
2511                 break;
2512             case AM_HAL_HOST_BUS_WIDTH_4:
2513                 //
2514                 // 3 << 24 | 183 << 16 | 1 << 8
2515                 // 0x03b70100
2516                 //
2517                 if (pCard->cfg.eUHSMode == AM_HAL_HOST_UHS_DDR50)
2518                 {
2519                     ui32Mode = MMC_EXT_MODE_WRITE_BYTE | MMC_EXT_REGS_BUS_WIDTH | MMC_EXT_SET_BUS_WIDTH4_DDR;
2520                 }
2521                 else
2522                 {
2523                     ui32Mode = MMC_EXT_MODE_WRITE_BYTE | MMC_EXT_REGS_BUS_WIDTH | MMC_EXT_SET_BUS_WIDTH4;
2524                 }
2525                 break;
2526             case AM_HAL_HOST_BUS_WIDTH_8:
2527                 //
2528                 // 3 << 24 | 183 << 16 | 2 << 8
2529                 // 0x03b70200
2530                 //
2531                 if (pCard->cfg.eUHSMode == AM_HAL_HOST_UHS_DDR50)
2532                 {
2533                     ui32Mode = MMC_EXT_MODE_WRITE_BYTE | MMC_EXT_REGS_BUS_WIDTH | MMC_EXT_SET_BUS_WIDTH8_DDR;
2534                 }
2535                 else
2536                 {
2537                     ui32Mode = MMC_EXT_MODE_WRITE_BYTE | MMC_EXT_REGS_BUS_WIDTH | MMC_EXT_SET_BUS_WIDTH8;
2538                 }
2539                 break;
2540         }
2541 
2542         if ( (ui32Status = am_hal_card_mode_switch(pCard, ui32Mode, DEFAULT_CMD6_TIMEOUT_MS)) != AM_HAL_STATUS_SUCCESS )
2543         {
2544             return ui32Status;
2545         }
2546 
2547         if ( pHost->ops->set_bus_width(pHost->pHandle, eBusWidth) != AM_HAL_STATUS_SUCCESS )
2548         {
2549             return AM_HAL_STATUS_FAIL;
2550         }
2551     }
2552 
2553     return AM_HAL_STATUS_SUCCESS;
2554 }
2555 
2556 static uint32_t
am_hal_card_set_uhs_mode(am_hal_card_t * pCard,am_hal_host_uhs_mode_e eUHSMode)2557 am_hal_card_set_uhs_mode(am_hal_card_t *pCard, am_hal_host_uhs_mode_e eUHSMode)
2558 {
2559     am_hal_card_host_t *pHost;
2560 
2561 #ifndef AM_HAL_DISABLE_API_VALIDATION
2562     if ( !pCard || !pCard->pHost )
2563     {
2564         return AM_HAL_STATUS_INVALID_ARG;
2565     }
2566 #endif // AM_HAL_DISABLE_API_VALIDATION
2567 
2568     pHost = pCard->pHost;
2569 
2570     //
2571     // Already in this UHS mode
2572     //
2573     if ( pHost->eUHSMode == eUHSMode )
2574     {
2575         return AM_HAL_STATUS_SUCCESS;
2576     }
2577 
2578     if ( eUHSMode == AM_HAL_HOST_UHS_DDR50 )
2579     {
2580         if ( pCard->eType == AM_HAL_CARD_TYPE_EMMC ||
2581             pCard->eType == AM_HAL_CARD_TYPE_MMC  ||
2582             pCard->eType == AM_HAL_CARD_TYPE_SDSC ||
2583             pCard->eType == AM_HAL_CARD_TYPE_SDHC ||
2584             pCard->eType == AM_HAL_CARD_TYPE_SDXC )
2585         {
2586             //
2587             // Card does not support DDR52 mode
2588             //
2589             if ( pCard->eType == AM_HAL_CARD_TYPE_EMMC || pCard->eType == AM_HAL_CARD_TYPE_MMC )
2590             {
2591                 if ( (pCard->ui8DeviceType & HS_DDR_52MHZ_18_3V) == 0x0 )
2592                 {
2593                     return AM_HAL_STATUS_FAIL;
2594                 }
2595             }
2596             else
2597             {
2598                 if ( pCard->sdcard.bSupportDDR50 == false)
2599                 {
2600                     return AM_HAL_STATUS_FAIL;
2601                 }
2602             }
2603 
2604             if (pHost->ops->set_uhs_mode)
2605             {
2606                 return pHost->ops->set_uhs_mode(pHost->pHandle, eUHSMode);
2607             }
2608         }
2609         else
2610         {
2611             if (pHost->ops->set_uhs_mode)
2612             {
2613                 return pHost->ops->set_uhs_mode(pHost->pHandle, eUHSMode);
2614             }
2615         }
2616     }
2617     else
2618     {
2619         if (pHost->ops->set_uhs_mode)
2620         {
2621             return pHost->ops->set_uhs_mode(pHost->pHandle, AM_HAL_HOST_UHS_NONE);
2622         }
2623     }
2624 
2625     return AM_HAL_STATUS_SUCCESS;
2626 }
2627 
2628 static uint32_t
am_hal_card_set_voltage(am_hal_card_t * pCard,am_hal_host_bus_voltage_e eBusVoltage)2629 am_hal_card_set_voltage(am_hal_card_t *pCard, am_hal_host_bus_voltage_e eBusVoltage)
2630 {
2631     am_hal_card_host_t *pHost;
2632 
2633 #ifndef AM_HAL_DISABLE_API_VALIDATION
2634 
2635     if ( !pCard || !pCard->pHost )
2636     {
2637         return AM_HAL_STATUS_INVALID_ARG;
2638     }
2639 
2640 #endif // AM_HAL_DISABLE_API_VALIDATION
2641 
2642     pHost = pCard->pHost;
2643 
2644     if ( eBusVoltage != pHost->eBusVoltage )
2645     {
2646         if ( pHost->ops->set_bus_voltage(pHost->pHandle, eBusVoltage) != AM_HAL_STATUS_SUCCESS )
2647         {
2648             return AM_HAL_STATUS_FAIL;
2649         }
2650     }
2651 
2652     return AM_HAL_STATUS_SUCCESS;
2653 }
2654 
2655 static uint32_t
am_hal_card_set_speed(am_hal_card_t * pCard,uint32_t ui32Clock)2656 am_hal_card_set_speed(am_hal_card_t *pCard, uint32_t ui32Clock)
2657 {
2658     uint32_t ui32Status;
2659     uint32_t ui32Mode;
2660     uint32_t ui32HSMode = 1;
2661     am_hal_card_host_t *pHost;
2662 
2663 #ifndef AM_HAL_DISABLE_API_VALIDATION
2664 
2665     if ( !pCard || !pCard->pHost )
2666     {
2667         return AM_HAL_STATUS_INVALID_ARG;
2668     }
2669 
2670 #endif // AM_HAL_DISABLE_API_VALIDATION
2671 
2672     pHost = pCard->pHost;
2673 
2674     if ((pCard->cfg.eUHSMode == AM_HAL_HOST_UHS_SDR104) &&
2675         (ui32Clock > MMC_HS_MAX_SPEED_LIMIT) &&
2676         (ui32Clock <= MMC_HS200_MAX_SPEED_LIMIT))
2677     {
2678         ui32HSMode = 2;
2679     }
2680 
2681     if ( (pCard->ui8SpecVer >= 4) && (ui32Clock >= MMC_LEGACY_HS) )
2682     {
2683         //
2684         // Already in the high speed mode
2685         //
2686         if ( am_hal_unstuff_bytes(pCard->ui32ExtCSD, 185, 1) != ui32HSMode )
2687         {
2688             //
2689             // 0x03B90100
2690             //
2691             ui32Mode = MMC_EXT_MODE_WRITE_BYTE | MMC_EXT_REGS_HIGH_SPEED | (ui32HSMode << 8);
2692             if ( (ui32Status = am_hal_card_mode_switch(pCard, ui32Mode, DEFAULT_CMD6_TIMEOUT_MS)) != AM_HAL_STATUS_SUCCESS )
2693             {
2694                 return ui32Status;
2695             }
2696 
2697             //
2698             // read back the ext_csd and check 'HS_TIMING' is set or not
2699             //
2700             if ( am_hal_sdmmc_cmd8_send_ext_csd(pCard) != AM_HAL_CMD_ERR_NONE )
2701             {
2702                 return AM_HAL_STATUS_FAIL;
2703             }
2704 
2705             if ( am_hal_unstuff_bytes(pCard->ui32ExtCSD, 185, 1) != ui32HSMode )
2706             {
2707                 AM_HAL_CARD_DEBUG("%d - Failed to switch to high speed mode\n", __FUNCTION__);
2708                 return AM_HAL_STATUS_FAIL;
2709             }
2710         }
2711     }
2712 
2713     if ( pHost->ops->set_bus_clock(pHost->pHandle, ui32Clock) != AM_HAL_STATUS_SUCCESS )
2714     {
2715         return AM_HAL_STATUS_FAIL;
2716     }
2717 
2718     return AM_HAL_STATUS_SUCCESS;
2719 }
2720 
2721 //
2722 // Static helper function:
2723 //  Count the longest consecutive 1s in a 32bit word
2724 //
2725 static uint32_t
count_consecutive_ones(uint32_t * pVal)2726 count_consecutive_ones(uint32_t* pVal)
2727 {
2728     uint32_t count = 0;
2729     uint32_t data = *pVal;
2730 
2731     while ( data )
2732     {
2733         data = (data & (data << 1));
2734         count++;
2735     }
2736     return count;
2737 }
2738 
2739 //
2740 // Static helper function:
2741 //  Find and return the mid point of the longest continuous 1s in a 32bit word
2742 //
2743 static uint32_t
find_mid_point(uint32_t * pVal)2744 find_mid_point(uint32_t* pVal)
2745 {
2746     uint32_t pattern_len = 0;
2747     uint32_t max_len = 0;
2748     uint32_t pick_point = 0;
2749     bool pattern_start = false;
2750     uint32_t val = *pVal;
2751     uint8_t remainder = 0;
2752     bool pick_point_flag = false;
2753 
2754     for ( uint32_t i = 0; i < 32; i++ )
2755     {
2756         if ( val & (0x01 << i) )
2757         {
2758             pattern_start = true;
2759             pattern_len++;
2760         }
2761         else
2762         {
2763             if ( pattern_start == true )
2764             {
2765                 pattern_start = false;
2766                 pick_point_flag = true;
2767             }
2768         }
2769         if ( (i == 31) && ( pattern_start == true ) )
2770         {
2771             pick_point_flag = true;
2772         }
2773 
2774         if ( pick_point_flag == true )
2775         {
2776             if ( pattern_len > max_len )
2777             {
2778                 max_len = pattern_len;
2779                 pick_point = i - 1 - pattern_len / 2;
2780                 remainder = pattern_len % 2;
2781             }
2782             pattern_len = 0;
2783             pick_point_flag = false;
2784         }
2785     }
2786 
2787     //
2788     // check the passing window side
2789     //
2790     if ( (pick_point < 16) && (val & 0x00000002) )
2791     {
2792         // window is likely on low side
2793         pick_point = pick_point - remainder;    // minus only when pattern length is odd
2794     }
2795     else if ( (pick_point > 15) && (val & 0x40000000) )
2796     {
2797         // window is likely on high side
2798         pick_point = pick_point + 1;
2799     }
2800     else
2801     {
2802         // window is in the middle, no action
2803     }
2804     return pick_point;
2805 }
2806 
2807 uint32_t
am_hal_card_emmc_calibrate(am_hal_host_uhs_mode_e eUHSMode,uint32_t ui32Clock,am_hal_host_bus_width_e eBusWidth,uint8_t * ui8CalibBuf,uint32_t ui32StartBlk,uint32_t ui32BlkCnt,uint8_t ui8TxRxDelays[2])2808 am_hal_card_emmc_calibrate(am_hal_host_uhs_mode_e eUHSMode,
2809                            uint32_t ui32Clock,
2810                            am_hal_host_bus_width_e eBusWidth,
2811                            uint8_t *ui8CalibBuf,
2812                            uint32_t ui32StartBlk,
2813                            uint32_t ui32BlkCnt,
2814                            uint8_t ui8TxRxDelays[2])
2815 {
2816     am_hal_card_t eMMCard;
2817     am_hal_card_host_t *pSdhcCardHost;
2818 
2819     uint32_t i;
2820     uint32_t len = ui32BlkCnt*512;
2821     uint8_t  ui8TxDelay = 0;
2822     uint8_t  ui8RxDelay = 0;
2823     uint32_t ui32TxResult = 0;
2824     uint32_t ui32RxResultArray[16] = {0};
2825 
2826 #ifdef AM_DEBUG_PRINTF
2827     if (eUHSMode == AM_HAL_HOST_UHS_DDR50)
2828     {
2829         AM_HAL_CARD_DEBUG("eMMC Timing Scan for DDR %d Hz %d bit mode...\n", ui32Clock, eBusWidth);
2830     }
2831     else
2832     {
2833         AM_HAL_CARD_DEBUG("eMMC Timing Scan for SDR %d Hz %d bit mode...\n", ui32Clock, eBusWidth);
2834     }
2835 #endif
2836 
2837     for (int j = 0; j < SDIO_SCAN_TXDELAY_MAX; j++)
2838     {
2839         for (int k = 0; k < SDIO_SCAN_RXDELAY_MAX; k++)
2840         {
2841             //
2842             // Get the uderlying SDHC card host instance
2843             //
2844             pSdhcCardHost = am_hal_get_card_host(AM_HAL_SDHC_CARD_HOST, true);
2845 
2846             if (pSdhcCardHost == NULL)
2847             {
2848                 AM_HAL_CARD_DEBUG("No such card host and stop\n");
2849                 return AM_HAL_STATUS_FAIL;
2850             }
2851 
2852             ui8TxRxDelays[0] = j;
2853             ui8TxRxDelays[1] = k;
2854             AM_HAL_CARD_DEBUG("Test TX delay setting SDIOOTAPDLYSEL = %d, RX delay setting SDIOITAPDLYSEL = %d\n", j, k);
2855             am_hal_card_host_set_txrx_delay(pSdhcCardHost, ui8TxRxDelays);
2856 
2857             //
2858             // check if card is present
2859             //
2860             if (am_hal_card_host_find_card(pSdhcCardHost, &eMMCard) != AM_HAL_STATUS_SUCCESS)
2861             {
2862                 AM_HAL_CARD_DEBUG("No card is present now\n");
2863                 return AM_HAL_STATUS_FAIL;
2864             }
2865 
2866             if (am_hal_card_init(&eMMCard, NULL, AM_HAL_CARD_PWR_CTRL_NONE) != AM_HAL_STATUS_SUCCESS)
2867             {
2868                 AM_HAL_CARD_DEBUG("card initialization failed\n");
2869                 return AM_HAL_STATUS_FAIL;
2870             }
2871 
2872             if (am_hal_card_cfg_set(&eMMCard, AM_HAL_CARD_TYPE_EMMC,
2873                 eBusWidth, ui32Clock, AM_HAL_HOST_BUS_VOLTAGE_1_8,
2874                 eUHSMode) != AM_HAL_STATUS_SUCCESS)
2875             {
2876                 AM_HAL_CARD_DEBUG("card config failed\n");
2877                 continue;
2878             }
2879 
2880             for (i = 0; i < len; i++)
2881             {
2882                 ui8CalibBuf[i] = i % 256;
2883             }
2884 
2885             am_hal_card_block_write_sync(&eMMCard, ui32StartBlk, ui32BlkCnt, (uint8_t *)ui8CalibBuf);
2886 
2887             memset((void *)ui8CalibBuf, 0x0, len);
2888             am_hal_card_block_read_sync(&eMMCard, ui32StartBlk, ui32BlkCnt, (uint8_t *)ui8CalibBuf);
2889 
2890             for (i = 0; i < len; i++)
2891             {
2892                 if (ui8CalibBuf[i] != i % 256)
2893                 {
2894                     break;
2895                 }
2896             }
2897 
2898             if (i == len)
2899             {
2900                 ui32RxResultArray[j] |= 0x01 << k;
2901                 AM_HAL_CARD_DEBUG("TX Delay SDIOOTAPDLYSEL = %d, RX Delay SDIOITAPDLYSEL = %d works\n", j, k);
2902             }
2903             else
2904             {
2905                 AM_HAL_CARD_DEBUG("TX Delay SDIOOTAPDLYSEL = %d, RX Delay SDIOITAPDLYSEL = %d doesn't work\n", j, k);
2906             }
2907         }
2908     }
2909 
2910 #ifdef AM_DEBUG_PRINTF
2911     AM_HAL_CARD_DEBUG("\nSDIO TX RX Delay Scan Result:\n");
2912     for (i = 0; i < 16; i++ )
2913     {
2914         AM_HAL_CARD_DEBUG("TX_Delay = %2d, RX_Delay Window = 0x%08X\n", i, ui32RxResultArray[i]);
2915     }
2916 #endif
2917 
2918     uint32_t ui32Result = 0;
2919     for (i = 0; i < SDIO_SCAN_TXDELAY_MAX; i++ )
2920     {
2921         ui32Result = count_consecutive_ones(&ui32RxResultArray[i]);
2922         if ( ui32Result >= SDIO_TIMING_SCAN_MIN_ACCEPTANCE_LENGTH )
2923         {
2924             ui32TxResult |= 0x01 << i;
2925         }
2926     }
2927 
2928     //
2929     // Check consecutive passing settings
2930     //
2931     if ( ui32TxResult == 0 )
2932     {
2933         //
2934         // No acceptable window
2935         //
2936         return AM_HAL_STATUS_FAIL;
2937     }
2938     else
2939     {
2940         ui32Result = count_consecutive_ones(&ui32TxResult);
2941         if ( ui32Result < SDIO_TIMING_SCAN_MIN_ACCEPTANCE_LENGTH )
2942         {
2943             //
2944             // No acceptable window
2945             //
2946             return AM_HAL_STATUS_FAIL;
2947         }
2948     }
2949 
2950     //
2951     // Find TX Delay Value
2952     //
2953     ui8TxDelay = find_mid_point(&ui32TxResult);
2954 
2955     AM_HAL_CARD_DEBUG("\nSDIO Timing Scan found a RX delay window %X with TX delay Setting = %d.\n", ui32RxResultArray[ui8TxDelay], ui8TxDelay);
2956 
2957     //
2958     // Find RX Delay Value
2959     //
2960     ui8RxDelay = find_mid_point(&ui32RxResultArray[ui8TxDelay]);
2961     ui8TxRxDelays[0] = ui8TxDelay;
2962     ui8TxRxDelays[1] = ui8RxDelay;
2963 
2964     AM_HAL_CARD_DEBUG("Timing Scan set the SDIO TX delay to %d and RX delay to %d.\n", ui8TxDelay, ui8RxDelay);
2965 
2966     //
2967     // Force the card host to reset with the calibration settings
2968     //
2969     pSdhcCardHost = am_hal_get_card_host(AM_HAL_SDHC_CARD_HOST, true);
2970 
2971     if (pSdhcCardHost == NULL)
2972     {
2973         AM_HAL_CARD_DEBUG("No such card host and stop\n");
2974         return AM_HAL_STATUS_FAIL;
2975     }
2976     am_hal_card_host_set_txrx_delay(pSdhcCardHost, ui8TxRxDelays);
2977 
2978     return AM_HAL_STATUS_SUCCESS;
2979 }
2980 
2981 uint32_t
am_hal_sd_card_calibrate(am_hal_host_uhs_mode_e eUHSMode,uint32_t ui32Clock,am_hal_host_bus_width_e eBusWidth,uint8_t * ui8CalibBuf,uint32_t ui32StartBlk,uint32_t ui32BlkCnt,uint8_t ui8TxRxDelays[2],am_hal_card_pwr_ctrl_func pCardPwrCtrlFunc)2982 am_hal_sd_card_calibrate(am_hal_host_uhs_mode_e eUHSMode,
2983                          uint32_t ui32Clock,
2984                          am_hal_host_bus_width_e eBusWidth,
2985                          uint8_t *ui8CalibBuf,
2986                          uint32_t ui32StartBlk,
2987                          uint32_t ui32BlkCnt,
2988                          uint8_t ui8TxRxDelays[2],
2989                          am_hal_card_pwr_ctrl_func pCardPwrCtrlFunc)
2990 {
2991     am_hal_card_t SdCard;
2992     am_hal_card_host_t *pSdhcCardHost;
2993 
2994     uint32_t i;
2995     uint32_t len = ui32BlkCnt*512;
2996     uint8_t  ui8TxDelay = 0;
2997     uint8_t  ui8RxDelay = 0;
2998     uint32_t ui32TxResult = 0;
2999     uint32_t ui32RxResultArray[16] = {0};
3000     uint32_t ui32RxIndexEnd = SDIO_SCAN_RXDELAY_MAX;
3001 
3002 #ifdef AM_DEBUG_PRINTF
3003     if (eUHSMode == AM_HAL_HOST_UHS_DDR50)
3004     {
3005         AM_HAL_CARD_DEBUG("SD Card Timing Scan for DDR %d Hz %d bit mode...\n", ui32Clock, eBusWidth);
3006     }
3007     else
3008     {
3009         AM_HAL_CARD_DEBUG("SD Card Timing Scan for SDR %d Hz %d bit mode...\n", ui32Clock, eBusWidth);
3010     }
3011 #endif
3012 
3013     if ( eUHSMode == AM_HAL_HOST_UHS_SDR104 )
3014     {
3015         ui32RxIndexEnd = 15;
3016     }
3017 
3018     for (int j = 0; j < SDIO_SCAN_TXDELAY_MAX; j++)
3019     {
3020         for (int k = 0; k < ui32RxIndexEnd; k++)
3021         {
3022             //
3023             // Get the uderlying SDHC card host instance
3024             //
3025             pSdhcCardHost = am_hal_get_card_host(AM_HAL_SDHC_CARD_HOST, true);
3026 
3027             if (pSdhcCardHost == NULL)
3028             {
3029                 AM_HAL_CARD_DEBUG("No such card host and stop\n");
3030                 return AM_HAL_STATUS_FAIL;
3031             }
3032 
3033             ui8TxRxDelays[0] = j;
3034             ui8TxRxDelays[1] = k;
3035             AM_HAL_CARD_DEBUG("Test TX delay setting SDIOOTAPDLYSEL = %d, RX delay setting SDIOITAPDLYSEL = %d\n", j, k);
3036             am_hal_card_host_set_txrx_delay(pSdhcCardHost, ui8TxRxDelays);
3037 
3038             //
3039             // check if card is present
3040             //
3041             if (am_hal_card_host_find_card(pSdhcCardHost, &SdCard) != AM_HAL_STATUS_SUCCESS)
3042             {
3043                 AM_HAL_CARD_DEBUG("No card is present now\n");
3044                 return AM_HAL_STATUS_FAIL;
3045             }
3046 
3047             if (am_hal_card_init(&SdCard, pCardPwrCtrlFunc, AM_HAL_CARD_PWR_CTRL_NONE) != AM_HAL_STATUS_SUCCESS)
3048             {
3049                 AM_HAL_CARD_DEBUG("card initialization failed\n");
3050                 return AM_HAL_STATUS_FAIL;
3051             }
3052 
3053             if (am_hal_card_cfg_set(&SdCard, AM_HAL_CARD_TYPE_SDHC,
3054                 eBusWidth, ui32Clock, AM_HAL_HOST_BUS_VOLTAGE_1_8,
3055                 eUHSMode) != AM_HAL_STATUS_SUCCESS)
3056             {
3057                 AM_HAL_CARD_DEBUG("card config failed\n");
3058                 continue;
3059             }
3060 
3061             for (i = 0; i < len; i++)
3062             {
3063                 ui8CalibBuf[i] = i % 256;
3064             }
3065 
3066             am_hal_sd_card_block_write_sync(&SdCard, ui32StartBlk, ui32BlkCnt, (uint8_t *)ui8CalibBuf);
3067             memset((void *)ui8CalibBuf, 0x0, len);
3068             am_hal_sd_card_block_read_sync(&SdCard, ui32StartBlk, ui32BlkCnt, (uint8_t *)ui8CalibBuf);
3069 
3070             for (i = 0; i < len; i++)
3071             {
3072                 if (ui8CalibBuf[i] != i % 256)
3073                 {
3074                     break;
3075                 }
3076             }
3077 
3078             if (i == len)
3079             {
3080                 ui32RxResultArray[j] |= 0x01 << k;
3081                 AM_HAL_CARD_DEBUG("TX Delay SDIOOTAPDLYSEL = %d, RX Delay SDIOITAPDLYSEL = %d works\n", j, k);
3082             }
3083             else
3084             {
3085                 AM_HAL_CARD_DEBUG("TX Delay SDIOOTAPDLYSEL = %d, RX Delay SDIOITAPDLYSEL = %d doesn't work\n", j, k);
3086             }
3087         }
3088     }
3089 
3090 #ifdef AM_DEBUG_PRINTF
3091     AM_HAL_CARD_DEBUG("\nSDIO TX RX Delay Scan Result:\n");
3092     for (i = 0; i < 16; i++ )
3093     {
3094         AM_HAL_CARD_DEBUG("TX_Delay = %2d, RX_Delay Window = 0x%08X\n", i, ui32RxResultArray[i]);
3095     }
3096 #endif
3097 
3098     uint32_t ui32Result = 0;
3099     for (i = 0; i < SDIO_SCAN_TXDELAY_MAX; i++ )
3100     {
3101         ui32Result = count_consecutive_ones(&ui32RxResultArray[i]);
3102         if ( ui32Result >= SDIO_TIMING_SCAN_MIN_ACCEPTANCE_LENGTH )
3103         {
3104             ui32TxResult |= 0x01 << i;
3105         }
3106     }
3107 
3108     //
3109     // Check consecutive passing settings
3110     //
3111     if ( ui32TxResult == 0 )
3112     {
3113         //
3114         // No acceptable window
3115         //
3116         return AM_HAL_STATUS_FAIL;
3117     }
3118     else
3119     {
3120         ui32Result = count_consecutive_ones(&ui32TxResult);
3121         if ( ui32Result < SDIO_TIMING_SCAN_MIN_ACCEPTANCE_LENGTH )
3122         {
3123             //
3124             // No acceptable window
3125             //
3126             return AM_HAL_STATUS_FAIL;
3127         }
3128     }
3129 
3130     //
3131     // Find TX Delay Value
3132     //
3133     ui8TxDelay = find_mid_point(&ui32TxResult);
3134 
3135     AM_HAL_CARD_DEBUG("\nSDIO Timing Scan found a RX delay window %X with TX delay Setting = %d.\n", ui32RxResultArray[ui8TxDelay], ui8TxDelay);
3136 
3137     //
3138     // Find RX Delay Value
3139     //
3140     ui8RxDelay = find_mid_point(&ui32RxResultArray[ui8TxDelay]);
3141     ui8TxRxDelays[0] = ui8TxDelay;
3142     ui8TxRxDelays[1] = ui8RxDelay;
3143 
3144     AM_HAL_CARD_DEBUG("Timing Scan set the SDIO TX delay to %d and RX delay to %d.\n", ui8TxDelay, ui8RxDelay);
3145 
3146     am_hal_card_host_set_txrx_delay(pSdhcCardHost, ui8TxRxDelays);
3147 
3148     return AM_HAL_STATUS_SUCCESS;
3149 }
3150 
3151 //
3152 // Public functions
3153 //
3154 
3155 //*****************************************************************************
3156 //
3157 // Power off the SDHC or eMMC CARD
3158 //
3159 //*****************************************************************************
3160 uint32_t
am_hal_card_pwrctrl_sleep(am_hal_card_t * pCard)3161 am_hal_card_pwrctrl_sleep(am_hal_card_t *pCard)
3162 {
3163     am_hal_card_host_t *pHost;
3164     uint32_t ui32Status = AM_HAL_STATUS_SUCCESS;
3165 
3166 #ifndef AM_HAL_DISABLE_API_VALIDATION
3167     if ( !pCard || !pCard->pHost )
3168     {
3169         return AM_HAL_STATUS_INVALID_ARG;
3170     }
3171 #endif // AM_HAL_DISABLE_API_VALIDATION
3172 
3173     pHost = pCard->pHost;
3174 
3175     switch (pCard->eCardPwrCtrlPolicy)
3176     {
3177         case AM_HAL_CARD_PWR_CTRL_SDHC_AND_CARD_OFF:
3178             //
3179             // Flush the cache before power off the eMMC card
3180             //
3181             if ( (ui32Status = am_hal_card_cache_off(pCard)) != AM_HAL_STATUS_SUCCESS )
3182             {
3183                 AM_HAL_CARD_DEBUG("sdhc & card power off - am_hal_card_cache_off Failed\n");
3184                 return ui32Status;
3185             }
3186 
3187             //
3188             // Host is going to power off the device
3189             //
3190             if ((ui32Status = am_hal_card_pwr_notification(pCard, MMC_EXT_CSD_POWER_OFF_LONG)) != AM_HAL_STATUS_SUCCESS)
3191             {
3192                 AM_HAL_CARD_DEBUG("sdhc & card power off - am_hal_card_cache_off Failed\n");
3193                 return ui32Status;
3194             }
3195 
3196             //
3197             // Deselect card
3198             //
3199             if ((ui32Status = am_hal_sdmmc_cmd7_card_deselect(pCard)) != AM_HAL_STATUS_SUCCESS)
3200             {
3201                 AM_HAL_CARD_DEBUG("sdhc & card sleep - Failed to deselect the card\n");
3202                 return AM_HAL_STATUS_FAIL;
3203             }
3204 
3205             //
3206             // Goto Sleep state before power off the card
3207             //
3208             if ( AM_HAL_CMD_ERR_NONE != am_hal_sdmmc_cmd5(pCard, true) )
3209             {
3210                 AM_HAL_CARD_DEBUG("sdhc & card sleep - am_hal_sdmmc_cmd5 Failed\n");
3211                 return AM_HAL_STATUS_FAIL;
3212             }
3213 
3214             //
3215             // Call User Set Callback Function for Power Control
3216             //
3217             if (pCard->pCardPwrCtrlFunc)
3218             {
3219                 pCard->pCardPwrCtrlFunc(AM_HAL_CARD_PWR_OFF);
3220             }
3221 
3222             pCard->eState = AM_HAL_CARD_STATE_PWROFF;
3223 
3224             if ((ui32Status = pHost->ops->deinit(pHost->pHandle)) != AM_HAL_STATUS_SUCCESS)
3225             {
3226                 AM_HAL_CARD_DEBUG("sdhc & card power off - host deinit failed\n");
3227                 return ui32Status;
3228             }
3229             break;
3230 
3231         case AM_HAL_CARD_PWR_CTRL_SDHC_OFF_AND_CARD_SLEEP:
3232 
3233             //
3234             // Flush the cache before power off the eMMC card
3235             //
3236             if ( (ui32Status = am_hal_card_cache_off(pCard)) != AM_HAL_STATUS_SUCCESS )
3237             {
3238                 AM_HAL_CARD_DEBUG("sdhc & card sleep - am_hal_card_cache_off Failed\n");
3239                 return ui32Status;
3240             }
3241 
3242             //
3243             // Host is going to put the device in Sleep Mode
3244             //
3245             if ( (ui32Status = am_hal_card_pwr_notification(pCard, MMC_EXT_CSD_SLEEP_NOTIFICATION)) != AM_HAL_STATUS_SUCCESS )
3246             {
3247                 AM_HAL_CARD_DEBUG("sdhc & card sleep - am_hal_card_pwr_notification Failed\n");
3248                 return ui32Status;
3249             }
3250 
3251             //
3252             // Deselect card
3253             //
3254             if ((ui32Status = am_hal_sdmmc_cmd7_card_deselect(pCard)) != AM_HAL_STATUS_SUCCESS)
3255             {
3256                 AM_HAL_CARD_DEBUG("sdhc & card sleep - Failed to deselect the card\n");
3257                 return AM_HAL_STATUS_FAIL;
3258             }
3259 
3260             //
3261             // Goto Sleep state
3262             //
3263             if ( AM_HAL_CMD_ERR_NONE != am_hal_sdmmc_cmd5(pCard, true) )
3264             {
3265                 AM_HAL_CARD_DEBUG("sdhc & card sleep - am_hal_sdmmc_cmd5 Failed\n");
3266                 return AM_HAL_STATUS_FAIL;
3267             }
3268 
3269             //
3270             // Power off the SDHC controller
3271             //
3272             if ((ui32Status = pHost->ops->pwr_ctrl(pHost->pHandle, false)) != AM_HAL_STATUS_SUCCESS)
3273             {
3274                 AM_HAL_CARD_DEBUG("sdhc & card sleep - emmc card power control failed\n");
3275                 return ui32Status;
3276             }
3277             break;
3278 
3279         case AM_HAL_CARD_PWR_CTRL_SDHC_OFF:
3280             //
3281             // Power off the SDHC controller
3282             //
3283             if ((ui32Status = pHost->ops->pwr_ctrl(pHost->pHandle, false)) != AM_HAL_STATUS_SUCCESS)
3284             {
3285                 AM_HAL_CARD_DEBUG("sdhc - emmc card power control failed\n");
3286                 return ui32Status;
3287             }
3288             break;
3289 
3290         default:
3291             break;
3292 
3293     }
3294 
3295     return AM_HAL_STATUS_SUCCESS;
3296 }
3297 
3298 //*****************************************************************************
3299 //
3300 // Power on the SDHC or eMMC CARD
3301 //
3302 //*****************************************************************************
3303 uint32_t
am_hal_card_pwrctrl_wakeup(am_hal_card_t * pCard)3304 am_hal_card_pwrctrl_wakeup(am_hal_card_t *pCard)
3305 {
3306     uint32_t ui32Status;
3307     am_hal_card_host_t *pHost;
3308 
3309 #ifndef AM_HAL_DISABLE_API_VALIDATION
3310     if ( !pCard || !pCard->pHost )
3311     {
3312         return AM_HAL_STATUS_INVALID_ARG;
3313     }
3314 #endif // AM_HAL_DISABLE_API_VALIDATION
3315 
3316     pHost = pCard->pHost;
3317 
3318     switch (pCard->eCardPwrCtrlPolicy)
3319     {
3320         case AM_HAL_CARD_PWR_CTRL_SDHC_AND_CARD_OFF:
3321             //
3322             // ReInit the SDHC controller
3323             //
3324             if ((ui32Status = pHost->ops->init(pHost)) != AM_HAL_STATUS_SUCCESS)
3325             {
3326                 AM_HAL_CARD_DEBUG("wakeup reinit sdhc controller failed\n");
3327                 return ui32Status;
3328             }
3329 
3330             //
3331             // ReInit the card again
3332             //
3333             if ((ui32Status = am_hal_card_init(pCard,
3334                 pCard->pCardPwrCtrlFunc, pCard->eCardPwrCtrlPolicy)) != AM_HAL_STATUS_SUCCESS)
3335             {
3336                 AM_HAL_CARD_DEBUG("wakeup reinit sd card failed\n");
3337                 return ui32Status;
3338             }
3339 
3340             //
3341             // Reconfig the card with the original settings
3342             //
3343             if ((ui32Status = am_hal_card_cfg_set(pCard, pCard->eType, pCard->cfg.eBusWidth,
3344                 pCard->cfg.ui32Clock, pCard->cfg.eIoVoltage, pCard->cfg.eUHSMode)) != AM_HAL_STATUS_SUCCESS)
3345             {
3346                 AM_HAL_CARD_DEBUG("wakeup configure sd card failed\n");
3347                 return ui32Status;
3348             }
3349             break;
3350 
3351         case AM_HAL_CARD_PWR_CTRL_SDHC_OFF_AND_CARD_SLEEP:
3352             //
3353             // Power on the SDHC controller
3354             //
3355             if ((ui32Status = pHost->ops->pwr_ctrl(pHost->pHandle, true)) != AM_HAL_STATUS_SUCCESS)
3356             {
3357                 AM_HAL_CARD_DEBUG("wakeup - power on the sdhc controller failed\n");
3358                 return ui32Status;
3359             }
3360 
3361             //
3362             // Exit Sleep state
3363             //
3364             if ( AM_HAL_CMD_ERR_NONE != am_hal_sdmmc_cmd5(pCard, false) )
3365             {
3366                 AM_HAL_CARD_DEBUG("wakeup - am_hal_sdmmc_cmd5 Failed\n");
3367                 return AM_HAL_STATUS_FAIL;
3368             }
3369 
3370             //
3371             // Reselect card
3372             //
3373             if ( AM_HAL_CMD_ERR_NONE != am_hal_sdmmc_cmd7_card_select(pCard) )
3374             {
3375                 AM_HAL_CARD_DEBUG("wakeup - am_hal_sdmmc_cmd7_card_select Failed\n");
3376                 return AM_HAL_STATUS_FAIL;
3377             }
3378             break;
3379 
3380         case AM_HAL_CARD_PWR_CTRL_SDHC_OFF:
3381             //
3382             // Power on the SDHC controller
3383             //
3384             if ((ui32Status = pHost->ops->pwr_ctrl(pHost->pHandle, true)) != AM_HAL_STATUS_SUCCESS)
3385             {
3386                 AM_HAL_CARD_DEBUG("wakeup - power on the sdhc controller failed\n");
3387                 return ui32Status;
3388             }
3389             break;
3390 
3391         default:
3392             break;
3393     }
3394 
3395     return AM_HAL_STATUS_SUCCESS;
3396 }
3397 
3398 //*****************************************************************************
3399 //
3400 // Get the card instance function
3401 //
3402 //*****************************************************************************
3403 uint32_t
am_hal_card_host_find_card(am_hal_card_host_t * pHost,am_hal_card_t * pCard)3404 am_hal_card_host_find_card(am_hal_card_host_t *pHost, am_hal_card_t *pCard)
3405 {
3406 
3407 #ifndef AM_HAL_DISABLE_API_VALIDATION
3408 
3409     if ( !pHost || !pCard )
3410     {
3411         return AM_HAL_STATUS_INVALID_ARG;
3412     }
3413 
3414 #endif // AM_HAL_DISABLE_API_VALIDATION
3415 
3416     if ( pHost->bCardInSlot ||
3417         pHost->ops->get_cd(pHost->pHandle) )
3418     {
3419         pCard->eState = AM_HAL_CARD_STATE_PRESENT;
3420         pCard->pHost  = pHost;
3421         //
3422         // Fill the default setting with the host's current value
3423         //
3424         pCard->cfg.eBusWidth = pHost->eBusWidth;
3425         pCard->cfg.eIoVoltage = pHost->eBusVoltage;
3426         pCard->cfg.ui32Clock = pHost->ui32MinClock;
3427         pCard->cfg.eUHSMode = pHost->eUHSMode;
3428         pCard->eState = AM_HAL_CARD_STATE_PWROFF;
3429         return AM_HAL_STATUS_SUCCESS;
3430     }
3431     else
3432     {
3433         pCard->eState = AM_HAL_CARD_STATE_NOT_PRESENT;
3434         return AM_HAL_STATUS_FAIL;
3435     }
3436 }
3437 
3438 //*****************************************************************************
3439 //
3440 // Set the card operation configurations
3441 //
3442 //*****************************************************************************
3443 uint32_t
am_hal_card_cfg_set(am_hal_card_t * pCard,am_hal_card_type_e eType,am_hal_host_bus_width_e eBusWidth,uint32_t ui32Clock,am_hal_host_bus_voltage_e eIoVoltage,am_hal_host_uhs_mode_e eUHSMode)3444 am_hal_card_cfg_set(am_hal_card_t *pCard, am_hal_card_type_e eType,
3445                     am_hal_host_bus_width_e eBusWidth,
3446                     uint32_t ui32Clock,
3447                     am_hal_host_bus_voltage_e eIoVoltage,
3448                     am_hal_host_uhs_mode_e eUHSMode)
3449 {
3450 #ifndef AM_HAL_DISABLE_API_VALIDATION
3451     if ( !pCard || !pCard->pHost )
3452     {
3453         AM_HAL_CARD_DEBUG("This card is not connected to a host\n");
3454         return AM_HAL_STATUS_INVALID_ARG;
3455     }
3456 #endif // AM_HAL_DISABLE_API_VALIDATION
3457 
3458     if ( pCard->eState != AM_HAL_CARD_STATE_TRANS )
3459     {
3460         return AM_HAL_STATUS_INVALID_OPERATION;
3461     }
3462 
3463     //
3464     // Checking the validation of the clock settings
3465     // Clock should not exceed the capabilities of the SDHC
3466     // DDR mode, max speed is not higer than 48MHz
3467     // SDR mode, max speed is not higer than 96MHz
3468     //
3469     if ((ui32Clock > pCard->pHost->ui32MaxClock) || (ui32Clock < pCard->pHost->ui32MinClock) ||
3470         ((eUHSMode == AM_HAL_HOST_UHS_DDR50) && (ui32Clock > MMC_HS_MAX_SPEED_LIMIT)) ||
3471         ((eUHSMode == AM_HAL_HOST_UHS_NONE) && (ui32Clock > MMC_HS200_MAX_SPEED_LIMIT)) ||
3472         (ui32Clock > MMC_HS200_MAX_SPEED_LIMIT))
3473     {
3474         return AM_HAL_STATUS_INVALID_ARG;
3475     }
3476 
3477     pCard->cfg.eBusWidth = eBusWidth;
3478     pCard->cfg.ui32Clock = ui32Clock;
3479     pCard->cfg.eIoVoltage = eIoVoltage;
3480     pCard->cfg.eUHSMode = eUHSMode;
3481 
3482     if ( pCard->eType == AM_HAL_CARD_TYPE_EMMC )
3483     {
3484         //
3485         // Configure the card voltage
3486         //
3487         if ( am_hal_card_set_voltage(pCard, pCard->cfg.eIoVoltage) != AM_HAL_STATUS_SUCCESS )
3488         {
3489             AM_HAL_CARD_DEBUG("Failed to change bus voltage\n");
3490             return AM_HAL_STATUS_FAIL;
3491         }
3492 
3493         //
3494         // Checking the validation of the clock settings
3495         // Clock should not exceed the capabilities of the SDHC
3496         // DDR mode, max speed is not higer than 48MHz
3497         // SDR mode, max speed is not higer than 96MHz
3498         // Legacy card, max speed is not higher than 26MHz
3499         //
3500         if ((ui32Clock > MMC_LEGACY_HS) && (pCard->ui8SpecVer < 4))
3501         {
3502             return AM_HAL_STATUS_INVALID_ARG;
3503         }
3504 
3505         if ( eUHSMode == AM_HAL_HOST_UHS_SDR104 )
3506         {
3507             //
3508             // Configure the card bus width
3509             //
3510             if ( am_hal_card_set_bus_width(pCard, pCard->cfg.eBusWidth) != AM_HAL_STATUS_SUCCESS )
3511             {
3512                 AM_HAL_CARD_DEBUG("Failed to change bus width\n");
3513                 return AM_HAL_STATUS_FAIL;
3514             }
3515 
3516             //
3517             // Configure the card bus speed
3518             //
3519             if ( am_hal_card_set_speed(pCard, pCard->cfg.ui32Clock) != AM_HAL_STATUS_SUCCESS )
3520             {
3521                 AM_HAL_CARD_DEBUG("Failed to change bus speed\n");
3522                 return AM_HAL_STATUS_FAIL;
3523             }
3524         }
3525         else
3526         {
3527             //
3528             // Configure the card bus speed
3529             //
3530             if ( am_hal_card_set_speed(pCard, pCard->cfg.ui32Clock) != AM_HAL_STATUS_SUCCESS )
3531             {
3532                 AM_HAL_CARD_DEBUG("Failed to change bus speed\n");
3533                 return AM_HAL_STATUS_FAIL;
3534             }
3535 
3536             //
3537             // Configure the card bus width
3538             //
3539             if ( am_hal_card_set_bus_width(pCard, pCard->cfg.eBusWidth) != AM_HAL_STATUS_SUCCESS )
3540             {
3541                 AM_HAL_CARD_DEBUG("Failed to change bus width\n");
3542                 return AM_HAL_STATUS_FAIL;
3543             }
3544         }
3545 
3546         //
3547         // Select the UHS mode
3548         //
3549         if (am_hal_card_set_uhs_mode(pCard, pCard->cfg.eUHSMode) != AM_HAL_STATUS_SUCCESS)
3550         {
3551             AM_HAL_CARD_DEBUG("Failed to change UHS mode\n");
3552             return AM_HAL_STATUS_FAIL;
3553         }
3554     }
3555     else if ( pCard->eType == AM_HAL_CARD_TYPE_SDIO )
3556     {
3557         //
3558         // Configure the card bus speed
3559         //
3560         if ( am_hal_sdio_card_set_speed(pCard, pCard->cfg.ui32Clock) != AM_HAL_STATUS_SUCCESS )
3561         {
3562             AM_HAL_CARD_DEBUG("Failed to change bus speed\n");
3563             return AM_HAL_STATUS_FAIL;
3564         }
3565 
3566         //
3567         // Configure the card bus width
3568         //
3569         if ( am_hal_sdio_card_set_bus_width(pCard, pCard->cfg.eBusWidth) != AM_HAL_STATUS_SUCCESS )
3570         {
3571             AM_HAL_CARD_DEBUG("Failed to change bus width\n");
3572             return AM_HAL_STATUS_FAIL;
3573         }
3574     }
3575     else if ( pCard->eType == AM_HAL_CARD_TYPE_SDSC ||
3576               pCard->eType == AM_HAL_CARD_TYPE_SDHC ||
3577               pCard->eType == AM_HAL_CARD_TYPE_SDXC )
3578     {
3579         //
3580         // Reinit sd card when switch working voltage
3581         //
3582         if ( am_hal_sd_card_set_voltage(pCard, eIoVoltage)!= AM_HAL_STATUS_SUCCESS )
3583         {
3584             AM_HAL_CARD_DEBUG("Failed to set sd card voltage\n");
3585             return AM_HAL_STATUS_FAIL;
3586         }
3587 
3588         //
3589         // Configure the card bus speed
3590         //
3591         if ( am_hal_sd_card_set_speed(pCard, pCard->cfg.ui32Clock) != AM_HAL_STATUS_SUCCESS )
3592         {
3593             AM_HAL_CARD_DEBUG("Failed to change bus speed\n");
3594             return AM_HAL_STATUS_FAIL;
3595         }
3596 
3597         //
3598         // Configure the card bus width when work at 3.3V
3599         //
3600         if ( pCard->sdcard.ui32CurrentVolt == AM_HAL_SD_CARD_3_3_V )
3601         {
3602             if ( am_hal_sd_card_set_bus_width(pCard, pCard->cfg.eBusWidth) != AM_HAL_STATUS_SUCCESS )
3603             {
3604                 AM_HAL_CARD_DEBUG("Failed to change bus width\n");
3605                 return AM_HAL_STATUS_FAIL;
3606             }
3607         }
3608 
3609         //
3610         // Select the UHS mode
3611         //
3612         if ( pCard->sdcard.ui32CurrentVolt == AM_HAL_SD_CARD_1_8_V )
3613         {
3614             if (am_hal_card_set_uhs_mode(pCard, pCard->cfg.eUHSMode) != AM_HAL_STATUS_SUCCESS)
3615             {
3616                 AM_HAL_CARD_DEBUG("Failed to change UHS mode\n");
3617                 return AM_HAL_STATUS_FAIL;
3618             }
3619         }
3620     }
3621     else
3622     {
3623         AM_HAL_CARD_DEBUG("Card Tpye is not supported!\n");
3624         return AM_HAL_STATUS_FAIL;
3625     }
3626 
3627     return AM_HAL_STATUS_SUCCESS;
3628 }
3629 
3630 //*****************************************************************************
3631 //
3632 // Initialize the card instance function
3633 //
3634 //*****************************************************************************
3635 uint32_t
am_hal_card_init(am_hal_card_t * pCard,am_hal_card_pwr_ctrl_func pCardPwrCtrlFunc,am_hal_card_pwr_ctrl_policy_e eCardPwrCtrlPolicy)3636 am_hal_card_init(am_hal_card_t *pCard,
3637                  am_hal_card_pwr_ctrl_func pCardPwrCtrlFunc,
3638                  am_hal_card_pwr_ctrl_policy_e eCardPwrCtrlPolicy)
3639 {
3640 #ifndef AM_HAL_DISABLE_API_VALIDATION
3641     if ( !pCard || !pCard->pHost )
3642     {
3643         AM_HAL_CARD_DEBUG("This card is not connected to a host\n");
3644         return AM_HAL_STATUS_INVALID_ARG;
3645     }
3646 #endif // AM_HAL_DISABLE_API_VALIDATION
3647 
3648     //
3649     // Turn on the eMMC card power supply firstly or sd card power cycle
3650     //
3651     if (pCardPwrCtrlFunc != NULL)
3652     {
3653         AM_HAL_CARD_DEBUG("turn on the eMMC/sdcard power supply\n");
3654         pCardPwrCtrlFunc(AM_HAL_CARD_PWR_CYCLE);
3655     }
3656 
3657     pCard->pCardPwrCtrlFunc = pCardPwrCtrlFunc;
3658     pCard->eState = AM_HAL_CARD_STATE_PWRON;
3659     pCard->eCardPwrCtrlPolicy = eCardPwrCtrlPolicy;
3660 
3661     AM_HAL_CARD_DEBUG("card type is %d\n", pCard->eType);
3662 
3663     //
3664     // Detect card type
3665     //
3666     AM_HAL_CARD_DEBUG("enter into card type detect\n");
3667     if ( am_hal_card_type_detect(pCard) != AM_HAL_STATUS_SUCCESS )
3668     {
3669         return AM_HAL_STATUS_FAIL;
3670     }
3671 
3672     switch (pCard->eType)
3673     {
3674         case AM_HAL_CARD_TYPE_UNKNOWN:
3675             AM_HAL_CARD_DEBUG("card type is unknown:%d\n", pCard->eType);
3676             return AM_HAL_STATUS_FAIL;
3677             break;
3678         case AM_HAL_CARD_TYPE_MMC:
3679         case AM_HAL_CARD_TYPE_EMMC:
3680             if ( am_hal_card_mmc_init(pCard) != AM_HAL_STATUS_SUCCESS )
3681             {
3682                 return AM_HAL_STATUS_FAIL;
3683             }
3684             break;
3685         case AM_HAL_CARD_TYPE_SDSC:
3686         case AM_HAL_CARD_TYPE_SDHC:
3687         case AM_HAL_CARD_TYPE_SDXC:
3688             if ( am_hal_sd_card_init(pCard, pCardPwrCtrlFunc) != AM_HAL_STATUS_SUCCESS )
3689             {
3690                 return AM_HAL_STATUS_FAIL;
3691             }
3692             break;
3693         case AM_HAL_CARD_TYPE_SDIO:
3694             if ( am_hal_card_sdio_init(pCard) != AM_HAL_STATUS_SUCCESS )
3695             {
3696                 return AM_HAL_STATUS_FAIL;
3697             }
3698             break;
3699         case AM_HAL_CARD_TYPE_COMBO:
3700             if ( am_hal_card_sd_init(pCard) != AM_HAL_STATUS_SUCCESS )
3701             {
3702                 return AM_HAL_STATUS_FAIL;
3703             }
3704             break;
3705     }
3706 
3707     return AM_HAL_STATUS_SUCCESS;
3708 }
3709 
3710 //*****************************************************************************
3711 //
3712 // De-Initialize the card instance function
3713 //
3714 //*****************************************************************************
3715 uint32_t
am_hal_card_deinit(am_hal_card_t * pCard)3716 am_hal_card_deinit(am_hal_card_t *pCard)
3717 {
3718 #ifndef AM_HAL_DISABLE_API_VALIDATION
3719     if ( !pCard || !pCard->pHost )
3720     {
3721         AM_HAL_CARD_DEBUG("This card is not connected to a host\n");
3722         return AM_HAL_STATUS_INVALID_ARG;
3723     }
3724 #endif // AM_HAL_DISABLE_API_VALIDATION
3725 
3726     //
3727     // Turn off the eMMC card power supply firstly
3728     //
3729     if (pCard->pCardPwrCtrlFunc != NULL)
3730     {
3731         AM_HAL_CARD_DEBUG("turn off the eMMC/sdcard power supply\n");
3732         pCard->pCardPwrCtrlFunc(AM_HAL_CARD_PWR_OFF);
3733     }
3734 
3735     memset((void *)pCard, 0x0, sizeof(am_hal_card_t));
3736 
3737     return AM_HAL_STATUS_SUCCESS;
3738 }
3739 
3740 static uint32_t
am_hal_card_block_rw(am_hal_card_t * pCard,uint32_t ui32Blk,uint32_t ui32BlkCnt,uint8_t * pui8Buf,bool bRead,bool bASync)3741 am_hal_card_block_rw(am_hal_card_t *pCard, uint32_t ui32Blk, uint32_t ui32BlkCnt, uint8_t *pui8Buf, bool bRead, bool bASync)
3742 {
3743     uint32_t ui32Status;
3744 
3745     am_hal_card_host_t *pHost;
3746     am_hal_card_cmd_t cmd;
3747     am_hal_card_cmd_data_t cmd_data;
3748 
3749 #ifndef AM_HAL_DISABLE_API_VALIDATION
3750 
3751     if ( !pCard || !pCard->pHost )
3752     {
3753         return AM_HAL_STATUS_INVALID_ARG;
3754     }
3755 
3756 #endif // AM_HAL_DISABLE_API_VALIDATION
3757 
3758     if ( pCard->eState != AM_HAL_CARD_STATE_TRANS )
3759     {
3760         return AM_HAL_STATUS_INVALID_OPERATION;
3761     }
3762 
3763     pHost = pCard->pHost;
3764 
3765     //
3766     // Check if the start block number and block count is valid or not
3767     //
3768     if ( ui32Blk >= pCard->ui32MaxBlks || (ui32BlkCnt > 0xFFFF) || (ui32Blk + ui32BlkCnt) > pCard->ui32MaxBlks )
3769     {
3770         return AM_HAL_STATUS_OUT_OF_RANGE;
3771     }
3772 
3773     if ( pHost->eXferMode == AM_HAL_HOST_XFER_ADMA && ui32BlkCnt > pHost->ui32MaxADMA2BlkNums )
3774     {
3775         ui32BlkCnt = pHost->ui32MaxADMA2BlkNums;
3776     }
3777 
3778 #ifndef ENABLE_SDHC_AUTO_CMD23_FEATURE
3779     //
3780     // Send CMD23 firstly for mulitple blocks transfer
3781     //
3782     memset((void *)&cmd, 0x0, sizeof(cmd));
3783     if ( ui32BlkCnt > 1 )
3784     {
3785         cmd.ui8Idx = MMC_CMD_SET_BLOCK_COUNT;
3786         cmd.ui32Arg = ui32BlkCnt;
3787         cmd.ui32RespType = MMC_RSP_R1;
3788 
3789         if ( (ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL)) != AM_HAL_STATUS_SUCCESS )
3790         {
3791             return ui32Status;
3792         }
3793     }
3794 #endif
3795 
3796     memset((void *)&cmd, 0x0, sizeof(cmd));
3797     memset((void *)&cmd_data, 0x0, sizeof(cmd_data));
3798     if ( bRead )
3799     {
3800         cmd.ui8Idx = ui32BlkCnt > 1 ? MMC_CMD_READ_MULTIPLE_BLOCK : MMC_CMD_READ_SINGLE_BLOCK;
3801     }
3802     else
3803     {
3804         cmd.ui8Idx = ui32BlkCnt > 1 ? MMC_CMD_WRITE_MULTIPLE_BLOCK : MMC_CMD_WRITE_SINGLE_BLOCK;
3805     }
3806 
3807     cmd.ui32Arg = pCard->bHighCapcity ? ui32Blk : ui32Blk * pCard->ui32BlkSize;
3808     cmd.ui32RespType = MMC_RSP_R1;
3809     cmd.bASync = bASync;
3810 #ifdef ENABLE_SDHC_AUTO_CMD23_FEATURE
3811     cmd.bAutoCMD23 = ui32BlkCnt > 1 ? true : false;
3812 #endif
3813 
3814     cmd_data.ui8IovCnt = 0;
3815     cmd_data.pui8Buf = pui8Buf;
3816     cmd_data.ui32BlkCnt = ui32BlkCnt;
3817     cmd_data.ui32BlkSize = pCard->ui32BlkSize;
3818     cmd_data.dir = bRead ? AM_HAL_DATA_DIR_READ : AM_HAL_DATA_DIR_WRITE;
3819 
3820     if ( cmd.bASync )
3821     {
3822         pHost->AsyncCmd = cmd;
3823         pHost->AsyncCmdData = cmd_data;
3824     }
3825 
3826     ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, &cmd_data);
3827 
3828     return ui32Status;
3829 }
3830 
3831 static uint32_t
am_hal_emmc_card_scatter_rw(am_hal_card_t * pCard,uint32_t ui32Blk,am_hal_card_iovec_t * pIoVec,uint8_t ui8IovCnt,bool bRead,bool bASync)3832 am_hal_emmc_card_scatter_rw(am_hal_card_t *pCard, uint32_t ui32Blk, am_hal_card_iovec_t *pIoVec, uint8_t ui8IovCnt, bool bRead, bool bASync)
3833 {
3834     uint32_t ui32Status;
3835 
3836     am_hal_card_host_t *pHost;
3837     am_hal_card_cmd_t cmd;
3838     am_hal_card_cmd_data_t cmd_data;
3839     uint32_t ui32BlkCnt = 0;
3840 
3841 #ifndef AM_HAL_DISABLE_API_VALIDATION
3842 
3843     if ( !pCard || !pCard->pHost || !pIoVec || !ui8IovCnt)
3844     {
3845         return AM_HAL_STATUS_INVALID_ARG;
3846     }
3847 
3848 #endif // AM_HAL_DISABLE_API_VALIDATION
3849 
3850     if ( pCard->eState != AM_HAL_CARD_STATE_TRANS )
3851     {
3852         return AM_HAL_STATUS_INVALID_OPERATION;
3853     }
3854 
3855     for (uint8_t i = 0; i < ui8IovCnt ; i++ )
3856     {
3857         if ( pIoVec[i].pIovBase == NULL  || pIoVec[i].ui32IovLen == 0 )
3858         {
3859             return AM_HAL_STATUS_INVALID_ARG;
3860         }
3861 
3862         if ( (pIoVec[i].ui32IovLen % pCard->ui32BlkSize) != 0 )
3863         {
3864             return AM_HAL_STATUS_INVALID_ARG;
3865         }
3866 
3867         ui32BlkCnt += pIoVec[i].ui32IovLen / pCard->ui32BlkSize;
3868     }
3869 
3870     pHost = pCard->pHost;
3871 
3872     //
3873     // Check transfer mode
3874     //
3875     if ( pHost->eXferMode != AM_HAL_HOST_XFER_ADMA )
3876     {
3877         return AM_HAL_STATUS_INVALID_OPERATION;
3878     }
3879 
3880     // Check if the start block number and block count is valid or not
3881     //
3882     if ( ui32Blk >= pCard->ui32MaxBlks || (ui32BlkCnt > 0xFFFF) || (ui32Blk + ui32BlkCnt) > pCard->ui32MaxBlks )
3883     {
3884         return AM_HAL_STATUS_OUT_OF_RANGE;
3885     }
3886 
3887     if ( ui32BlkCnt > pHost->ui32MaxADMA2BlkNums )
3888     {
3889         ui32BlkCnt = pHost->ui32MaxADMA2BlkNums;
3890     }
3891 
3892 #ifndef ENABLE_SDHC_AUTO_CMD23_FEATURE
3893     //
3894     // Send CMD23 firstly for mulitple blocks transfer
3895     //
3896     memset((void *)&cmd, 0x0, sizeof(cmd));
3897     if ( ui32BlkCnt > 1 )
3898     {
3899         cmd.ui8Idx = MMC_CMD_SET_BLOCK_COUNT;
3900         cmd.ui32Arg = ui32BlkCnt;
3901         cmd.ui32RespType = MMC_RSP_R1;
3902 
3903         if ( (ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL)) != AM_HAL_STATUS_SUCCESS )
3904         {
3905             return ui32Status;
3906         }
3907     }
3908 #endif
3909 
3910     memset((void *)&cmd, 0x0, sizeof(cmd));
3911     memset((void *)&cmd_data, 0x0, sizeof(cmd_data));
3912     if ( bRead )
3913     {
3914         cmd.ui8Idx = ui32BlkCnt > 1 ? MMC_CMD_READ_MULTIPLE_BLOCK : MMC_CMD_READ_SINGLE_BLOCK;
3915     }
3916     else
3917     {
3918         cmd.ui8Idx = ui32BlkCnt > 1 ? MMC_CMD_WRITE_MULTIPLE_BLOCK : MMC_CMD_WRITE_SINGLE_BLOCK;
3919     }
3920 
3921     cmd.ui32Arg = pCard->bHighCapcity ? ui32Blk : ui32Blk * pCard->ui32BlkSize;
3922     cmd.ui32RespType = MMC_RSP_R1;
3923     cmd.bASync = bASync;
3924 #ifdef ENABLE_SDHC_AUTO_CMD23_FEATURE
3925     cmd.bAutoCMD23 = ui32BlkCnt > 1 ? true : false;
3926 #endif
3927 
3928     cmd_data.ui32BlkCnt = ui32BlkCnt;
3929     cmd_data.ui32BlkSize = pCard->ui32BlkSize;
3930     cmd_data.dir = bRead ? AM_HAL_DATA_DIR_READ : AM_HAL_DATA_DIR_WRITE;
3931     cmd_data.pIov = pIoVec;
3932     cmd_data.ui8IovCnt = ui8IovCnt;
3933 
3934     if ( cmd.bASync )
3935     {
3936         pHost->AsyncCmd = cmd;
3937         pHost->AsyncCmdData = cmd_data;
3938     }
3939 
3940     ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, &cmd_data);
3941 
3942     return ui32Status;
3943 }
3944 
3945 //*****************************************************************************
3946 //
3947 // synchronous block-oriented read function
3948 //
3949 //*****************************************************************************
3950 uint32_t
am_hal_card_block_read_sync(am_hal_card_t * pCard,uint32_t ui32Blk,uint32_t ui32BlkCnt,uint8_t * pui8Buf)3951 am_hal_card_block_read_sync(am_hal_card_t *pCard, uint32_t ui32Blk, uint32_t ui32BlkCnt, uint8_t *pui8Buf)
3952 {
3953     return am_hal_card_block_rw(pCard, ui32Blk, ui32BlkCnt, pui8Buf, true, false);
3954 }
3955 
3956 //*****************************************************************************
3957 //
3958 // synchronous block-oriented write function
3959 //
3960 //*****************************************************************************
3961 uint32_t
am_hal_card_block_write_sync(am_hal_card_t * pCard,uint32_t ui32Blk,uint32_t ui32BlkCnt,uint8_t * pui8Buf)3962 am_hal_card_block_write_sync(am_hal_card_t *pCard, uint32_t ui32Blk, uint32_t ui32BlkCnt, uint8_t *pui8Buf)
3963 {
3964     return am_hal_card_block_rw(pCard, ui32Blk, ui32BlkCnt, pui8Buf, false, false);
3965 }
3966 
3967 //*****************************************************************************
3968 //
3969 // emmc scatter write synchronous function
3970 //
3971 //*****************************************************************************
3972 uint32_t
am_hal_emmc_card_scatter_write_sync(am_hal_card_t * pCard,uint32_t ui32Blk,am_hal_card_iovec_t * pIoVec,uint8_t ui8IovCnt)3973 am_hal_emmc_card_scatter_write_sync(am_hal_card_t *pCard, uint32_t ui32Blk, am_hal_card_iovec_t *pIoVec, uint8_t ui8IovCnt)
3974 {
3975     return am_hal_emmc_card_scatter_rw(pCard, ui32Blk, pIoVec, ui8IovCnt, false, false);
3976 }
3977 
3978 //*****************************************************************************
3979 //
3980 // emmc scatter read synchronous function
3981 //
3982 //*****************************************************************************
3983 uint32_t
am_hal_emmc_card_scatter_read_sync(am_hal_card_t * pCard,uint32_t ui32Blk,am_hal_card_iovec_t * pIoVec,uint8_t ui8IovCnt)3984 am_hal_emmc_card_scatter_read_sync(am_hal_card_t *pCard, uint32_t ui32Blk, am_hal_card_iovec_t *pIoVec, uint8_t ui8IovCnt)
3985 {
3986     return am_hal_emmc_card_scatter_rw(pCard, ui32Blk, pIoVec, ui8IovCnt, true, false);
3987 }
3988 
3989 //*****************************************************************************
3990 //
3991 // asynchronous block-oriented read function
3992 //
3993 //*****************************************************************************
3994 uint32_t
am_hal_card_block_read_async(am_hal_card_t * pCard,uint32_t ui32Blk,uint32_t ui32BlkCnt,uint8_t * pui8Buf)3995 am_hal_card_block_read_async(am_hal_card_t *pCard, uint32_t ui32Blk, uint32_t ui32BlkCnt, uint8_t *pui8Buf)
3996 {
3997     return am_hal_card_block_rw(pCard, ui32Blk, ui32BlkCnt, pui8Buf, true, true);
3998 }
3999 
4000 //*****************************************************************************
4001 //
4002 // asynchronous block-oriented write function
4003 //
4004 //*****************************************************************************
4005 uint32_t
am_hal_card_block_write_async(am_hal_card_t * pCard,uint32_t ui32Blk,uint32_t ui32BlkCnt,uint8_t * pui8Buf)4006 am_hal_card_block_write_async(am_hal_card_t *pCard, uint32_t ui32Blk, uint32_t ui32BlkCnt, uint8_t *pui8Buf)
4007 {
4008     return am_hal_card_block_rw(pCard, ui32Blk, ui32BlkCnt, pui8Buf, false, true);
4009 }
4010 
4011 //*****************************************************************************
4012 //
4013 // emmc scatter write asynchronous function
4014 //
4015 //*****************************************************************************
4016 uint32_t
am_hal_emmc_card_scatter_write_async(am_hal_card_t * pCard,uint32_t ui32Blk,am_hal_card_iovec_t * pIoVec,uint8_t ui8IovCnt)4017 am_hal_emmc_card_scatter_write_async(am_hal_card_t *pCard, uint32_t ui32Blk, am_hal_card_iovec_t *pIoVec, uint8_t ui8IovCnt)
4018 {
4019     return am_hal_emmc_card_scatter_rw(pCard, ui32Blk, pIoVec, ui8IovCnt, false, true);
4020 }
4021 
4022 //*****************************************************************************
4023 //
4024 // emmc scatter read asynchronous function
4025 //
4026 //*****************************************************************************
4027 uint32_t
am_hal_emmc_card_scatter_read_async(am_hal_card_t * pCard,uint32_t ui32Blk,am_hal_card_iovec_t * pIoVec,uint8_t ui8IovCnt)4028 am_hal_emmc_card_scatter_read_async(am_hal_card_t *pCard, uint32_t ui32Blk, am_hal_card_iovec_t *pIoVec, uint8_t ui8IovCnt)
4029 {
4030     return am_hal_emmc_card_scatter_rw(pCard, ui32Blk, pIoVec, ui8IovCnt, true, true);
4031 }
4032 
4033 //*****************************************************************************
4034 //
4035 // block-oriented erase function
4036 //
4037 //*****************************************************************************
4038 uint32_t
am_hal_card_block_erase(am_hal_card_t * pCard,uint32_t ui32Blk,uint32_t ui32BlkCnt,am_hal_card_erase_type_t erasetype,uint32_t ui32TimeoutMS)4039 am_hal_card_block_erase(am_hal_card_t *pCard, uint32_t ui32Blk, uint32_t ui32BlkCnt, am_hal_card_erase_type_t erasetype, uint32_t ui32TimeoutMS)
4040 {
4041     uint32_t ui32Status;
4042     am_hal_card_host_t *pHost;
4043     am_hal_card_cmd_t cmd;
4044 
4045 #ifndef AM_HAL_DISABLE_API_VALIDATION
4046 
4047     if ( !pCard || !pCard->pHost )
4048     {
4049         return AM_HAL_STATUS_INVALID_ARG;
4050     }
4051 
4052 #endif // AM_HAL_DISABLE_API_VALIDATION
4053 
4054     if ( pCard->eState != AM_HAL_CARD_STATE_TRANS )
4055     {
4056         return AM_HAL_STATUS_INVALID_OPERATION;
4057     }
4058 
4059     //
4060     // Check if the start block number and block count is valid or not
4061     //
4062     if ( ui32Blk >= pCard->ui32MaxBlks || ui32Blk + ui32BlkCnt > pCard->ui32MaxBlks )
4063     {
4064         return AM_HAL_STATUS_OUT_OF_RANGE;
4065     }
4066 
4067     if ( erasetype == AM_HAL_SECURE_ERASE || erasetype == AM_HAL_SECURE_TRIM1 || erasetype == AM_HAL_SECURE_TRIM2 )
4068     {
4069         if ( !(pCard->ui8SecureErase & SEC_ER_EN) )
4070         {
4071             AM_HAL_CARD_DEBUG("This device does not support Secure Erase or Trim\n");
4072             return AM_HAL_STATUS_INVALID_ARG;
4073         }
4074     }
4075 
4076     if ( erasetype == AM_HAL_TRIM || erasetype == AM_HAL_SECURE_TRIM1 || erasetype == AM_HAL_SECURE_TRIM2 )
4077     {
4078         if ( !(pCard->ui8SecureErase & SEC_GB_CL_EN) )
4079         {
4080             AM_HAL_CARD_DEBUG("This device does not support Trim operation\n");
4081             return AM_HAL_STATUS_INVALID_ARG;
4082         }
4083     }
4084 
4085     pHost = pCard->pHost;
4086 
4087     //
4088     // Define the erase start address
4089     //
4090     memset((void *)&cmd, 0x0, sizeof(cmd));
4091     cmd.ui8Idx = MMC_CMD_ERASE_GROUP_START;
4092     cmd.ui32Arg = pCard->bHighCapcity ? ui32Blk : ui32Blk * pCard->ui32BlkSize;
4093     cmd.ui32RespType = MMC_RSP_R1;
4094 
4095     if ( (ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL)) != AM_HAL_STATUS_SUCCESS )
4096     {
4097         return ui32Status;
4098     }
4099 
4100     //
4101     // Define the erase end address
4102     //
4103     memset((void *)&cmd, 0x0, sizeof(cmd));
4104     cmd.ui8Idx = MMC_CMD_ERASE_GROUP_END;
4105     cmd.ui32Arg = pCard->bHighCapcity ? (ui32Blk + ui32BlkCnt - 1) : (ui32Blk + ui32BlkCnt - 1) * pCard->ui32BlkSize;
4106     cmd.ui32RespType = MMC_RSP_R1;
4107 
4108     if ( (ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL)) != AM_HAL_STATUS_SUCCESS )
4109     {
4110         return ui32Status;
4111     }
4112 
4113     //
4114     // Do the erase job
4115     //
4116     memset((void *)&cmd, 0x0, sizeof(cmd));
4117     cmd.bCheckBusyCmd = true;
4118     cmd.ui8Idx = MMC_CMD_ERASE;
4119     cmd.ui32Arg = (uint32_t)erasetype;
4120     cmd.ui32RespType = MMC_RSP_R1b;
4121 
4122     if ( (ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL)) != AM_HAL_STATUS_SUCCESS )
4123     {
4124         return ui32Status;
4125     }
4126 
4127     return pHost->ops->card_busy(pHost->pHandle, ui32TimeoutMS);
4128 }
4129 
4130 //*****************************************************************************
4131 //
4132 // Get the card status function
4133 //
4134 //*****************************************************************************
4135 uint32_t
am_hal_card_status(am_hal_card_t * pCard,uint32_t * pui32Status)4136 am_hal_card_status(am_hal_card_t *pCard, uint32_t *pui32Status)
4137 {
4138     uint32_t ui32Status;
4139     am_hal_card_cmd_t cmd;
4140 
4141 #ifndef AM_HAL_DISABLE_API_VALIDATION
4142 
4143     if ( !pCard || !pCard->pHost )
4144     {
4145         return AM_HAL_STATUS_INVALID_ARG;
4146     }
4147 
4148 #endif // AM_HAL_DISABLE_API_VALIDATION
4149 
4150     if ( pCard->eState < AM_HAL_CARD_STATE_STDY )
4151     {
4152         return AM_HAL_STATUS_INVALID_OPERATION;
4153     }
4154 
4155     am_hal_card_host_t *pHost = pCard->pHost;
4156 
4157     memset(&cmd, 0, sizeof(cmd));
4158     cmd.ui8Idx = MMC_CMD_SEND_STATUS;
4159     cmd.ui32Arg = pCard->ui32RCA << 16;
4160     cmd.ui32RespType = MMC_RSP_R1;
4161 
4162     if ( (ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL)) != AM_HAL_STATUS_SUCCESS )
4163     {
4164         return ui32Status;
4165     }
4166 
4167     if ( cmd.eError == AM_HAL_CMD_ERR_NONE )
4168     {
4169         *pui32Status = cmd.ui32Resp[0];
4170     }
4171 
4172     return ui32Status;
4173 }
4174 
4175 //*****************************************************************************
4176 //
4177 // Get the card state function
4178 //
4179 //*****************************************************************************
am_hal_card_state(am_hal_card_t * pCard)4180 am_hal_card_state_e am_hal_card_state(am_hal_card_t *pCard)
4181 {
4182     uint32_t ui32Status = 0;
4183     uint32_t ui32State;
4184 
4185 #ifndef AM_HAL_DISABLE_API_VALIDATION
4186 
4187     if ( !pCard || !pCard->pHost )
4188     {
4189         return AM_HAL_CARD_STATE_ERROR;
4190     }
4191 
4192 #endif // AM_HAL_DISABLE_API_VALIDATION
4193 
4194     if ( am_hal_card_status(pCard, &ui32Status) != AM_HAL_STATUS_SUCCESS )
4195     {
4196         return AM_HAL_CARD_STATE_ERROR;
4197     }
4198     else
4199     {
4200         ui32State = ui32Status >> 9 & 0xF;
4201         if ( ui32State <= 10 )
4202         {
4203             pCard->eState = (am_hal_card_state_e)(ui32State + 2);
4204         }
4205         else
4206         {
4207             return AM_HAL_CARD_STATE_ERROR;
4208         }
4209     }
4210 
4211     return pCard->eState;
4212 }
4213 
4214 //*****************************************************************************
4215 //
4216 // CMD6 - Mode switch
4217 //
4218 //*****************************************************************************
4219 uint32_t
am_hal_card_mode_switch(am_hal_card_t * pCard,uint32_t ui32Mode,uint32_t ui32Timeout)4220 am_hal_card_mode_switch(am_hal_card_t *pCard, uint32_t ui32Mode, uint32_t ui32Timeout)
4221 {
4222     uint32_t ui32Status;
4223     uint32_t ui32CardStatus;
4224     am_hal_card_cmd_t cmd;
4225 
4226 #ifndef AM_HAL_DISABLE_API_VALIDATION
4227 
4228     if ( !pCard || !pCard->pHost )
4229     {
4230         return AM_HAL_STATUS_INVALID_ARG;
4231     }
4232 
4233 #endif // AM_HAL_DISABLE_API_VALIDATION
4234 
4235     if ( pCard->eState != AM_HAL_CARD_STATE_TRANS )
4236     {
4237         return AM_HAL_STATUS_INVALID_OPERATION;
4238     }
4239 
4240     am_hal_card_host_t *pHost = pCard->pHost;
4241 
4242     memset(&cmd, 0, sizeof(cmd));
4243     cmd.ui8Idx = MMC_CMD_SWITCH;
4244     cmd.ui32Arg = ui32Mode;
4245     pCard->bExtCsdValid = 0;
4246 
4247     if ( pCard->eType == AM_HAL_CARD_TYPE_MMC || pCard->eType == AM_HAL_CARD_TYPE_EMMC )
4248     {
4249         cmd.bCheckBusyCmd = true;
4250         cmd.ui32RespType = MMC_RSP_R1b;
4251     }
4252     else
4253     {
4254         cmd.ui32RespType = MMC_RSP_R1;
4255     }
4256 
4257     if ( (ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL)) != AM_HAL_STATUS_SUCCESS )
4258     {
4259         return ui32Status;
4260     }
4261 
4262     if ( pCard->eType == AM_HAL_CARD_TYPE_MMC || pCard->eType == AM_HAL_CARD_TYPE_EMMC )
4263     {
4264         if ((ui32Status = pHost->ops->card_busy(pHost->pHandle, DEFAULT_GET_STATUS_TIMEOUT_MS)) != AM_HAL_STATUS_SUCCESS)
4265         {
4266             return ui32Status;
4267         }
4268     }
4269 
4270     ui32CardStatus = 0x0;
4271 
4272     do
4273     {
4274         ui32Status = am_hal_card_status(pCard, &ui32CardStatus);
4275         if (ui32Status == AM_HAL_STATUS_SUCCESS && (ui32CardStatus & MMC_STATUS_SWITCH_ERROR))
4276         {
4277             AM_HAL_CARD_DEBUG("switch failed - mode is 0x%x !\n", ui32Mode);
4278             return AM_HAL_STATUS_FAIL;
4279         }
4280         if (ui32Status == AM_HAL_STATUS_SUCCESS && (ui32CardStatus & MMC_STATUS_RDY_FOR_DATA))
4281         {
4282             AM_HAL_CARD_DEBUG("switch succeeded - mode is 0x%x !\n", ui32Mode);
4283             return AM_HAL_STATUS_SUCCESS;
4284         }
4285         am_util_delay_ms(1);
4286     } while (ui32Timeout--);
4287 
4288     return ui32Timeout ? AM_HAL_STATUS_SUCCESS : AM_HAL_STATUS_FAIL;
4289 }
4290 
4291 //*****************************************************************************
4292 //
4293 // Read blocks of data from the card (GEN_CMD)
4294 //
4295 //*****************************************************************************
4296 static uint32_t
am_hal_card_cmd56_read(am_hal_card_t * pCard,uint32_t ui32Arg,uint8_t * pui8Buf,bool bASync)4297 am_hal_card_cmd56_read(am_hal_card_t *pCard, uint32_t ui32Arg, uint8_t *pui8Buf, bool bASync)
4298 {
4299     uint32_t ui32Status;
4300 
4301     am_hal_card_host_t *pHost;
4302     am_hal_card_cmd_t cmd;
4303     am_hal_card_cmd_data_t cmd_data;
4304 
4305 #ifndef AM_HAL_DISABLE_API_VALIDATION
4306 
4307     if ( !pCard || !pCard->pHost )
4308     {
4309         return AM_HAL_STATUS_INVALID_ARG;
4310     }
4311 
4312 #endif // AM_HAL_DISABLE_API_VALIDATION
4313 
4314     if ( pCard->eState != AM_HAL_CARD_STATE_TRANS )
4315     {
4316         return AM_HAL_STATUS_INVALID_OPERATION;
4317     }
4318 
4319     pHost = pCard->pHost;
4320 
4321     memset((void *)&cmd, 0x0, sizeof(cmd));
4322     cmd.ui8Idx = MMC_CMD_CMD56;
4323     cmd.ui32Arg = ui32Arg;
4324     cmd.ui32RespType = MMC_RSP_R1;
4325     cmd.bASync = bASync;
4326 
4327     memset((void *)&cmd_data, 0x0, sizeof(cmd_data));
4328     cmd_data.ui8IovCnt = 0;
4329     cmd_data.pui8Buf = pui8Buf;
4330     cmd_data.ui32BlkCnt = 1;
4331     cmd_data.ui32BlkSize = 512;
4332     cmd_data.dir = AM_HAL_DATA_DIR_READ;
4333 
4334     if ( cmd.bASync )
4335     {
4336         pHost->AsyncCmd = cmd;
4337         pHost->AsyncCmdData = cmd_data;
4338     }
4339 
4340     ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, &cmd_data);
4341 
4342     return ui32Status;
4343 }
4344 
4345 //*****************************************************************************
4346 //
4347 // Read blocks of data from the card (GEN_CMD) asynchronously
4348 //
4349 //*****************************************************************************
4350 uint32_t
am_hal_card_cmd56_read_async(am_hal_card_t * pCard,uint32_t ui32Arg,uint8_t * pui8Buf)4351 am_hal_card_cmd56_read_async(am_hal_card_t *pCard, uint32_t ui32Arg, uint8_t *pui8Buf)
4352 {
4353     return am_hal_card_cmd56_read(pCard, ui32Arg, pui8Buf, true);
4354 }
4355 
4356 //*****************************************************************************
4357 //
4358 // Read blocks of data from the card (GEN_CMD) synchronously
4359 //
4360 //*****************************************************************************
4361 uint32_t
am_hal_card_cmd56_read_sync(am_hal_card_t * pCard,uint32_t ui32Arg,uint8_t * pui8Buf)4362 am_hal_card_cmd56_read_sync(am_hal_card_t *pCard, uint32_t ui32Arg, uint8_t *pui8Buf)
4363 {
4364     return am_hal_card_cmd56_read(pCard, ui32Arg, pui8Buf, false);
4365 }
4366 
4367 //*****************************************************************************
4368 //
4369 // register the card event call back function
4370 //
4371 //*****************************************************************************
4372 uint32_t
am_hal_card_register_evt_callback(am_hal_card_t * pCard,am_hal_host_event_cb_t pfunCallback)4373 am_hal_card_register_evt_callback(am_hal_card_t *pCard, am_hal_host_event_cb_t pfunCallback)
4374 {
4375 #ifndef AM_HAL_DISABLE_API_VALIDATION
4376     if ( !pCard || !pCard->pHost )
4377     {
4378         AM_HAL_CARD_DEBUG("both Card and Host are needed to be initialized firstly\n");
4379         return AM_HAL_STATUS_INVALID_ARG;
4380     }
4381 #endif // AM_HAL_DISABLE_API_VALIDATION
4382 
4383     pCard->pHost->pfunEvtCallback = pfunCallback;
4384 
4385     return AM_HAL_STATUS_SUCCESS;
4386 }
4387 
4388 //*****************************************************************************
4389 //
4390 // card cid information parse function
4391 //
4392 //*****************************************************************************
4393 uint32_t
am_hal_card_get_cid_field(am_hal_card_t * pCard,uint16_t ui16Offset,uint8_t ui8Size)4394 am_hal_card_get_cid_field(am_hal_card_t *pCard, uint16_t ui16Offset, uint8_t ui8Size)
4395 {
4396 #ifndef AM_HAL_DISABLE_API_VALIDATION
4397     if ( !pCard || !pCard->bCidValid )
4398     {
4399         return 0xFFFFFFFF;
4400     }
4401 #endif // AM_HAL_DISABLE_API_VALIDATION
4402 
4403     return am_hal_unstuff_bits(pCard->ui32CID, ui16Offset, ui8Size);
4404 
4405 
4406 }
4407 
4408 //*****************************************************************************
4409 //
4410 // card csd information parse function
4411 //
4412 //*****************************************************************************
4413 uint32_t
am_hal_card_get_csd_field(am_hal_card_t * pCard,uint16_t ui16Offset,uint8_t ui8Size)4414 am_hal_card_get_csd_field(am_hal_card_t *pCard, uint16_t ui16Offset, uint8_t ui8Size)
4415 {
4416 #ifndef AM_HAL_DISABLE_API_VALIDATION
4417     if ( !pCard || !pCard->bCsdValid )
4418     {
4419         return 0xFFFFFFFF;
4420     }
4421 #endif // AM_HAL_DISABLE_API_VALIDATION
4422 
4423     return am_hal_unstuff_bits(pCard->ui32CSD, ui16Offset, ui8Size);
4424 
4425 }
4426 
4427 //*****************************************************************************
4428 //
4429 // card ext csd information parse function
4430 //
4431 //*****************************************************************************
4432 uint32_t
am_hal_card_get_ext_csd_field(am_hal_card_t * pCard,uint16_t ui16Offset,uint8_t ui8Size)4433 am_hal_card_get_ext_csd_field(am_hal_card_t *pCard, uint16_t ui16Offset, uint8_t ui8Size)
4434 {
4435 
4436 #ifndef AM_HAL_DISABLE_API_VALIDATION
4437 
4438     if ( !pCard || !pCard->pHost)
4439     {
4440         return 0xFFFFFFFF;
4441     }
4442 
4443 #endif // AM_HAL_DISABLE_API_VALIDATION
4444 
4445     if ( !pCard->bExtCsdValid )
4446     {
4447         if (am_hal_sdmmc_cmd8_send_ext_csd(pCard) != AM_HAL_CMD_ERR_NONE)
4448         {
4449             return 0xFFFFFFFF;
4450         }
4451         pCard->bExtCsdValid = 1;
4452     }
4453 
4454     return am_hal_unstuff_bytes(pCard->ui32ExtCSD, ui16Offset, ui8Size);
4455 
4456 }
4457 
4458 //*****************************************************************************
4459 //
4460 // Get the card information function
4461 //
4462 //*****************************************************************************
4463 uint32_t
am_hal_card_get_info(am_hal_card_t * pCard,am_hal_card_info_t * pCardInfo)4464 am_hal_card_get_info(am_hal_card_t *pCard, am_hal_card_info_t *pCardInfo)
4465 {
4466 #ifndef AM_HAL_DISABLE_API_VALIDATION
4467     if ( !pCard || !pCard->pHost )
4468     {
4469         AM_HAL_CARD_DEBUG("both Card and Host are needed to be initialized firstly\n");
4470         return AM_HAL_STATUS_INVALID_ARG;
4471     }
4472 #endif // AM_HAL_DISABLE_API_VALIDATION
4473 
4474     pCardInfo->eType        = pCard->eType;
4475     pCardInfo->ui16CmdClass = pCard->ui16CmdClass;
4476     pCardInfo->ui32RCA       = pCard->ui32RCA;
4477     pCardInfo->ui32MaxBlks  = pCard->ui32MaxBlks;
4478     pCardInfo->ui32BlkSize  = pCard->ui32BlkSize;
4479     if ( pCard->bHighCapcity )
4480     {
4481         pCardInfo->ui32LogiMaxBlks = pCard->ui32MaxBlks;
4482         pCardInfo->ui32LogiBlkSize = pCard->ui32BlkSize;
4483     }
4484     else
4485     {
4486         pCardInfo->ui32LogiMaxBlks = (pCard->ui32MaxBlks) * ((pCard->ui32BlkSize) / 512);
4487         pCardInfo->ui32LogiBlkSize = 512;
4488     }
4489 
4490     return AM_HAL_STATUS_SUCCESS;
4491 }
4492 
4493 //
4494 //! Read single byte from SDIO card
4495 //
4496 uint32_t
am_hal_sdio_card_byte_read(am_hal_card_t * pCard,uint32_t ui32Func,uint32_t ui32Addr,uint8_t * pui8Data)4497 am_hal_sdio_card_byte_read(am_hal_card_t *pCard, uint32_t ui32Func, uint32_t ui32Addr, uint8_t *pui8Data)
4498 {
4499     uint32_t ui32Status;
4500 
4501     ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, ui32Func, ui32Addr, 0, pui8Data, true);
4502     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
4503     {
4504         AM_HAL_CARD_DEBUG("Fail to read byte from SDIO card\n");
4505         return ui32Status;
4506     }
4507 
4508     return AM_HAL_STATUS_SUCCESS;
4509 }
4510 
4511 //
4512 //! Write single byte to SDIO card
4513 //
4514 uint32_t
am_hal_sdio_card_byte_write(am_hal_card_t * pCard,uint32_t ui32Func,uint32_t ui32Addr,uint8_t ui8Data)4515 am_hal_sdio_card_byte_write(am_hal_card_t *pCard, uint32_t ui32Func, uint32_t ui32Addr, uint8_t ui8Data)
4516 {
4517     uint32_t ui32Status;
4518 
4519     ui32Status = am_hal_sdio_cmd52_io_rw_direct(pCard, ui32Func, ui32Addr, ui8Data, NULL, false);
4520     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
4521     {
4522         AM_HAL_CARD_DEBUG("Fail to write byte to SDIO card\n");
4523         return ui32Status;
4524     }
4525 
4526     return AM_HAL_STATUS_SUCCESS;
4527 }
4528 
4529 //
4530 //! Read multiple bytes/blocks from SDIO card in sync/blocking mode
4531 //
4532 uint32_t
am_hal_sdio_card_multi_bytes_read_sync(am_hal_card_t * pCard,uint32_t ui32Func,uint32_t ui32Addr,uint8_t * pui8Buf,uint32_t ui32BlkCnt,uint32_t ui32BlkSize,bool bIncrAddr)4533 am_hal_sdio_card_multi_bytes_read_sync(am_hal_card_t *pCard,
4534                                        uint32_t ui32Func,
4535                                        uint32_t ui32Addr,
4536                                        uint8_t *pui8Buf,
4537                                        uint32_t ui32BlkCnt,
4538                                        uint32_t ui32BlkSize,
4539                                        bool bIncrAddr)
4540 {
4541    return am_hal_sdio_cmd53_io_rw_extended(pCard, ui32Func, ui32Addr, pui8Buf, ui32BlkCnt, ui32BlkSize, bIncrAddr, true, false);
4542 }
4543 
4544 //
4545 //! Write multiple bytes/blocks to SDIO card in sync/blocking mode
4546 //
4547 uint32_t
am_hal_sdio_card_multi_bytes_write_sync(am_hal_card_t * pCard,uint32_t ui32Func,uint32_t ui32Addr,uint8_t * pui8Buf,uint32_t ui32BlkCnt,uint32_t ui32BlkSize,bool bIncrAddr)4548 am_hal_sdio_card_multi_bytes_write_sync(am_hal_card_t *pCard,
4549                                         uint32_t ui32Func,
4550                                         uint32_t ui32Addr,
4551                                         uint8_t *pui8Buf,
4552                                         uint32_t ui32BlkCnt,
4553                                         uint32_t ui32BlkSize,
4554                                         bool bIncrAddr)
4555 {
4556    return am_hal_sdio_cmd53_io_rw_extended(pCard, ui32Func, ui32Addr, pui8Buf, ui32BlkCnt, ui32BlkSize, bIncrAddr, false, false);
4557 }
4558 
4559 //
4560 //! Read multiple bytes/blocks from SDIO card in async/non-blocking mode
4561 //
4562 uint32_t
am_hal_sdio_card_multi_bytes_read_async(am_hal_card_t * pCard,uint32_t ui32Func,uint32_t ui32Addr,uint8_t * pui8Buf,uint32_t ui32BlkCnt,uint32_t ui32BlkSize,bool bIncrAddr)4563 am_hal_sdio_card_multi_bytes_read_async(am_hal_card_t *pCard,
4564                                         uint32_t ui32Func,
4565                                         uint32_t ui32Addr,
4566                                         uint8_t *pui8Buf,
4567                                         uint32_t ui32BlkCnt,
4568                                         uint32_t ui32BlkSize,
4569                                         bool bIncrAddr)
4570 {
4571    return am_hal_sdio_cmd53_io_rw_extended(pCard, ui32Func, ui32Addr, pui8Buf, ui32BlkCnt, ui32BlkSize, bIncrAddr, true, true);
4572 }
4573 
4574 //
4575 //! Write multiple bytes/blocks to SDIO card in async/non-blocking mode
4576 //
4577 uint32_t
am_hal_sdio_card_multi_bytes_write_async(am_hal_card_t * pCard,uint32_t ui32Func,uint32_t ui32Addr,uint8_t * pui8Buf,uint32_t ui32BlkCnt,uint32_t ui32BlkSize,bool bIncrAddr)4578 am_hal_sdio_card_multi_bytes_write_async(am_hal_card_t *pCard,
4579                                          uint32_t ui32Func,
4580                                          uint32_t ui32Addr,
4581                                          uint8_t *pui8Buf,
4582                                          uint32_t ui32BlkCnt,
4583                                          uint32_t ui32BlkSize,
4584                                          bool bIncrAddr)
4585 {
4586    return am_hal_sdio_cmd53_io_rw_extended(pCard, ui32Func, ui32Addr, pui8Buf, ui32BlkCnt, ui32BlkSize, bIncrAddr, false, true);
4587 }
4588 
4589 
4590 uint32_t
am_hal_sdio_card_calibrate(am_hal_host_inst_index_e eIndex,am_hal_host_uhs_mode_e eUHSMode,uint32_t ui32Clock,am_hal_host_bus_width_e eBusWidth,uint8_t * ui8CalibBuf,uint32_t ui32StartAddr,uint32_t ui32BlockCnt,am_hal_host_bus_voltage_e eIoVoltage,uint8_t ui8TxRxDelays[2],am_hal_card_pwr_ctrl_func pSdioCardReset)4591 am_hal_sdio_card_calibrate(am_hal_host_inst_index_e eIndex,
4592                            am_hal_host_uhs_mode_e eUHSMode,
4593                            uint32_t ui32Clock,
4594                            am_hal_host_bus_width_e eBusWidth,
4595                            uint8_t *ui8CalibBuf,
4596                            uint32_t ui32StartAddr,
4597                            uint32_t ui32BlockCnt,
4598                            am_hal_host_bus_voltage_e eIoVoltage,
4599                            uint8_t ui8TxRxDelays[2],
4600                            am_hal_card_pwr_ctrl_func pSdioCardReset)
4601 {
4602     am_hal_card_host_t *pSdhcCardHost;
4603     am_hal_card_t SdioCard;
4604 
4605     uint32_t ui32Status;
4606     uint32_t ui32BlkSize;
4607     uint32_t ui32FuncNum = 1;
4608 
4609     uint32_t i;
4610     uint32_t ui32BufLength;
4611     uint8_t  ui8TxDelay = 0;
4612     uint8_t  ui8RxDelay = 0;
4613     uint32_t ui32TxResult = 0;
4614     uint32_t ui32RxResultArray[16] = {0};
4615     uint32_t ui32MisMatchCnt = 0;
4616     uint32_t ui32WrErrCnt = 0;
4617 
4618 #ifdef AM_DEBUG_PRINTF
4619     if (eUHSMode == AM_HAL_HOST_UHS_DDR50)
4620     {
4621         AM_HAL_CARD_DEBUG("SDIO:%d Card Timing Scan for DDR %d Hz %d bit mode...\n", eIndex, ui32Clock, eBusWidth);
4622     }
4623     else
4624     {
4625         AM_HAL_CARD_DEBUG("SDIO:%d Card Timing Scan for SDR %d Hz %d bit mode...\n", eIndex, ui32Clock, eBusWidth);
4626     }
4627 #endif
4628 
4629     for (int j = 0; j < SDIO_SCAN_TXDELAY_MAX; j++)
4630     {
4631         ui32MisMatchCnt = 0;
4632         ui32WrErrCnt = 0;
4633 
4634         for (int k = 0; k < SDIO_SCAN_RXDELAY_MAX; k++)
4635         {
4636             if ( (ui32MisMatchCnt >= SDIO_CARD_MISMATCH_CNT_MAX)
4637                  || (ui32WrErrCnt >= SDIO_CARD_MISMATCH_CNT_MAX) )
4638             {
4639                 break;
4640             }
4641 
4642             //
4643             // Configure SDIO PINs.
4644             //
4645             pSdioCardReset(eIndex);
4646 
4647             //
4648             // Get the uderlying SDHC card host instance
4649             //
4650             pSdhcCardHost = am_hal_get_card_host((am_hal_host_inst_index_e)(AM_HAL_SDHC_CARD_HOST + eIndex), true);
4651             if ( pSdhcCardHost == NULL )
4652             {
4653                 AM_HAL_CARD_DEBUG("No such card host and stop\n");
4654                 return AM_HAL_STATUS_FAIL;
4655             }
4656 
4657             ui8TxRxDelays[0] = j;
4658             ui8TxRxDelays[1] = k;
4659             AM_HAL_CARD_DEBUG("Test TX delay setting SDIOOTAPDLYSEL = %d, RX delay setting SDIOITAPDLYSEL = %d\n", j, k);
4660             am_hal_card_host_set_txrx_delay(pSdhcCardHost, ui8TxRxDelays);
4661 
4662             //
4663             // check if card is present
4664             //
4665             if ( am_hal_card_host_find_card(pSdhcCardHost, &SdioCard) != AM_HAL_STATUS_SUCCESS )
4666             {
4667                 AM_HAL_CARD_DEBUG("No card is present now\n");
4668                 return AM_HAL_STATUS_FAIL;
4669             }
4670 
4671             if ( am_hal_card_init(&SdioCard, NULL, AM_HAL_CARD_PWR_CTRL_SDHC_OFF) != AM_HAL_STATUS_SUCCESS )
4672             {
4673                 AM_HAL_CARD_DEBUG("card initialization failed\n");
4674                 continue;
4675             }
4676 
4677             if ( am_hal_card_cfg_set(&SdioCard, AM_HAL_CARD_TYPE_SDIO,
4678                 eBusWidth, ui32Clock, eIoVoltage, AM_HAL_HOST_UHS_NONE) != AM_HAL_STATUS_SUCCESS )
4679             {
4680                 AM_HAL_CARD_DEBUG("sdio card config failed\n");
4681                 continue;
4682             }
4683 
4684             //
4685             // Enable SDIO card function 1
4686             //
4687             ui32Status = am_hal_sdio_card_func_enable(&SdioCard, ui32FuncNum);
4688             if ( ui32Status != AM_HAL_STATUS_SUCCESS )
4689             {
4690                 AM_HAL_CARD_DEBUG("Enable function 1 failed. Status=0x%x\n", ui32Status);
4691                 return AM_HAL_STATUS_FAIL;
4692             }
4693 
4694             //
4695             // Enable SDIO card function 1 interrupt
4696             //
4697             ui32Status = am_hal_sdio_card_func_interrupt_enable(&SdioCard, ui32FuncNum);
4698             if ( ui32Status != AM_HAL_STATUS_SUCCESS )
4699             {
4700                 AM_HAL_CARD_DEBUG("Enable function 1 interrupt failed. Status=0x%x\n", ui32Status);
4701                 return AM_HAL_STATUS_FAIL;
4702             }
4703 
4704             //
4705             // Set SDIO card function 1 block size
4706             //
4707             ui32BlkSize = 256;
4708             ui32Status = am_hal_sdio_card_set_block_size(&SdioCard, ui32FuncNum, ui32BlkSize);
4709             if ( ui32Status != AM_HAL_STATUS_SUCCESS )
4710             {
4711                 AM_HAL_CARD_DEBUG("Fail to set SDIO card function 1 block size. Status=0x%x\n", ui32Status);
4712                 return AM_HAL_STATUS_FAIL;
4713             }
4714 
4715             //
4716             // Get SDIO card function 1 block size
4717             //
4718             ui32Status = am_hal_sdio_card_get_block_size(&SdioCard, ui32FuncNum, &ui32BlkSize);
4719             if ( ui32Status != AM_HAL_STATUS_SUCCESS )
4720             {
4721                 AM_HAL_CARD_DEBUG("Fail to check SDIO card function 1 block size. Status=0x%x\n", ui32Status);
4722                 return AM_HAL_STATUS_FAIL;
4723             }
4724 
4725             ui32BufLength = ui32BlockCnt*ui32BlkSize;
4726 
4727             for (i = 0; i < ui32BufLength; i++)
4728             {
4729                 ui8CalibBuf[i] = i % 256;
4730             }
4731 
4732             ui32Status = am_hal_sdio_card_multi_bytes_write_sync(&SdioCard, ui32FuncNum, ui32StartAddr, (uint8_t *)ui8CalibBuf, ui32BlockCnt, ui32BlkSize, true);
4733             if ( (ui32Status & 0xffff) != AM_HAL_STATUS_SUCCESS )
4734             {
4735                 ui32WrErrCnt ++;
4736                 AM_HAL_CARD_DEBUG("Sdio Card calibration write fail. Status=0x%x\n", ui32Status & 0xffff);
4737                 continue;
4738             }
4739 
4740             memset((void *)ui8CalibBuf, 0x0, ui32BufLength);
4741 
4742             ui32Status = am_hal_sdio_card_multi_bytes_read_sync(&SdioCard, ui32FuncNum, ui32StartAddr, (uint8_t *)ui8CalibBuf, ui32BlockCnt, ui32BlkSize, true);
4743             if ( (ui32Status & 0xffff)  != AM_HAL_STATUS_SUCCESS )
4744             {
4745                 ui32WrErrCnt ++;
4746                 AM_HAL_CARD_DEBUG("Sdio Card calibration read fail. Status=0x%x\n", ui32Status & 0xffff);
4747                 continue;
4748             }
4749 
4750             for (i = 0; i < ui32BufLength; i++)
4751             {
4752                 if (ui8CalibBuf[i] != i % 256)
4753                 {
4754                     ui32MisMatchCnt ++;
4755                     break;
4756                 }
4757             }
4758 
4759             if (i == ui32BufLength)
4760             {
4761                 ui32RxResultArray[j] |= 0x01 << k;
4762                 AM_HAL_CARD_DEBUG("TX Delay SDIOOTAPDLYSEL = %d, RX Delay SDIOITAPDLYSEL = %d works\n", j, k);
4763             }
4764             else
4765             {
4766                 AM_HAL_CARD_DEBUG("TX Delay SDIOOTAPDLYSEL = %d, RX Delay SDIOITAPDLYSEL = %d doesn't work\n", j, k);
4767             }
4768         }
4769     }
4770 
4771 #ifdef AM_DEBUG_PRINTF
4772     AM_HAL_CARD_DEBUG("\nSDIO TX RX Delay Scan Result:\n");
4773     for (i = 0; i < 16; i++ )
4774     {
4775         AM_HAL_CARD_DEBUG("TX_Delay = %2d, RX_Delay Window = 0x%08X\n", i, ui32RxResultArray[i]);
4776     }
4777 #endif
4778 
4779     uint32_t ui32Result = 0;
4780     for (i = 0; i < SDIO_SCAN_TXDELAY_MAX; i++ )
4781     {
4782         ui32Result = count_consecutive_ones(&ui32RxResultArray[i]);
4783         if ( ui32Result >= SDIO_TIMING_SCAN_MIN_ACCEPTANCE_LENGTH )
4784         {
4785             ui32TxResult |= 0x01 << i;
4786         }
4787     }
4788 
4789     //
4790     // Check consecutive passing settings
4791     //
4792     if ( ui32TxResult == 0 )
4793     {
4794         //
4795         // No acceptable window
4796         //
4797         return AM_HAL_STATUS_FAIL;
4798     }
4799     else
4800     {
4801         ui32Result = count_consecutive_ones(&ui32TxResult);
4802         if ( ui32Result < SDIO_TIMING_SCAN_MIN_ACCEPTANCE_LENGTH )
4803         {
4804             //
4805             // No acceptable window
4806             //
4807             return AM_HAL_STATUS_FAIL;
4808         }
4809     }
4810 
4811     //
4812     // Find TX Delay Value
4813     //
4814     ui8TxDelay = find_mid_point(&ui32TxResult);
4815 
4816     AM_HAL_CARD_DEBUG("\nSDIO Card Timing Scan found a RX delay window %X with TX delay Setting = %d.\n", ui32RxResultArray[ui8TxDelay], ui8TxDelay);
4817 
4818     //
4819     // Find RX Delay Value
4820     //
4821     ui8RxDelay = find_mid_point(&ui32RxResultArray[ui8TxDelay]);
4822     ui8TxRxDelays[0] = ui8TxDelay;
4823     ui8TxRxDelays[1] = ui8RxDelay;
4824 
4825     AM_HAL_CARD_DEBUG("Timing Scan set the SDIO TX delay to %d and RX delay to %d.\n", ui8TxDelay, ui8RxDelay);
4826 
4827     //
4828     // Force the card host to reset with the calibration settings
4829     //
4830     pSdhcCardHost = am_hal_get_card_host(eIndex, true);
4831 
4832     if (pSdhcCardHost == NULL)
4833     {
4834         AM_HAL_CARD_DEBUG("No such card host and stop\n");
4835         return AM_HAL_STATUS_FAIL;
4836     }
4837     am_hal_card_host_set_txrx_delay(pSdhcCardHost, ui8TxRxDelays);
4838 
4839     return AM_HAL_STATUS_SUCCESS;
4840 }
4841 
4842 uint32_t
am_hal_card_block_rpmb_rw(am_hal_card_t * pCard,uint8_t * pui8Buf,bool bRead,bool bRelWrite)4843 am_hal_card_block_rpmb_rw(am_hal_card_t *pCard, uint8_t *pui8Buf, bool bRead, bool bRelWrite)
4844 {
4845     uint32_t ui32Status;
4846 
4847     am_hal_card_host_t *pHost;
4848     am_hal_card_cmd_t cmd;
4849     am_hal_card_cmd_data_t cmd_data;
4850 
4851 #ifndef AM_HAL_DISABLE_API_VALIDATION
4852 
4853     if ( !pCard || !pCard->pHost )
4854     {
4855         return AM_HAL_STATUS_INVALID_ARG;
4856     }
4857 
4858 #endif // AM_HAL_DISABLE_API_VALIDATION
4859 
4860     if ( pCard->eState != AM_HAL_CARD_STATE_TRANS )
4861     {
4862         return AM_HAL_STATUS_INVALID_OPERATION;
4863     }
4864 
4865     pHost = pCard->pHost;
4866 
4867     //
4868     // Send CMD23 firstly for mulitple blocks transfer
4869     //
4870     memset((void *)&cmd, 0x0, sizeof(cmd));
4871 
4872     cmd.ui8Idx = MMC_CMD_SET_BLOCK_COUNT;
4873     cmd.ui32RespType = MMC_RSP_R1;
4874     cmd.ui32Arg = 1;
4875 
4876     if ( bRelWrite )
4877     {
4878         cmd.ui32Arg |= ((uint32_t)0x01 << 31);
4879     }
4880 
4881     if ( (ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL)) != AM_HAL_STATUS_SUCCESS )
4882     {
4883         return ui32Status;
4884     }
4885 
4886     memset((void *)&cmd, 0x0, sizeof(cmd));
4887     memset((void *)&cmd_data, 0x0, sizeof(cmd_data));
4888     if ( bRead )
4889     {
4890         cmd.ui8Idx = MMC_CMD_READ_MULTIPLE_BLOCK;
4891     }
4892     else
4893     {
4894         cmd.ui8Idx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
4895     }
4896 
4897     cmd.ui32Arg = 0;
4898     cmd.ui32RespType = MMC_RSP_R1;
4899     cmd.bASync = false;
4900     cmd.bAutoCMD23 = false;
4901 
4902     cmd_data.ui8IovCnt = 0;
4903     cmd_data.ui32BlkCnt = 1;
4904     cmd_data.pui8Buf = pui8Buf;
4905     cmd_data.ui32BlkSize = 512;
4906     cmd_data.dir = bRead ? AM_HAL_DATA_DIR_READ : AM_HAL_DATA_DIR_WRITE;
4907 
4908     ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, &cmd_data);
4909 
4910     return ui32Status;
4911 }
4912 
4913 static uint32_t
am_hal_sd_card_block_rw(am_hal_card_t * pCard,uint32_t ui32Blk,uint32_t ui32BlkCnt,uint8_t * pui8Buf,bool bRead,bool bASync)4914 am_hal_sd_card_block_rw(am_hal_card_t *pCard, uint32_t ui32Blk, uint32_t ui32BlkCnt, uint8_t *pui8Buf, bool bRead, bool bASync)
4915 {
4916     uint32_t ui32Status;
4917 
4918     am_hal_card_host_t *pHost;
4919     am_hal_card_cmd_t cmd;
4920     am_hal_card_cmd_data_t cmd_data;
4921 
4922 #ifndef AM_HAL_DISABLE_API_VALIDATION
4923 
4924     if ( !pCard || !pCard->pHost )
4925     {
4926         return AM_HAL_STATUS_INVALID_ARG;
4927     }
4928 
4929 #endif // AM_HAL_DISABLE_API_VALIDATION
4930 
4931     if ( pCard->eState != AM_HAL_CARD_STATE_TRANS )
4932     {
4933         return AM_HAL_STATUS_INVALID_OPERATION;
4934     }
4935 
4936     pHost = pCard->pHost;
4937 
4938     //
4939     // Check if the start block number and block count is valid or not
4940     //
4941     if ( ui32Blk >= pCard->ui32MaxBlks || (ui32BlkCnt > 0xFFFF) || (ui32Blk + ui32BlkCnt) > pCard->ui32MaxBlks )
4942     {
4943         return AM_HAL_STATUS_OUT_OF_RANGE;
4944     }
4945 
4946     if ( pHost->eXferMode == AM_HAL_HOST_XFER_ADMA && ui32BlkCnt > pHost->ui32MaxADMA2BlkNums )
4947     {
4948         ui32BlkCnt = pHost->ui32MaxADMA2BlkNums;
4949     }
4950 
4951     memset((void *)&cmd, 0x0, sizeof(cmd));
4952     memset((void *)&cmd_data, 0x0, sizeof(cmd_data));
4953     if ( bRead )
4954     {
4955         cmd.ui8Idx = ui32BlkCnt > 1 ? MMC_CMD_READ_MULTIPLE_BLOCK : MMC_CMD_READ_SINGLE_BLOCK;
4956     }
4957     else
4958     {
4959         cmd.ui8Idx = ui32BlkCnt > 1 ? MMC_CMD_WRITE_MULTIPLE_BLOCK : MMC_CMD_WRITE_SINGLE_BLOCK;
4960     }
4961 
4962     cmd.ui32Arg = pCard->bHighCapcity ? ui32Blk : ui32Blk * pCard->ui32BlkSize;
4963     cmd.ui32RespType = MMC_RSP_R1;
4964     cmd.bASync = bASync;
4965     cmd.bAutoCMD12 = ui32BlkCnt > 1 ? true : false;
4966 
4967     cmd_data.ui8IovCnt = 0;
4968     cmd_data.pui8Buf = pui8Buf;
4969     cmd_data.ui32BlkCnt = ui32BlkCnt;
4970     cmd_data.ui32BlkSize = pCard->ui32BlkSize;
4971     cmd_data.dir = bRead ? AM_HAL_DATA_DIR_READ : AM_HAL_DATA_DIR_WRITE;
4972 
4973     if ( cmd.bASync )
4974     {
4975         pHost->AsyncCmd = cmd;
4976         pHost->AsyncCmdData = cmd_data;
4977     }
4978 
4979     ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, &cmd_data);
4980 
4981     return ui32Status;
4982 }
4983 
4984 //*****************************************************************************
4985 //
4986 // SD card synchronous block-oriented read function
4987 //
4988 //*****************************************************************************
4989 uint32_t
am_hal_sd_card_block_read_sync(am_hal_card_t * pCard,uint32_t ui32Blk,uint32_t ui32BlkCnt,uint8_t * pui8Buf)4990 am_hal_sd_card_block_read_sync(am_hal_card_t *pCard, uint32_t ui32Blk, uint32_t ui32BlkCnt, uint8_t *pui8Buf)
4991 {
4992     return am_hal_sd_card_block_rw(pCard, ui32Blk, ui32BlkCnt, pui8Buf, true, false);
4993 }
4994 
4995 //*****************************************************************************
4996 //
4997 // SD card synchronous block-oriented write function
4998 //
4999 //*****************************************************************************
5000 uint32_t
am_hal_sd_card_block_write_sync(am_hal_card_t * pCard,uint32_t ui32Blk,uint32_t ui32BlkCnt,uint8_t * pui8Buf)5001 am_hal_sd_card_block_write_sync(am_hal_card_t *pCard, uint32_t ui32Blk, uint32_t ui32BlkCnt, uint8_t *pui8Buf)
5002 {
5003     if ( pCard->sdcard.bWrProtect )
5004     {
5005         AM_HAL_CARD_DEBUG("SD Card is protected, fail to write sd card\n");
5006         return AM_HAL_STATUS_INVALID_OPERATION;
5007     }
5008 
5009     return am_hal_sd_card_block_rw(pCard, ui32Blk, ui32BlkCnt, pui8Buf, false, false);
5010 }
5011 
5012 //*****************************************************************************
5013 //
5014 // SD card asynchronous block-oriented read function
5015 //
5016 //*****************************************************************************
5017 uint32_t
am_hal_sd_card_block_read_async(am_hal_card_t * pCard,uint32_t ui32Blk,uint32_t ui32BlkCnt,uint8_t * pui8Buf)5018 am_hal_sd_card_block_read_async(am_hal_card_t *pCard, uint32_t ui32Blk, uint32_t ui32BlkCnt, uint8_t *pui8Buf)
5019 {
5020     return am_hal_sd_card_block_rw(pCard, ui32Blk, ui32BlkCnt, pui8Buf, true, true);
5021 }
5022 
5023 //*****************************************************************************
5024 //
5025 // SD card asynchronous block-oriented write function
5026 //
5027 //*****************************************************************************
5028 uint32_t
am_hal_sd_card_block_write_async(am_hal_card_t * pCard,uint32_t ui32Blk,uint32_t ui32BlkCnt,uint8_t * pui8Buf)5029 am_hal_sd_card_block_write_async(am_hal_card_t *pCard, uint32_t ui32Blk, uint32_t ui32BlkCnt, uint8_t *pui8Buf)
5030 {
5031     if ( pCard->sdcard.bWrProtect )
5032     {
5033         AM_HAL_CARD_DEBUG("SD Card is protected, fail to write sd card\n");
5034         return AM_HAL_STATUS_INVALID_OPERATION;
5035     }
5036 
5037     return am_hal_sd_card_block_rw(pCard, ui32Blk, ui32BlkCnt, pui8Buf, false, true);
5038 }
5039 
5040 //*****************************************************************************
5041 //
5042 // SD card block-oriented erase function
5043 //
5044 //*****************************************************************************
5045 uint32_t
am_hal_sd_card_block_erase(am_hal_card_t * pCard,uint32_t ui32Blk,uint32_t ui32BlkCnt,uint32_t ui32TimeoutMS)5046 am_hal_sd_card_block_erase(am_hal_card_t *pCard, uint32_t ui32Blk, uint32_t ui32BlkCnt, uint32_t ui32TimeoutMS)
5047 {
5048     uint32_t ui32Status;
5049     am_hal_card_host_t *pHost;
5050     am_hal_card_cmd_t cmd;
5051 
5052 #ifndef AM_HAL_DISABLE_API_VALIDATION
5053 
5054     if ( !pCard || !pCard->pHost )
5055     {
5056         return AM_HAL_STATUS_INVALID_ARG;
5057     }
5058 
5059 #endif // AM_HAL_DISABLE_API_VALIDATION
5060 
5061     if ( pCard->eState != AM_HAL_CARD_STATE_TRANS )
5062     {
5063         return AM_HAL_STATUS_INVALID_OPERATION;
5064     }
5065 
5066     //
5067     // Check if the start block number and block count is valid or not
5068     //
5069     if ( ui32Blk >= pCard->ui32MaxBlks || ui32Blk + ui32BlkCnt > pCard->ui32MaxBlks )
5070     {
5071         return AM_HAL_STATUS_OUT_OF_RANGE;
5072     }
5073 
5074    pHost = pCard->pHost;
5075 
5076     //
5077     // Define the erase start address
5078     //
5079     memset((void *)&cmd, 0x0, sizeof(cmd));
5080     cmd.ui8Idx = SD_CMD_ERASE_WR_BLK_START;
5081     cmd.ui32Arg = pCard->bHighCapcity ? ui32Blk : ui32Blk * pCard->ui32BlkSize;
5082     cmd.ui32RespType = MMC_RSP_R1;
5083 
5084     if ( (ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL)) != AM_HAL_STATUS_SUCCESS )
5085     {
5086         return ui32Status;
5087     }
5088 
5089     //
5090     // Define the erase end address
5091     //
5092     memset((void *)&cmd, 0x0, sizeof(cmd));
5093     cmd.ui8Idx = SD_CMD_ERASE_WR_BLK_END;
5094     cmd.ui32Arg = pCard->bHighCapcity ? (ui32Blk + ui32BlkCnt - 1) : (ui32Blk + ui32BlkCnt - 1) * pCard->ui32BlkSize;
5095     cmd.ui32RespType = MMC_RSP_R1;
5096 
5097     if ( (ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL)) != AM_HAL_STATUS_SUCCESS )
5098     {
5099         return ui32Status;
5100     }
5101 
5102     //
5103     // Do the erase job
5104     //
5105     memset((void *)&cmd, 0x0, sizeof(cmd));
5106     cmd.bCheckBusyCmd = true;
5107     cmd.ui8Idx = MMC_CMD_ERASE;
5108     cmd.ui32Arg = 0;
5109     cmd.ui32RespType = MMC_RSP_R1b;
5110 
5111     if ( (ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL)) != AM_HAL_STATUS_SUCCESS )
5112     {
5113         return ui32Status;
5114     }
5115 
5116     return pHost->ops->card_busy(pHost->pHandle, ui32TimeoutMS);
5117 }
5118 
5119 //*****************************************************************************
5120 //
5121 // End Doxygen group.
5122 //! @}
5123 //
5124 //*****************************************************************************
5125