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