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 release_sdk_4_4_0-3c5977e664 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 // Internal macros
59 //
60 #define SDIO_TIMING_SCAN_MIN_ACCEPTANCE_LENGTH 2 // Acceptable length should be determined based on system level test.
61 #define AM_HAL_CARD_DEBUG(fmt, ...) am_util_debug_printf("[CARD] line %04d - "fmt, __LINE__, ##__VA_ARGS__)
62
63 //
64 // Private internal functions
65 //
66
67 //
68 //! CMD0 - go idle
69 //
am_hal_sdmmc_cmd0_go_idle(am_hal_card_t * pCard)70 static inline uint32_t am_hal_sdmmc_cmd0_go_idle(am_hal_card_t *pCard)
71 {
72 am_hal_card_cmd_t cmd;
73 am_hal_card_host_t *pHost = pCard->pHost;
74
75 memset(&cmd, 0, sizeof(cmd));
76 cmd.ui8Idx = MMC_CMD_GO_IDLE_STATE;
77 cmd.ui32Arg = 0x0;
78 cmd.ui32RespType = MMC_RSP_NONE;
79
80 pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL);
81
82 return cmd.eError;
83 }
84
85
86 #define SECTOR_MODE 0x4
87 #define CMD1_CARD_RDY_BIT ((uint32_t)0x1 << 31)
88 //
89 //! CMD1 - send operation condition
90 //
am_hal_sdmmc_cmd1_send_op_cond(am_hal_card_t * pCard)91 static inline uint32_t am_hal_sdmmc_cmd1_send_op_cond(am_hal_card_t *pCard)
92 {
93 uint32_t ui32CardOCR = 0;
94 uint8_t ui8Tries = 100;
95
96 am_hal_card_cmd_t cmd;
97 am_hal_card_host_t *pHost = pCard->pHost;
98
99 memset(&cmd, 0, sizeof(cmd));
100 cmd.ui8Idx = MMC_CMD_SEND_OP_COND;
101 cmd.ui32Arg = SECTOR_MODE << 28;
102 cmd.ui32RespType = MMC_RSP_R3;
103
104 do
105 {
106 pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL);
107
108 if ( cmd.eError == AM_HAL_CMD_ERR_NONE )
109 {
110 ui32CardOCR = cmd.ui32Resp[0];
111 cmd.ui32Arg |= ui32CardOCR;
112 }
113
114 if ( ui32CardOCR & CMD1_CARD_RDY_BIT )
115 {
116 pCard->ui32OCR = ui32CardOCR;
117 break;
118 }
119
120 am_util_delay_ms(10);
121 } while (--ui8Tries != 0);
122
123 return ui8Tries == 0x0 ? AM_HAL_CMD_ERR_TIMEOUT : cmd.eError;
124 }
125
126 //
127 //! CMD2 - send card identification
128 //
am_hal_sdmmc_cmd2_send_cid(am_hal_card_t * pCard)129 static inline uint32_t am_hal_sdmmc_cmd2_send_cid(am_hal_card_t *pCard)
130 {
131 am_hal_card_cmd_t cmd;
132 am_hal_card_host_t *pHost = pCard->pHost;
133
134 memset(&cmd, 0, sizeof(cmd));
135 cmd.ui8Idx = MMC_CMD_ALL_SEND_CID;
136 cmd.ui32Arg = 0x0;
137 cmd.ui32RespType = MMC_RSP_R2;
138
139 pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL);
140
141 if ( cmd.eError == AM_HAL_CMD_ERR_NONE )
142 {
143 memcpy((void *)pCard->ui32CID, (void *)&cmd.ui32Resp[0], 16);
144 pCard->bCidValid = 1;
145 }
146
147 return cmd.eError;
148 }
149
150 //
151 //! CMD3 - set the relative card address
152 //
am_hal_sdmmc_cmd3_set_rca(am_hal_card_t * pCard,uint16_t ui16RCA)153 static inline uint32_t am_hal_sdmmc_cmd3_set_rca(am_hal_card_t *pCard, uint16_t ui16RCA)
154 {
155 am_hal_card_cmd_t cmd;
156 am_hal_card_host_t *pHost = pCard->pHost;
157
158 memset(&cmd, 0, sizeof(cmd));
159 cmd.ui8Idx = MMC_CMD_SET_RELATIVE_ADDR;
160 cmd.ui32Arg = ui16RCA << 16;
161 cmd.ui32RespType = MMC_RSP_R1;
162
163 pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL);
164
165 if ( cmd.eError == AM_HAL_CMD_ERR_NONE )
166 {
167 pCard->ui8RCA = ui16RCA;
168 }
169
170 return cmd.eError;
171 }
172
173 //
174 //! CMD5 - Sleep/Awake
175 //
am_hal_sdmmc_cmd5(am_hal_card_t * pCard,bool sleep)176 static uint32_t am_hal_sdmmc_cmd5(am_hal_card_t *pCard, bool sleep)
177 {
178 uint32_t ui32Status;
179 am_hal_card_cmd_t cmd;
180 am_hal_card_host_t *pHost = pCard->pHost;
181
182 memset(&cmd, 0, sizeof(cmd));
183 cmd.ui8Idx = MMC_CMD_SLEEP_AWAKE;
184 cmd.ui32Arg = pCard->ui8RCA << 16 | sleep << 15;
185 cmd.ui32RespType = MMC_RSP_R1b;
186 cmd.bCheckBusyCmd = true;
187
188 if ( (ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL)) != AM_HAL_STATUS_SUCCESS )
189 {
190 return ui32Status;
191 }
192
193 if ( cmd.eError == AM_HAL_CMD_ERR_NONE )
194 {
195 if ( sleep == true )
196 {
197 pCard->eState = AM_HAL_CARD_STATE_SLP;
198 }
199 else
200 {
201 pCard->eState = AM_HAL_CARD_STATE_STDY;
202 }
203 }
204
205 if ((ui32Status = pHost->ops->card_busy(pHost->pHandle, 20)) != AM_HAL_STATUS_SUCCESS)
206 {
207 return ui32Status;
208 }
209
210 return AM_HAL_STATUS_SUCCESS;
211 }
212
213 //
214 //! CMD7 - select the card
215 //
216
am_hal_sdmmc_cmd7_card_select(am_hal_card_t * pCard)217 static uint32_t am_hal_sdmmc_cmd7_card_select(am_hal_card_t *pCard)
218 {
219 am_hal_card_cmd_t cmd;
220 am_hal_card_host_t *pHost = pCard->pHost;
221
222 memset(&cmd, 0, sizeof(cmd));
223 cmd.ui8Idx = MMC_CMD_SELECT_CARD;
224 cmd.ui32Arg = pCard->ui8RCA << 16;
225
226 //
227 // RCA of zero is not valid for a card select, so this
228 // is a card deselect which requires no response
229 //
230 if ( pCard->ui8RCA == 0x0 )
231 {
232 cmd.ui32RespType = MMC_RSP_NONE;
233 }
234 else
235 {
236 cmd.ui32RespType = MMC_RSP_R1;
237 }
238
239 pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL);
240
241 if ( cmd.eError == AM_HAL_CMD_ERR_NONE )
242 {
243 //
244 // For a card deselect, the state is stand-by-state
245 //
246 if ( pCard->ui8RCA == 0x0 )
247 {
248 pCard->eState = AM_HAL_CARD_STATE_STDY;
249 }
250 //
251 // for a card select, the state is the transfer state
252 //
253 else
254 {
255 pCard->eState = AM_HAL_CARD_STATE_TRANS;
256 }
257 }
258
259 return cmd.eError;
260 }
261
262 //
263 //! CMD7 - select/deselect the card
264 //
am_hal_sdmmc_cmd7_card_deselect(am_hal_card_t * pCard)265 static uint32_t am_hal_sdmmc_cmd7_card_deselect(am_hal_card_t *pCard)
266 {
267 uint8_t ui8RCA = pCard->ui8RCA;
268 uint32_t ui32Status = AM_HAL_STATUS_SUCCESS;
269
270 pCard->ui8RCA = 0;
271 if ( AM_HAL_CMD_ERR_NONE != am_hal_sdmmc_cmd7_card_select(pCard) )
272 {
273 AM_HAL_CARD_DEBUG("sleep - am_hal_sdmmc_cmd7_card_select Failed\n");
274 ui32Status = AM_HAL_STATUS_FAIL;
275 }
276 pCard->ui8RCA = ui8RCA;
277
278 return ui32Status;
279 }
280
281 //
282 //! CMD8 - get the 512 bytes ext csd
283 //
am_hal_sdmmc_cmd8_send_ext_csd(am_hal_card_t * pCard)284 static uint32_t am_hal_sdmmc_cmd8_send_ext_csd(am_hal_card_t *pCard)
285 {
286 am_hal_card_cmd_t cmd;
287 am_hal_card_cmd_data_t cmd_data;
288 am_hal_card_host_t *pHost = pCard->pHost;
289
290 memset(&cmd, 0x0, sizeof(cmd));
291 memset(&cmd_data, 0x0, sizeof(cmd_data));
292
293 cmd.ui8Idx = MMC_CMD_SEND_EXT_CSD;
294 cmd.ui32Arg = pCard->ui8RCA << 16;
295 cmd.ui32RespType = MMC_RSP_R1;
296
297 cmd_data.pui8Buf = (uint8_t *)pCard->ui32ExtCSD;
298 cmd_data.ui32BlkCnt = 1;
299 cmd_data.ui32BlkSize = 512;
300 cmd_data.dir = AM_HAL_DATA_DIR_READ;
301
302 pHost->ops->execute_cmd(pHost->pHandle, &cmd, &cmd_data);
303
304 if ( cmd.eError == AM_HAL_CMD_ERR_NONE )
305 {
306 pCard->bExtCsdValid = 1;
307 }
308
309 return cmd.eError;
310 }
311
312 //
313 //! CMD9 - get the CSD
314 //
am_hal_sdmmc_cmd9_send_csd(am_hal_card_t * pCard)315 static inline uint32_t am_hal_sdmmc_cmd9_send_csd(am_hal_card_t *pCard)
316 {
317 am_hal_card_cmd_t cmd;
318 am_hal_card_host_t *pHost = pCard->pHost;
319
320 memset(&cmd, 0, sizeof(cmd));
321 cmd.ui8Idx = MMC_CMD_SEND_CSD;
322 cmd.ui32Arg = pCard->ui8RCA << 16;
323 cmd.ui32RespType = MMC_RSP_R2;
324
325 pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL);
326
327 if ( cmd.eError == AM_HAL_CMD_ERR_NONE )
328 {
329 memcpy((void *)pCard->ui32CSD, (void *)&cmd.ui32Resp[0], 16);
330 pCard->bCsdValid = 1;
331 }
332
333 return cmd.eError;
334 }
335
336 //
337 //! Card Cache Control
338 //
339 static uint32_t
am_hal_card_cache_ctrl(am_hal_card_t * pCard,bool bCacheEnable)340 am_hal_card_cache_ctrl(am_hal_card_t *pCard, bool bCacheEnable)
341 {
342 uint32_t ui32Mode;
343 #ifndef AM_HAL_DISABLE_API_VALIDATION
344 if ( !pCard || !pCard->pHost )
345 {
346 AM_HAL_CARD_DEBUG("This card is not connected to a host\n");
347 return AM_HAL_STATUS_INVALID_ARG;
348 }
349 #endif // AM_HAL_DISABLE_API_VALIDATION
350
351 if (pCard->ui32CacheSize > 0)
352 {
353 ui32Mode = MMC_EXT_MODE_WRITE_BYTE | (MMC_EXT_REGS_CACHE_CTRL << 16) | (bCacheEnable ? (1 << 8) : 0);
354 return am_hal_card_mode_switch(pCard, ui32Mode, DEFAULT_CMD6_TIMEOUT_MS);
355 }
356
357 return AM_HAL_STATUS_INVALID_OPERATION;
358 }
359
360 //
361 //! Card Cache On
362 //
363 static inline uint32_t
am_hal_card_cache_on(am_hal_card_t * pCard)364 am_hal_card_cache_on(am_hal_card_t *pCard)
365 {
366 return am_hal_card_cache_ctrl(pCard, true);
367 }
368
369 //
370 //! Card Cache Off
371 //
372 static inline uint32_t
am_hal_card_cache_off(am_hal_card_t * pCard)373 am_hal_card_cache_off(am_hal_card_t *pCard)
374 {
375 return am_hal_card_cache_ctrl(pCard, false);
376 }
377
378 //
379 //! Card Power Notification
380 //
381 static uint32_t
am_hal_card_pwr_notification(am_hal_card_t * pCard,uint8_t ui8NotifyType)382 am_hal_card_pwr_notification(am_hal_card_t *pCard,
383 uint8_t ui8NotifyType)
384 {
385 uint32_t ui32Mode;
386 uint32_t ui32Timeout;
387
388 #ifndef AM_HAL_DISABLE_API_VALIDATION
389 if ( !pCard || !pCard->pHost )
390 {
391 AM_HAL_CARD_DEBUG("This card is not connected to a host\n");
392 return AM_HAL_STATUS_INVALID_ARG;
393 }
394 #endif // AM_HAL_DISABLE_API_VALIDATION
395
396 if (pCard->ui8ExtCSDRev < 6)
397 {
398 AM_HAL_CARD_DEBUG("this eMMC card type is not supporting notification\n");
399 return AM_HAL_STATUS_INVALID_OPERATION;
400 }
401
402 ui32Mode = MMC_EXT_MODE_WRITE_BYTE | MMC_EXT_REGS_PWR_OFF_NOTIFY << 16 | ui8NotifyType << 8;
403
404 //
405 // Timeout Selection based upon notification type
406 //
407 switch (ui8NotifyType)
408 {
409 case MMC_EXT_CSD_POWER_OFF_LONG:
410 ui32Timeout = pCard->ui32PowerOffNotificationLongTimeout;
411 break;
412 case MMC_EXT_CSD_SLEEP_NOTIFICATION:
413 ui32Timeout = pCard->ui32SleepNotificationTimeout;
414 break;
415 case MMC_EXT_CSD_POWERED_ON:
416 ui32Timeout = DEFAULT_CMD6_TIMEOUT_MS;
417 break;
418 default:
419 AM_HAL_CARD_DEBUG("Unknown notification type\n");
420 return AM_HAL_STATUS_INVALID_ARG;
421 }
422
423 if (am_hal_card_mode_switch(pCard, ui32Mode, ui32Timeout) != AM_HAL_STATUS_SUCCESS)
424 {
425 AM_HAL_CARD_DEBUG("Unknown notification type\n");
426 return AM_HAL_STATUS_FAIL;
427 }
428
429 pCard->ui8PowerOffNotification = ui8NotifyType;
430
431 return AM_HAL_STATUS_SUCCESS;
432 }
433
434 //
435 //! Card MMC Init
436 //
437 static uint32_t
am_hal_card_mmc_init(am_hal_card_t * pCard)438 am_hal_card_mmc_init(am_hal_card_t *pCard)
439 {
440 uint32_t ui32RetVal = AM_HAL_STATUS_SUCCESS;
441
442 //
443 // Reset the card
444 //
445 if ( am_hal_sdmmc_cmd0_go_idle(pCard) != AM_HAL_CMD_ERR_NONE )
446 {
447 AM_HAL_CARD_DEBUG("CMD0 Failed\n");
448 return AM_HAL_STATUS_FAIL;
449 }
450
451 //
452 // Set the operation condition of the card
453 //
454 if ( am_hal_sdmmc_cmd1_send_op_cond(pCard) != AM_HAL_CMD_ERR_NONE )
455 {
456 AM_HAL_CARD_DEBUG("CMD1 Failed\n");
457 return AM_HAL_STATUS_FAIL;
458 }
459
460 //
461 // Get the CID information of the card
462 //
463 if ( am_hal_sdmmc_cmd2_send_cid(pCard) != AM_HAL_CMD_ERR_NONE )
464 {
465 AM_HAL_CARD_DEBUG("CMD2 Failed\n");
466 return AM_HAL_STATUS_FAIL;
467 }
468
469 //
470 // Set relative card address to 0x1
471 //
472 if ( am_hal_sdmmc_cmd3_set_rca(pCard, 0x1) != AM_HAL_CMD_ERR_NONE )
473 {
474 AM_HAL_CARD_DEBUG("CMD3 Failed\n");
475 return AM_HAL_STATUS_FAIL;
476 }
477
478 //
479 // Get the card CSD
480 //
481 if ( am_hal_sdmmc_cmd9_send_csd(pCard) != AM_HAL_CMD_ERR_NONE )
482 {
483 AM_HAL_CARD_DEBUG("CMD9 Failed\n");
484 return AM_HAL_STATUS_FAIL;
485 }
486
487 //
488 // Select the card
489 //
490 if ( am_hal_sdmmc_cmd7_card_select(pCard) != AM_HAL_CMD_ERR_NONE )
491 {
492 AM_HAL_CARD_DEBUG("CMD7 Failed\n");
493 return AM_HAL_STATUS_FAIL;
494 }
495
496 //
497 // Get the ext csd
498 //
499 if ( am_hal_sdmmc_cmd8_send_ext_csd(pCard) != AM_HAL_CMD_ERR_NONE )
500 {
501 AM_HAL_CARD_DEBUG("CMD8 Failed\n");
502 return AM_HAL_STATUS_FAIL;
503 }
504
505 //
506 // Parse the CSD and EXT CSD to know the feature of card
507 //
508 uint32_t ui32CSize = am_hal_unstuff_bits(pCard->ui32CSD, 62, 12);
509 pCard->bHighCapcity = (ui32CSize == 0xFFF) ? true : false;
510
511 //
512 // High capacity card
513 //
514 if ( pCard->bHighCapcity )
515 {
516 //
517 // get blksize and capacity information from the ext csd
518 //
519 pCard->ui32BlkSize = am_hal_unstuff_bytes(pCard->ui32ExtCSD, 61, 1) ? 4096 : 512;
520 pCard->bUseBlkEmulation = am_hal_unstuff_bytes(pCard->ui32ExtCSD, 62, 1) ? false : true;
521 pCard->ui32NativeBlkSize = am_hal_unstuff_bytes(pCard->ui32ExtCSD, 63, 1) ? 4096 : 512;
522 pCard->ui16CmdClass = am_hal_unstuff_bits(pCard->ui32CSD, 84, 12);
523 pCard->ui8SpecVer = am_hal_unstuff_bits(pCard->ui32CSD, 122, 4);
524 pCard->ui32RpmbSizeMult = am_hal_unstuff_bytes(pCard->ui32ExtCSD, 168, 1);
525 pCard->ui8ExtCSDRev = am_hal_unstuff_bytes(pCard->ui32ExtCSD, 192, 1);
526 pCard->ui8DeviceType = am_hal_unstuff_bytes(pCard->ui32ExtCSD, 196, 1);
527 pCard->ui32MaxBlks = am_hal_unstuff_bytes(pCard->ui32ExtCSD, 212, 4);
528 pCard->ui32Capacity = pCard->ui32MaxBlks*pCard->ui32BlkSize;
529 pCard->ui32CacheSize = am_hal_unstuff_bytes(pCard->ui32ExtCSD, 249, 4);
530 pCard->ui8SecureErase = am_hal_unstuff_bytes(pCard->ui32ExtCSD, 231, 1);
531 pCard->ui32GenericCmd6Timeout = DEFAULT_CMD6_TIMEOUT_MS;
532 if (pCard->ui8ExtCSDRev >= 6)
533 {
534 pCard->ui32SleepNotificationTimeout = am_hal_unstuff_bytes(pCard->ui32ExtCSD, 216, 1)*10;
535 pCard->ui32PowerOffNotificationLongTimeout = am_hal_unstuff_bytes(pCard->ui32ExtCSD, 247, 1)*10;
536 pCard->ui32GenericCmd6Timeout = am_hal_unstuff_bytes(pCard->ui32ExtCSD, 248, 1)*10;
537 }
538 }
539 else
540 {
541 //
542 // non high capacity card gets blksize and capacity information from the CSD
543 //
544 }
545
546 //
547 // Always enable the cache if it's supported
548 //
549 ui32RetVal = am_hal_card_cache_on(pCard);
550 if ( AM_HAL_STATUS_SUCCESS == ui32RetVal )
551 {
552 //
553 // Reread the card to get the updated cache status.
554 //
555 ui32RetVal = am_hal_card_get_ext_csd_field(pCard, MMC_EXT_REGS_CACHE_CTRL, 1);
556 AM_HAL_CARD_DEBUG("\r\nExtCsd CACHE_ON - %s\r\n", ((ui32RetVal == 1) ? "Pass" : "Fail"));
557 }
558 else
559 {
560 AM_HAL_CARD_DEBUG("\r\am_hal_card_cache_on - status %x\r\n", ui32RetVal);
561 }
562
563 //
564 // Always enable the notifcaition if it's supported
565 //
566 pCard->ui8PowerOffNotification = MMC_EXT_CSD_NO_POWER_NOTIFICATION;
567 if (am_hal_card_pwr_notification(pCard, MMC_EXT_CSD_POWERED_ON) == AM_HAL_STATUS_SUCCESS)
568 {
569 pCard->ui8PowerOffNotification = MMC_EXT_CSD_POWERED_ON;
570 }
571
572 return AM_HAL_STATUS_SUCCESS;
573 }
574
575 static uint32_t
am_hal_card_sd_init(am_hal_card_t * pCard)576 am_hal_card_sd_init(am_hal_card_t *pCard)
577 {
578 AM_HAL_CARD_DEBUG("card type %d is not supported yet\n", pCard->eType);
579 return AM_HAL_STATUS_FAIL;
580 }
581
582 static uint32_t
am_hal_card_type_detect(am_hal_card_t * pCard)583 am_hal_card_type_detect(am_hal_card_t *pCard)
584 {
585 AM_HAL_CARD_DEBUG("card type detect is not supported yet\n");
586 return AM_HAL_STATUS_FAIL;
587 }
588
589 static uint32_t
am_hal_card_set_bus_width(am_hal_card_t * pCard,am_hal_host_bus_width_e eBusWidth)590 am_hal_card_set_bus_width(am_hal_card_t *pCard, am_hal_host_bus_width_e eBusWidth)
591 {
592 uint32_t ui32Mode;
593 uint32_t ui32Status;
594
595 am_hal_card_host_t *pHost;
596
597 #ifndef AM_HAL_DISABLE_API_VALIDATION
598
599 if ( !pCard || !pCard->pHost )
600 {
601 return AM_HAL_STATUS_INVALID_ARG;
602 }
603
604 #endif // AM_HAL_DISABLE_API_VALIDATION
605
606 pHost = pCard->pHost;
607 ui32Mode = 0x0;
608 if ( eBusWidth != pHost->eBusWidth || pHost->eUHSMode != pCard->cfg.eUHSMode)
609 {
610 switch ( eBusWidth )
611 {
612 case AM_HAL_HOST_BUS_WIDTH_1:
613 //
614 // 3 << 24 | 183 << 16 | 0 << 8
615 // 0x03b70000
616 //
617 ui32Mode = MMC_EXT_MODE_WRITE_BYTE | MMC_EXT_REGS_BUS_WIDTH | MMC_EXT_SET_BUS_WIDTH1;
618 break;
619 case AM_HAL_HOST_BUS_WIDTH_4:
620 //
621 // 3 << 24 | 183 << 16 | 1 << 8
622 // 0x03b70100
623 //
624 if (pCard->cfg.eUHSMode == AM_HAL_HOST_UHS_DDR50)
625 {
626 ui32Mode = MMC_EXT_MODE_WRITE_BYTE | MMC_EXT_REGS_BUS_WIDTH | MMC_EXT_SET_BUS_WIDTH4_DDR;
627 }
628 else
629 {
630 ui32Mode = MMC_EXT_MODE_WRITE_BYTE | MMC_EXT_REGS_BUS_WIDTH | MMC_EXT_SET_BUS_WIDTH4;
631 }
632 break;
633 case AM_HAL_HOST_BUS_WIDTH_8:
634 //
635 // 3 << 24 | 183 << 16 | 2 << 8
636 // 0x03b70200
637 //
638 if (pCard->cfg.eUHSMode == AM_HAL_HOST_UHS_DDR50)
639 {
640 ui32Mode = MMC_EXT_MODE_WRITE_BYTE | MMC_EXT_REGS_BUS_WIDTH | MMC_EXT_SET_BUS_WIDTH8_DDR;
641 }
642 else
643 {
644 ui32Mode = MMC_EXT_MODE_WRITE_BYTE | MMC_EXT_REGS_BUS_WIDTH | MMC_EXT_SET_BUS_WIDTH8;
645 }
646 break;
647 }
648
649 if ( (ui32Status = am_hal_card_mode_switch(pCard, ui32Mode, DEFAULT_CMD6_TIMEOUT_MS)) != AM_HAL_STATUS_SUCCESS )
650 {
651 return ui32Status;
652 }
653
654 if ( pHost->ops->set_bus_width(pHost->pHandle, eBusWidth) != AM_HAL_STATUS_SUCCESS )
655 {
656 return AM_HAL_STATUS_FAIL;
657 }
658 }
659
660 return AM_HAL_STATUS_SUCCESS;
661 }
662
663 static uint32_t
am_hal_card_set_uhs_mode(am_hal_card_t * pCard,am_hal_host_uhs_mode_e eUHSMode)664 am_hal_card_set_uhs_mode(am_hal_card_t *pCard, am_hal_host_uhs_mode_e eUHSMode)
665 {
666 am_hal_card_host_t *pHost;
667
668 #ifndef AM_HAL_DISABLE_API_VALIDATION
669 if ( !pCard || !pCard->pHost )
670 {
671 return AM_HAL_STATUS_INVALID_ARG;
672 }
673 #endif // AM_HAL_DISABLE_API_VALIDATION
674
675 pHost = pCard->pHost;
676
677 //
678 // Already in this UHS mode
679 //
680 if ( pHost->eUHSMode == eUHSMode )
681 {
682 return AM_HAL_STATUS_SUCCESS;
683 }
684
685 if ( eUHSMode == AM_HAL_HOST_UHS_DDR50 )
686 {
687 if (pCard->eType == AM_HAL_CARD_TYPE_EMMC || pCard->eType == AM_HAL_CARD_TYPE_MMC)
688 {
689 //
690 // Card does not support DDR52 mode
691 //
692 if ((pCard->ui8DeviceType & HS_DDR_52MHZ_18_3V) == 0x0)
693 {
694 return AM_HAL_STATUS_FAIL;
695 }
696
697 if (pHost->ops->set_uhs_mode)
698 {
699 return pHost->ops->set_uhs_mode(pHost->pHandle, eUHSMode);
700 }
701 }
702 else
703 {
704 if (pHost->ops->set_uhs_mode)
705 {
706 return pHost->ops->set_uhs_mode(pHost->pHandle, eUHSMode);
707 }
708 }
709 }
710 else
711 {
712 if (pCard->eType == AM_HAL_CARD_TYPE_EMMC || pCard->eType == AM_HAL_CARD_TYPE_MMC)
713 {
714 if (pHost->ops->set_uhs_mode)
715 {
716 return pHost->ops->set_uhs_mode(pHost->pHandle, AM_HAL_HOST_UHS_NONE);
717 }
718 }
719 else
720 {
721 if (pHost->ops->set_uhs_mode)
722 {
723 return pHost->ops->set_uhs_mode(pHost->pHandle, eUHSMode);
724 }
725 }
726 }
727
728 return AM_HAL_STATUS_SUCCESS;
729 }
730
731 static uint32_t
am_hal_card_set_voltage(am_hal_card_t * pCard,am_hal_host_bus_voltage_e eBusVoltage)732 am_hal_card_set_voltage(am_hal_card_t *pCard, am_hal_host_bus_voltage_e eBusVoltage)
733 {
734 am_hal_card_host_t *pHost;
735
736 #ifndef AM_HAL_DISABLE_API_VALIDATION
737
738 if ( !pCard || !pCard->pHost )
739 {
740 return AM_HAL_STATUS_INVALID_ARG;
741 }
742
743 #endif // AM_HAL_DISABLE_API_VALIDATION
744
745 pHost = pCard->pHost;
746
747 if ( eBusVoltage != pHost->eBusVoltage )
748 {
749 if ( pHost->ops->set_bus_voltage(pHost->pHandle, eBusVoltage) != AM_HAL_STATUS_SUCCESS )
750 {
751 return AM_HAL_STATUS_FAIL;
752 }
753 }
754
755 return AM_HAL_STATUS_SUCCESS;
756 }
757
758 #define ENABLE_SDR_96MHZ
759
760 #define MMC_LEGACY_HS 26000000
761 #define MMC_SDR_HS 52000000
762 #define MMC_DDR_HS 52000000
763 #define MMC_HS200 200000000
764
765 //
766 // apollo4 SDHC speed limitation settings
767 //
768 #define MMC_HS200_MAX_SPEED_LIMIT 96000000
769 #define MMC_HS_MAX_SPEED_LIMIT 48000000
770
771 static uint32_t
am_hal_card_set_speed(am_hal_card_t * pCard,uint32_t ui32Clock)772 am_hal_card_set_speed(am_hal_card_t *pCard, uint32_t ui32Clock)
773 {
774 uint32_t ui32Status;
775 uint32_t ui32Mode;
776 uint32_t ui32HSMode = 1;
777 am_hal_card_host_t *pHost;
778
779 #ifndef AM_HAL_DISABLE_API_VALIDATION
780
781 if ( !pCard || !pCard->pHost )
782 {
783 return AM_HAL_STATUS_INVALID_ARG;
784 }
785
786 #endif // AM_HAL_DISABLE_API_VALIDATION
787
788 pHost = pCard->pHost;
789
790 #ifdef ENABLE_SDR_96MHZ
791 if ((pCard->cfg.eUHSMode == AM_HAL_HOST_UHS_SDR104) &&
792 (ui32Clock > MMC_HS_MAX_SPEED_LIMIT) &&
793 (ui32Clock <= MMC_HS200_MAX_SPEED_LIMIT))
794 {
795 ui32HSMode = 2;
796 }
797 #endif
798
799 if ( (pCard->ui8SpecVer >= 4) && (ui32Clock >= MMC_LEGACY_HS) )
800 {
801 //
802 // Already in the high speed mode
803 //
804 if ( am_hal_unstuff_bytes(pCard->ui32ExtCSD, 185, 1) != ui32HSMode )
805 {
806 //
807 // 0x03B90100
808 //
809 ui32Mode = MMC_EXT_MODE_WRITE_BYTE | MMC_EXT_REGS_HIGH_SPEED | (ui32HSMode << 8);
810 if ( (ui32Status = am_hal_card_mode_switch(pCard, ui32Mode, DEFAULT_CMD6_TIMEOUT_MS)) != AM_HAL_STATUS_SUCCESS )
811 {
812 return ui32Status;
813 }
814
815 //
816 // read back the ext_csd and check 'HS_TIMING' is set or not
817 //
818 if ( am_hal_sdmmc_cmd8_send_ext_csd(pCard) != AM_HAL_CMD_ERR_NONE )
819 {
820 return AM_HAL_STATUS_FAIL;
821 }
822
823 if ( am_hal_unstuff_bytes(pCard->ui32ExtCSD, 185, 1) != ui32HSMode )
824 {
825 AM_HAL_CARD_DEBUG("%d - Failed to switch to high speed mode\n", __FUNCTION__);
826 return AM_HAL_STATUS_FAIL;
827 }
828 }
829 }
830
831 if ( pHost->ops->set_bus_clock(pHost->pHandle, ui32Clock) != AM_HAL_STATUS_SUCCESS )
832 {
833 return AM_HAL_STATUS_FAIL;
834 }
835
836 return AM_HAL_STATUS_SUCCESS;
837 }
838
839 //
840 // Static helper function:
841 // Count the longest consecutive 1s in a 32bit word
842 //
843 static uint32_t
count_consecutive_ones(uint32_t * pVal)844 count_consecutive_ones(uint32_t* pVal)
845 {
846 uint32_t count = 0;
847 uint32_t data = *pVal;
848
849 while ( data )
850 {
851 data = (data & (data << 1));
852 count++;
853 }
854 return count;
855 }
856
857 //
858 // Static helper function:
859 // Find and return the mid point of the longest continuous 1s in a 32bit word
860 //
861 static uint32_t
find_mid_point(uint32_t * pVal)862 find_mid_point(uint32_t* pVal)
863 {
864 uint32_t pattern_len = 0;
865 uint32_t max_len = 0;
866 uint32_t pick_point = 0;
867 bool pattern_start = false;
868 uint32_t val = *pVal;
869
870 for ( uint32_t i = 0; i < 32; i++ )
871 {
872 if ( val & (0x01 << i) )
873 {
874 pattern_start = true;
875 pattern_len++;
876 }
877 else
878 {
879 if ( pattern_start == true )
880 {
881 pattern_start = false;
882 if ( pattern_len > max_len )
883 {
884 max_len = pattern_len;
885 pick_point = i - 1 - pattern_len / 2;
886 }
887 pattern_len = 0;
888 }
889 }
890 }
891
892 return pick_point;
893 }
894
895 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])896 am_hal_card_emmc_calibrate(am_hal_host_uhs_mode_e eUHSMode,
897 uint32_t ui32Clock,
898 am_hal_host_bus_width_e eBusWidth,
899 uint8_t *ui8CalibBuf,
900 uint32_t ui32StartBlk,
901 uint32_t ui32BlkCnt,
902 uint8_t ui8TxRxDelays[2])
903 {
904 am_hal_card_t eMMCard;
905 am_hal_card_host_t *pSdhcCardHost;
906
907 uint32_t i;
908 uint32_t len = ui32BlkCnt*512;
909 uint8_t ui8TxDelay = 0;
910 uint8_t ui8RxDelay = 0;
911 uint32_t ui32TxResult = 0;
912 uint32_t ui32RxResultArray[16] = {0};
913
914 #ifdef AM_DEBUG_PRINTF
915 if (eUHSMode == AM_HAL_HOST_UHS_DDR50)
916 {
917 AM_HAL_CARD_DEBUG("eMMC Timing Scan for DDR %d Hz %d bit mode...\n", ui32Clock, eBusWidth);
918 }
919 else
920 {
921 AM_HAL_CARD_DEBUG("eMMC Timing Scan for SDR %d Hz %d bit mode...\n", ui32Clock, eBusWidth);
922 }
923 #endif
924
925 for (int j = 0; j < 16; j++)
926 {
927 for (int k = 0; k < 32; k++)
928 {
929 //
930 // Get the uderlying SDHC card host instance
931 //
932 pSdhcCardHost = am_hal_get_card_host(AM_HAL_SDHC_CARD_HOST, true);
933
934 if (pSdhcCardHost == NULL)
935 {
936 AM_HAL_CARD_DEBUG("No such card host and stop\n");
937 return AM_HAL_STATUS_FAIL;
938 }
939
940 ui8TxRxDelays[0] = j;
941 ui8TxRxDelays[1] = k;
942 AM_HAL_CARD_DEBUG("Test TX delay setting SDIOOTAPDLYSEL = %d, RX delay setting SDIOITAPDLYSEL = %d\n", j, k);
943 am_hal_card_host_set_txrx_delay(pSdhcCardHost, ui8TxRxDelays);
944
945 //
946 // check if card is present
947 //
948 if (am_hal_card_host_find_card(pSdhcCardHost, &eMMCard) != AM_HAL_STATUS_SUCCESS)
949 {
950 AM_HAL_CARD_DEBUG("No card is present now\n");
951 return AM_HAL_STATUS_FAIL;
952 }
953
954 if (am_hal_card_init(&eMMCard, NULL, AM_HAL_CARD_PWR_CTRL_NONE) != AM_HAL_STATUS_SUCCESS)
955 {
956 AM_HAL_CARD_DEBUG("card initialization failed\n");
957 return AM_HAL_STATUS_FAIL;
958 }
959
960 if (am_hal_card_cfg_set(&eMMCard, AM_HAL_CARD_TYPE_EMMC,
961 eBusWidth, ui32Clock, AM_HAL_HOST_BUS_VOLTAGE_1_8,
962 eUHSMode) != AM_HAL_STATUS_SUCCESS)
963 {
964 AM_HAL_CARD_DEBUG("card config failed\n");
965 continue;
966 }
967
968 for (i = 0; i < len; i++)
969 {
970 ui8CalibBuf[i] = i % 256;
971 }
972
973 am_hal_card_block_write_sync(&eMMCard, ui32StartBlk, ui32BlkCnt, (uint8_t *)ui8CalibBuf);
974
975 memset((void *)ui8CalibBuf, 0x0, len);
976 am_hal_card_block_read_sync(&eMMCard, ui32StartBlk, ui32BlkCnt, (uint8_t *)ui8CalibBuf);
977
978 for (i = 0; i < len; i++)
979 {
980 if (ui8CalibBuf[i] != i % 256)
981 {
982 break;
983 }
984 }
985
986 if (i == len)
987 {
988 ui32RxResultArray[j] |= 0x01 << k;
989 AM_HAL_CARD_DEBUG("TX Delay SDIOOTAPDLYSEL = %d, RX Delay SDIOITAPDLYSEL = %d works\n", j, k);
990 }
991 else
992 {
993 AM_HAL_CARD_DEBUG("TX Delay SDIOOTAPDLYSEL = %d, RX Delay SDIOITAPDLYSEL = %d doesn't work\n", j, k);
994 }
995 }
996 }
997
998 #ifdef AM_DEBUG_PRINTF
999 AM_HAL_CARD_DEBUG("\nSDIO TX RX Delay Scan Result:\n");
1000 for (i = 0; i < 16; i++ )
1001 {
1002 AM_HAL_CARD_DEBUG("TX_Delay = %2d, RX_Delay Window = 0x%08X\n", i, ui32RxResultArray[i]);
1003 }
1004 #endif
1005
1006 uint32_t ui32Result = 0;
1007 for (i = 0; i < 16; i++ )
1008 {
1009 ui32Result = count_consecutive_ones(&ui32RxResultArray[i]);
1010 if ( ui32Result >= SDIO_TIMING_SCAN_MIN_ACCEPTANCE_LENGTH )
1011 {
1012 ui32TxResult |= 0x01 << i;
1013 }
1014 }
1015
1016 //
1017 // Check consecutive passing settings
1018 //
1019 if ( ui32TxResult == 0 )
1020 {
1021 //
1022 // No acceptable window
1023 //
1024 return AM_HAL_STATUS_FAIL;
1025 }
1026 else
1027 {
1028 ui32Result = count_consecutive_ones(&ui32TxResult);
1029 if ( ui32Result < SDIO_TIMING_SCAN_MIN_ACCEPTANCE_LENGTH )
1030 {
1031 //
1032 // No acceptable window
1033 //
1034 return AM_HAL_STATUS_FAIL;
1035 }
1036 }
1037
1038 //
1039 // Find TX Delay Value
1040 //
1041 ui8TxDelay = find_mid_point(&ui32TxResult);
1042
1043 AM_HAL_CARD_DEBUG("\nSDIO Timing Scan found a RX delay window %X with TX delay Setting = %d.\n", ui32RxResultArray[ui8TxDelay], ui8TxDelay);
1044
1045 //
1046 // Find RX Delay Value
1047 //
1048 ui8RxDelay = find_mid_point(&ui32RxResultArray[ui8TxDelay]);
1049 ui8TxRxDelays[0] = ui8TxDelay;
1050 ui8TxRxDelays[1] = ui8RxDelay;
1051
1052 AM_HAL_CARD_DEBUG("Timing Scan set the SDIO TX delay to %d and RX delay to %d.\n", ui8TxDelay, ui8RxDelay);
1053
1054 //
1055 // Force the card host to reset with the calibration settings
1056 //
1057 pSdhcCardHost = am_hal_get_card_host(AM_HAL_SDHC_CARD_HOST, true);
1058
1059 if (pSdhcCardHost == NULL)
1060 {
1061 AM_HAL_CARD_DEBUG("No such card host and stop\n");
1062 return AM_HAL_STATUS_FAIL;
1063 }
1064 am_hal_card_host_set_txrx_delay(pSdhcCardHost, ui8TxRxDelays);
1065
1066 return AM_HAL_STATUS_SUCCESS;
1067 }
1068
1069 //
1070 // Public functions
1071 //
1072
1073 //*****************************************************************************
1074 //
1075 // Power off the SDHC or eMMC CARD
1076 //
1077 //*****************************************************************************
1078 uint32_t
am_hal_card_pwrctrl_sleep(am_hal_card_t * pCard)1079 am_hal_card_pwrctrl_sleep(am_hal_card_t *pCard)
1080 {
1081 am_hal_card_host_t *pHost;
1082 uint32_t ui32Status = AM_HAL_STATUS_SUCCESS;
1083
1084 #ifndef AM_HAL_DISABLE_API_VALIDATION
1085 if ( !pCard || !pCard->pHost )
1086 {
1087 return AM_HAL_STATUS_INVALID_ARG;
1088 }
1089 #endif // AM_HAL_DISABLE_API_VALIDATION
1090
1091 pHost = pCard->pHost;
1092
1093 switch (pCard->eCardPwrCtrlPolicy)
1094 {
1095 case AM_HAL_CARD_PWR_CTRL_SDHC_AND_CARD_OFF:
1096 //
1097 // Flush the cache before power off the eMMC card
1098 //
1099 if ( (ui32Status = am_hal_card_cache_off(pCard)) != AM_HAL_STATUS_SUCCESS )
1100 {
1101 AM_HAL_CARD_DEBUG("sdhc & card power off - am_hal_card_cache_off Failed\n");
1102 return ui32Status;
1103 }
1104
1105 //
1106 // Host is going to power off the device
1107 //
1108 if ((ui32Status = am_hal_card_pwr_notification(pCard, MMC_EXT_CSD_POWER_OFF_LONG)) != AM_HAL_STATUS_SUCCESS)
1109 {
1110 AM_HAL_CARD_DEBUG("sdhc & card power off - am_hal_card_cache_off Failed\n");
1111 return ui32Status;
1112 }
1113
1114 //
1115 // Deselect card
1116 //
1117 if ((ui32Status = am_hal_sdmmc_cmd7_card_deselect(pCard)) != AM_HAL_STATUS_SUCCESS)
1118 {
1119 AM_HAL_CARD_DEBUG("sdhc & card sleep - Failed to deselect the card\n");
1120 return AM_HAL_STATUS_FAIL;
1121 }
1122
1123 //
1124 // Goto Sleep state before power off the card
1125 //
1126 if ( AM_HAL_CMD_ERR_NONE != am_hal_sdmmc_cmd5(pCard, true) )
1127 {
1128 AM_HAL_CARD_DEBUG("sdhc & card sleep - am_hal_sdmmc_cmd5 Failed\n");
1129 return AM_HAL_STATUS_FAIL;
1130 }
1131
1132 //
1133 // Call User Set Callback Function for Power Control
1134 //
1135 if (pCard->pCardPwrCtrlFunc)
1136 {
1137 pCard->pCardPwrCtrlFunc(AM_HAL_CARD_PWR_OFF);
1138 }
1139
1140 pCard->eState = AM_HAL_CARD_STATE_PWROFF;
1141
1142 if ((ui32Status = pHost->ops->deinit(pHost->pHandle)) != AM_HAL_STATUS_SUCCESS)
1143 {
1144 AM_HAL_CARD_DEBUG("sdhc & card power off - host deinit failed\n");
1145 return ui32Status;
1146 }
1147 break;
1148
1149 case AM_HAL_CARD_PWR_CTRL_SDHC_OFF_AND_CARD_SLEEP:
1150
1151 //
1152 // Flush the cache before power off the eMMC card
1153 //
1154 if ( (ui32Status = am_hal_card_cache_off(pCard)) != AM_HAL_STATUS_SUCCESS )
1155 {
1156 AM_HAL_CARD_DEBUG("sdhc & card sleep - am_hal_card_cache_off Failed\n");
1157 return ui32Status;
1158 }
1159
1160 //
1161 // Host is going to put the device in Sleep Mode
1162 //
1163 if ( (ui32Status = am_hal_card_pwr_notification(pCard, MMC_EXT_CSD_SLEEP_NOTIFICATION)) != AM_HAL_STATUS_SUCCESS )
1164 {
1165 AM_HAL_CARD_DEBUG("sdhc & card sleep - am_hal_card_pwr_notification Failed\n");
1166 return ui32Status;
1167 }
1168
1169 //
1170 // Deselect card
1171 //
1172 if ((ui32Status = am_hal_sdmmc_cmd7_card_deselect(pCard)) != AM_HAL_STATUS_SUCCESS)
1173 {
1174 AM_HAL_CARD_DEBUG("sdhc & card sleep - Failed to deselect the card\n");
1175 return AM_HAL_STATUS_FAIL;
1176 }
1177
1178 //
1179 // Goto Sleep state
1180 //
1181 if ( AM_HAL_CMD_ERR_NONE != am_hal_sdmmc_cmd5(pCard, true) )
1182 {
1183 AM_HAL_CARD_DEBUG("sdhc & card sleep - am_hal_sdmmc_cmd5 Failed\n");
1184 return AM_HAL_STATUS_FAIL;
1185 }
1186
1187 //
1188 // Power off the SDHC controller
1189 //
1190 if ((ui32Status = pHost->ops->pwr_ctrl(pHost->pHandle, false)) != AM_HAL_STATUS_SUCCESS)
1191 {
1192 AM_HAL_CARD_DEBUG("sdhc & card sleep - emmc card power control failed\n");
1193 return ui32Status;
1194 }
1195 break;
1196
1197 case AM_HAL_CARD_PWR_CTRL_SDHC_OFF:
1198 //
1199 // Power off the SDHC controller
1200 //
1201 if ((ui32Status = pHost->ops->pwr_ctrl(pHost->pHandle, false)) != AM_HAL_STATUS_SUCCESS)
1202 {
1203 AM_HAL_CARD_DEBUG("sdhc - emmc card power control failed\n");
1204 return ui32Status;
1205 }
1206 break;
1207
1208 default:
1209 break;
1210
1211 }
1212
1213 return AM_HAL_STATUS_SUCCESS;
1214 }
1215
1216 //*****************************************************************************
1217 //
1218 // Power on the SDHC or eMMC CARD
1219 //
1220 //*****************************************************************************
1221 uint32_t
am_hal_card_pwrctrl_wakeup(am_hal_card_t * pCard)1222 am_hal_card_pwrctrl_wakeup(am_hal_card_t *pCard)
1223 {
1224 uint32_t ui32Status;
1225 am_hal_card_host_t *pHost;
1226
1227 #ifndef AM_HAL_DISABLE_API_VALIDATION
1228 if ( !pCard || !pCard->pHost )
1229 {
1230 return AM_HAL_STATUS_INVALID_ARG;
1231 }
1232 #endif // AM_HAL_DISABLE_API_VALIDATION
1233
1234 pHost = pCard->pHost;
1235
1236 switch (pCard->eCardPwrCtrlPolicy)
1237 {
1238 case AM_HAL_CARD_PWR_CTRL_SDHC_AND_CARD_OFF:
1239 //
1240 // ReInit the SDHC controller
1241 //
1242 if ((ui32Status = pHost->ops->init(pHost)) != AM_HAL_STATUS_SUCCESS)
1243 {
1244 AM_HAL_CARD_DEBUG("wakeup reinit sdhc controller failed\n");
1245 return ui32Status;
1246 }
1247
1248 //
1249 // ReInit the card again
1250 //
1251 if ((ui32Status = am_hal_card_init(pCard,
1252 pCard->pCardPwrCtrlFunc, pCard->eCardPwrCtrlPolicy)) != AM_HAL_STATUS_SUCCESS)
1253 {
1254 AM_HAL_CARD_DEBUG("wakeup reinit sd card failed\n");
1255 return ui32Status;
1256 }
1257
1258 //
1259 // Reconfig the card with the original settings
1260 //
1261 if ((ui32Status = am_hal_card_cfg_set(pCard, pCard->eType, pCard->cfg.eBusWidth,
1262 pCard->cfg.ui32Clock, pCard->cfg.eIoVoltage, pCard->cfg.eUHSMode)) != AM_HAL_STATUS_SUCCESS)
1263 {
1264 AM_HAL_CARD_DEBUG("wakeup configure sd card failed\n");
1265 return ui32Status;
1266 }
1267 break;
1268
1269 case AM_HAL_CARD_PWR_CTRL_SDHC_OFF_AND_CARD_SLEEP:
1270 //
1271 // Power on the SDHC controller
1272 //
1273 if ((ui32Status = pHost->ops->pwr_ctrl(pHost->pHandle, true)) != AM_HAL_STATUS_SUCCESS)
1274 {
1275 AM_HAL_CARD_DEBUG("wakeup - power on the sdhc controller failed\n");
1276 return ui32Status;
1277 }
1278
1279 //
1280 // Exit Sleep state
1281 //
1282 if ( AM_HAL_CMD_ERR_NONE != am_hal_sdmmc_cmd5(pCard, false) )
1283 {
1284 AM_HAL_CARD_DEBUG("wakeup - am_hal_sdmmc_cmd5 Failed\n");
1285 return AM_HAL_STATUS_FAIL;
1286 }
1287
1288 //
1289 // Reselect card
1290 //
1291 if ( AM_HAL_CMD_ERR_NONE != am_hal_sdmmc_cmd7_card_select(pCard) )
1292 {
1293 AM_HAL_CARD_DEBUG("wakeup - am_hal_sdmmc_cmd7_card_select Failed\n");
1294 return AM_HAL_STATUS_FAIL;
1295 }
1296 break;
1297
1298 case AM_HAL_CARD_PWR_CTRL_SDHC_OFF:
1299 //
1300 // Power on the SDHC controller
1301 //
1302 if ((ui32Status = pHost->ops->pwr_ctrl(pHost->pHandle, true)) != AM_HAL_STATUS_SUCCESS)
1303 {
1304 AM_HAL_CARD_DEBUG("wakeup - power on the sdhc controller failed\n");
1305 return ui32Status;
1306 }
1307 break;
1308
1309 default:
1310 break;
1311 }
1312
1313 return AM_HAL_STATUS_SUCCESS;
1314 }
1315
1316 //*****************************************************************************
1317 //
1318 // Get the card instance function
1319 //
1320 //*****************************************************************************
1321 uint32_t
am_hal_card_host_find_card(am_hal_card_host_t * pHost,am_hal_card_t * pCard)1322 am_hal_card_host_find_card(am_hal_card_host_t *pHost, am_hal_card_t *pCard)
1323 {
1324
1325 #ifndef AM_HAL_DISABLE_API_VALIDATION
1326
1327 if ( !pHost || !pCard )
1328 {
1329 return AM_HAL_STATUS_INVALID_ARG;
1330 }
1331
1332 #endif // AM_HAL_DISABLE_API_VALIDATION
1333
1334 if ( pHost->bCardInSlot ||
1335 pHost->ops->get_cd(pHost->pHandle) )
1336 {
1337 pCard->eState = AM_HAL_CARD_STATE_PRESENT;
1338 pCard->pHost = pHost;
1339 //
1340 // Fill the default setting with the host's current value
1341 //
1342 pCard->cfg.eBusWidth = pHost->eBusWidth;
1343 pCard->cfg.eIoVoltage = pHost->eBusVoltage;
1344 pCard->cfg.ui32Clock = pHost->ui32MinClock;
1345 pCard->cfg.eUHSMode = pHost->eUHSMode;
1346 pCard->eState = AM_HAL_CARD_STATE_PWROFF;
1347 return AM_HAL_STATUS_SUCCESS;
1348 }
1349 else
1350 {
1351 pCard->eState = AM_HAL_CARD_STATE_NOT_PRESENT;
1352 return AM_HAL_STATUS_FAIL;
1353 }
1354 }
1355
1356 //*****************************************************************************
1357 //
1358 // Set the card operation configurations
1359 //
1360 //*****************************************************************************
1361 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)1362 am_hal_card_cfg_set(am_hal_card_t *pCard, am_hal_card_type_e eType,
1363 am_hal_host_bus_width_e eBusWidth,
1364 uint32_t ui32Clock,
1365 am_hal_host_bus_voltage_e eIoVoltage,
1366 am_hal_host_uhs_mode_e eUHSMode)
1367 {
1368 #ifndef AM_HAL_DISABLE_API_VALIDATION
1369 if ( !pCard || !pCard->pHost )
1370 {
1371 AM_HAL_CARD_DEBUG("This card is not connected to a host\n");
1372 return AM_HAL_STATUS_INVALID_ARG;
1373 }
1374 #endif // AM_HAL_DISABLE_API_VALIDATION
1375
1376 if ( pCard->eState != AM_HAL_CARD_STATE_TRANS )
1377 {
1378 return AM_HAL_STATUS_INVALID_OPERATION;
1379 }
1380
1381 //
1382 // Checking the validation of the clock settings
1383 // Clock should not exceed the capabilities of the SDHC
1384 // DDR mode, max speed is not higer than 48MHz
1385 // SDR mode, max speed is not higer than 96MHz
1386 // Legacy card, max speed is not higher than 26MHz
1387 //
1388 if ((ui32Clock > pCard->pHost->ui32MaxClock) || (ui32Clock < pCard->pHost->ui32MinClock) ||
1389 ((eUHSMode == AM_HAL_HOST_UHS_DDR50) && (ui32Clock > MMC_HS_MAX_SPEED_LIMIT)) ||
1390 ((eUHSMode == AM_HAL_HOST_UHS_NONE) && (ui32Clock > MMC_HS200_MAX_SPEED_LIMIT)) ||
1391 ((ui32Clock > MMC_LEGACY_HS) && (pCard->ui8SpecVer < 4)))
1392 {
1393 return AM_HAL_STATUS_INVALID_ARG;
1394 }
1395
1396 pCard->eType = eType;
1397 pCard->cfg.eBusWidth = eBusWidth;
1398 pCard->cfg.ui32Clock = ui32Clock;
1399 pCard->cfg.eIoVoltage = eIoVoltage;
1400 pCard->cfg.eUHSMode = eUHSMode;
1401
1402 if (am_hal_card_set_voltage(pCard, pCard->cfg.eIoVoltage) != AM_HAL_STATUS_SUCCESS )
1403 {
1404 AM_HAL_CARD_DEBUG("Failed to change bus voltage\n");
1405 return AM_HAL_STATUS_FAIL;
1406 }
1407
1408 if ( eUHSMode == AM_HAL_HOST_UHS_SDR104 )
1409 {
1410 //
1411 // Configure the card bus width
1412 //
1413 if ( am_hal_card_set_bus_width(pCard, pCard->cfg.eBusWidth) != AM_HAL_STATUS_SUCCESS )
1414 {
1415 AM_HAL_CARD_DEBUG("Failed to change bus width\n");
1416 return AM_HAL_STATUS_FAIL;
1417 }
1418
1419 //
1420 // Configure the card bus speed
1421 //
1422 if ( am_hal_card_set_speed(pCard, pCard->cfg.ui32Clock) != AM_HAL_STATUS_SUCCESS )
1423 {
1424 AM_HAL_CARD_DEBUG("Failed to change bus speed\n");
1425 return AM_HAL_STATUS_FAIL;
1426 }
1427 }
1428 else
1429 {
1430 //
1431 // Configure the card bus speed
1432 //
1433 if ( am_hal_card_set_speed(pCard, pCard->cfg.ui32Clock) != AM_HAL_STATUS_SUCCESS )
1434 {
1435 AM_HAL_CARD_DEBUG("Failed to change bus speed\n");
1436 return AM_HAL_STATUS_FAIL;
1437 }
1438
1439 //
1440 // Configure the card bus width
1441 //
1442 if ( am_hal_card_set_bus_width(pCard, pCard->cfg.eBusWidth) != AM_HAL_STATUS_SUCCESS )
1443 {
1444 AM_HAL_CARD_DEBUG("Failed to change bus width\n");
1445 return AM_HAL_STATUS_FAIL;
1446 }
1447 }
1448
1449 //
1450 // Select the UHS mode
1451 //
1452 if (am_hal_card_set_uhs_mode(pCard, pCard->cfg.eUHSMode) != AM_HAL_STATUS_SUCCESS)
1453 {
1454 AM_HAL_CARD_DEBUG("Failed to change UHS mode\n");
1455 return AM_HAL_STATUS_FAIL;
1456 }
1457
1458 return AM_HAL_STATUS_SUCCESS;
1459 }
1460
1461 //*****************************************************************************
1462 //
1463 // Initialize the card instance function
1464 //
1465 //*****************************************************************************
1466 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)1467 am_hal_card_init(am_hal_card_t *pCard,
1468 am_hal_card_pwr_ctrl_func pCardPwrCtrlFunc,
1469 am_hal_card_pwr_ctrl_policy_e eCardPwrCtrlPolicy)
1470 {
1471 #ifndef AM_HAL_DISABLE_API_VALIDATION
1472 if ( !pCard || !pCard->pHost )
1473 {
1474 AM_HAL_CARD_DEBUG("This card is not connected to a host\n");
1475 return AM_HAL_STATUS_INVALID_ARG;
1476 }
1477 #endif // AM_HAL_DISABLE_API_VALIDATION
1478
1479 //
1480 // Turn on the eMMC card power supply firstly
1481 //
1482 if (pCard->eState == AM_HAL_CARD_STATE_PWROFF && pCardPwrCtrlFunc != NULL)
1483 {
1484 AM_HAL_CARD_DEBUG("turn on the eMMC power supply\n");
1485 pCardPwrCtrlFunc(AM_HAL_CARD_PWR_ON);
1486 }
1487
1488 pCard->pCardPwrCtrlFunc = pCardPwrCtrlFunc;
1489 pCard->eState = AM_HAL_CARD_STATE_PWRON;
1490 pCard->eCardPwrCtrlPolicy = eCardPwrCtrlPolicy;
1491
1492 AM_HAL_CARD_DEBUG("card type is %d\n", pCard->eType);
1493
1494 // Note: remove below code unless 'am_hal_card_type_detect' is finished
1495 pCard->eType = AM_HAL_CARD_TYPE_EMMC;
1496
1497 switch (pCard->eType)
1498 {
1499 case AM_HAL_CARD_TYPE_UNKNOWN:
1500 if ( am_hal_card_type_detect(pCard) != AM_HAL_STATUS_SUCCESS )
1501 {
1502 return AM_HAL_STATUS_FAIL;
1503 }
1504 break;
1505 case AM_HAL_CARD_TYPE_MMC:
1506 case AM_HAL_CARD_TYPE_EMMC:
1507 if ( am_hal_card_mmc_init(pCard) != AM_HAL_STATUS_SUCCESS )
1508 {
1509 return AM_HAL_STATUS_FAIL;
1510 }
1511 break;
1512 case AM_HAL_CARD_TYPE_SDSC:
1513 case AM_HAL_CARD_TYPE_SDHC:
1514 case AM_HAL_CARD_TYPE_SDIO:
1515 case AM_HAL_CARD_TYPE_COMBO:
1516 if ( am_hal_card_sd_init(pCard) != AM_HAL_STATUS_SUCCESS )
1517 {
1518 return AM_HAL_STATUS_FAIL;
1519 }
1520 break;
1521 }
1522
1523 return AM_HAL_STATUS_SUCCESS;
1524 }
1525
1526 //*****************************************************************************
1527 //
1528 // De-Initialize the card instance function
1529 //
1530 //*****************************************************************************
1531 uint32_t
am_hal_card_deinit(am_hal_card_t * pCard)1532 am_hal_card_deinit(am_hal_card_t *pCard)
1533 {
1534 #ifndef AM_HAL_DISABLE_API_VALIDATION
1535 if ( !pCard || !pCard->pHost )
1536 {
1537 AM_HAL_CARD_DEBUG("This card is not connected to a host\n");
1538 return AM_HAL_STATUS_INVALID_ARG;
1539 }
1540 #endif // AM_HAL_DISABLE_API_VALIDATION
1541
1542 memset((void *)pCard, 0x0, sizeof(am_hal_card_t));
1543
1544 return AM_HAL_STATUS_SUCCESS;
1545 }
1546
1547 #ifdef DSP_RAM1_WORKAROUND
1548
1549 #define DSP_RAM1_START_ADDR 0x101C4000
1550 #define DSP_RAM1_SIZE 96*1024 // 96KB
1551
1552 #define DSP_RAM1_TMP_ADDR DSP_RAM1_START_ADDR
1553
1554 #endif
1555
1556 #define ENABLE_SDHC_AUTO_CMD23_FEATURE
1557
1558 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)1559 am_hal_card_block_rw(am_hal_card_t *pCard, uint32_t ui32Blk, uint32_t ui32BlkCnt, uint8_t *pui8Buf, bool bRead, bool bASync)
1560 {
1561 uint32_t ui32Status;
1562
1563 am_hal_card_host_t *pHost;
1564 am_hal_card_cmd_t cmd;
1565 am_hal_card_cmd_data_t cmd_data;
1566
1567 #ifndef AM_HAL_DISABLE_API_VALIDATION
1568
1569 if ( !pCard || !pCard->pHost )
1570 {
1571 return AM_HAL_STATUS_INVALID_ARG;
1572 }
1573
1574 #endif // AM_HAL_DISABLE_API_VALIDATION
1575
1576 if ( pCard->eState != AM_HAL_CARD_STATE_TRANS )
1577 {
1578 return AM_HAL_STATUS_INVALID_OPERATION;
1579 }
1580
1581 pHost = pCard->pHost;
1582
1583 //
1584 // Check if the start block number and block count is valid or not
1585 //
1586 if ( ui32Blk >= pCard->ui32MaxBlks || (ui32BlkCnt > 0xFFFF) || (ui32Blk + ui32BlkCnt) > pCard->ui32MaxBlks )
1587 {
1588 return AM_HAL_STATUS_OUT_OF_RANGE;
1589 }
1590
1591 if ( pHost->eXferMode == AM_HAL_HOST_XFER_ADMA && ui32BlkCnt > pHost->ui32MaxADMA2BlkNums )
1592 {
1593 ui32BlkCnt = pHost->ui32MaxADMA2BlkNums;
1594 }
1595
1596 #ifdef DSP_RAM1_WORKAROUND
1597 if (bRead == false)
1598 {
1599 memcpy((void *)DSP_RAM1_TMP_ADDR, pui8Buf, ui32BlkCnt*512);
1600 pui8Buf = (uint8_t *)DSP_RAM1_TMP_ADDR;
1601 }
1602 #endif
1603
1604 #ifndef ENABLE_SDHC_AUTO_CMD23_FEATURE
1605 //
1606 // Send CMD23 firstly for mulitple blocks transfer
1607 //
1608 memset((void *)&cmd, 0x0, sizeof(cmd));
1609 if ( ui32BlkCnt > 1 )
1610 {
1611 cmd.ui8Idx = MMC_CMD_SET_BLOCK_COUNT;
1612 cmd.ui32Arg = ui32BlkCnt;
1613 cmd.ui32RespType = MMC_RSP_R1;
1614
1615 if ( (ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL)) != AM_HAL_STATUS_SUCCESS )
1616 {
1617 return ui32Status;
1618 }
1619 }
1620 #endif
1621
1622 memset((void *)&cmd, 0x0, sizeof(cmd));
1623 memset((void *)&cmd_data, 0x0, sizeof(cmd_data));
1624 if ( bRead )
1625 {
1626 cmd.ui8Idx = ui32BlkCnt > 1 ? MMC_CMD_READ_MULTIPLE_BLOCK : MMC_CMD_READ_SINGLE_BLOCK;
1627 }
1628 else
1629 {
1630 cmd.ui8Idx = ui32BlkCnt > 1 ? MMC_CMD_WRITE_MULTIPLE_BLOCK : MMC_CMD_WRITE_SINGLE_BLOCK;
1631 }
1632
1633 cmd.ui32Arg = pCard->bHighCapcity ? ui32Blk : ui32Blk * pCard->ui32BlkSize;
1634 cmd.ui32RespType = MMC_RSP_R1;
1635 cmd.bASync = bASync;
1636 #ifdef ENABLE_SDHC_AUTO_CMD23_FEATURE
1637 cmd.bAutoCMD23 = ui32BlkCnt > 1 ? true : false;
1638 #endif
1639
1640 cmd_data.pui8Buf = pui8Buf;
1641 cmd_data.ui32BlkCnt = ui32BlkCnt;
1642 cmd_data.ui32BlkSize = pCard->ui32BlkSize;
1643 cmd_data.dir = bRead ? AM_HAL_DATA_DIR_READ : AM_HAL_DATA_DIR_WRITE;
1644
1645 if ( cmd.bASync )
1646 {
1647 pHost->AsyncCmd = cmd;
1648 pHost->AsyncCmdData = cmd_data;
1649 }
1650
1651 ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, &cmd_data);
1652
1653 return ui32Status;
1654 }
1655
1656 //*****************************************************************************
1657 //
1658 // synchronous block-oriented read function
1659 //
1660 //*****************************************************************************
1661 uint32_t
am_hal_card_block_read_sync(am_hal_card_t * pCard,uint32_t ui32Blk,uint32_t ui32BlkCnt,uint8_t * pui8Buf)1662 am_hal_card_block_read_sync(am_hal_card_t *pCard, uint32_t ui32Blk, uint32_t ui32BlkCnt, uint8_t *pui8Buf)
1663 {
1664 return am_hal_card_block_rw(pCard, ui32Blk, ui32BlkCnt, pui8Buf, true, false);
1665 }
1666
1667 //*****************************************************************************
1668 //
1669 // synchronous block-oriented write function
1670 //
1671 //*****************************************************************************
1672 uint32_t
am_hal_card_block_write_sync(am_hal_card_t * pCard,uint32_t ui32Blk,uint32_t ui32BlkCnt,uint8_t * pui8Buf)1673 am_hal_card_block_write_sync(am_hal_card_t *pCard, uint32_t ui32Blk, uint32_t ui32BlkCnt, uint8_t *pui8Buf)
1674 {
1675 return am_hal_card_block_rw(pCard, ui32Blk, ui32BlkCnt, pui8Buf, false, false);
1676 }
1677
1678 //*****************************************************************************
1679 //
1680 // asynchronous block-oriented read function
1681 //
1682 //*****************************************************************************
1683 uint32_t
am_hal_card_block_read_async(am_hal_card_t * pCard,uint32_t ui32Blk,uint32_t ui32BlkCnt,uint8_t * pui8Buf)1684 am_hal_card_block_read_async(am_hal_card_t *pCard, uint32_t ui32Blk, uint32_t ui32BlkCnt, uint8_t *pui8Buf)
1685 {
1686 return am_hal_card_block_rw(pCard, ui32Blk, ui32BlkCnt, pui8Buf, true, true);
1687 }
1688
1689 //*****************************************************************************
1690 //
1691 // asynchronous block-oriented write function
1692 //
1693 //*****************************************************************************
1694 uint32_t
am_hal_card_block_write_async(am_hal_card_t * pCard,uint32_t ui32Blk,uint32_t ui32BlkCnt,uint8_t * pui8Buf)1695 am_hal_card_block_write_async(am_hal_card_t *pCard, uint32_t ui32Blk, uint32_t ui32BlkCnt, uint8_t *pui8Buf)
1696 {
1697 return am_hal_card_block_rw(pCard, ui32Blk, ui32BlkCnt, pui8Buf, false, true);
1698 }
1699
1700 //*****************************************************************************
1701 //
1702 // block-oriented erase function
1703 //
1704 //*****************************************************************************
1705 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)1706 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)
1707 {
1708 uint32_t ui32Status;
1709 am_hal_card_host_t *pHost;
1710 am_hal_card_cmd_t cmd;
1711
1712 #ifndef AM_HAL_DISABLE_API_VALIDATION
1713
1714 if ( !pCard || !pCard->pHost )
1715 {
1716 return AM_HAL_STATUS_INVALID_ARG;
1717 }
1718
1719 #endif // AM_HAL_DISABLE_API_VALIDATION
1720
1721 if ( pCard->eState != AM_HAL_CARD_STATE_TRANS )
1722 {
1723 return AM_HAL_STATUS_INVALID_OPERATION;
1724 }
1725
1726 //
1727 // Check if the start block number and block count is valid or not
1728 //
1729 if ( ui32Blk >= pCard->ui32MaxBlks || ui32Blk + ui32BlkCnt > pCard->ui32MaxBlks )
1730 {
1731 return AM_HAL_STATUS_OUT_OF_RANGE;
1732 }
1733
1734 if ( erasetype == AM_HAL_SECURE_ERASE || erasetype == AM_HAL_SECURE_TRIM1 || erasetype == AM_HAL_SECURE_TRIM2 )
1735 {
1736 if ( !(pCard->ui8SecureErase & SEC_ER_EN) )
1737 {
1738 AM_HAL_CARD_DEBUG("This device does not support Secure Erase or Trim\n");
1739 return AM_HAL_STATUS_INVALID_ARG;
1740 }
1741 }
1742
1743 if ( erasetype == AM_HAL_TRIM || erasetype == AM_HAL_SECURE_TRIM1 || erasetype == AM_HAL_SECURE_TRIM2 )
1744 {
1745 if ( !(pCard->ui8SecureErase & SEC_GB_CL_EN) )
1746 {
1747 AM_HAL_CARD_DEBUG("This device does not support Trim operation\n");
1748 return AM_HAL_STATUS_INVALID_ARG;
1749 }
1750 }
1751
1752 pHost = pCard->pHost;
1753
1754 //
1755 // Define the erase start address
1756 //
1757 memset((void *)&cmd, 0x0, sizeof(cmd));
1758 cmd.ui8Idx = MMC_CMD_ERASE_GROUP_START;
1759 cmd.ui32Arg = pCard->bHighCapcity ? ui32Blk : ui32Blk * pCard->ui32BlkSize;
1760 cmd.ui32RespType = MMC_RSP_R1;
1761
1762 if ( (ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL)) != AM_HAL_STATUS_SUCCESS )
1763 {
1764 return ui32Status;
1765 }
1766
1767 //
1768 // Define the erase end address
1769 //
1770 memset((void *)&cmd, 0x0, sizeof(cmd));
1771 cmd.ui8Idx = MMC_CMD_ERASE_GROUP_END;
1772 cmd.ui32Arg = pCard->bHighCapcity ? (ui32Blk + ui32BlkCnt - 1) : (ui32Blk + ui32BlkCnt - 1) * pCard->ui32BlkSize;
1773 cmd.ui32RespType = MMC_RSP_R1;
1774
1775 if ( (ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL)) != AM_HAL_STATUS_SUCCESS )
1776 {
1777 return ui32Status;
1778 }
1779
1780 //
1781 // Do the erase job
1782 //
1783 memset((void *)&cmd, 0x0, sizeof(cmd));
1784 cmd.bCheckBusyCmd = true;
1785 cmd.ui8Idx = MMC_CMD_ERASE;
1786 cmd.ui32Arg = (uint32_t)erasetype;
1787 cmd.ui32RespType = MMC_RSP_R1b;
1788
1789 if ( (ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL)) != AM_HAL_STATUS_SUCCESS )
1790 {
1791 return ui32Status;
1792 }
1793
1794 return pHost->ops->card_busy(pHost->pHandle, ui32TimeoutMS);
1795 }
1796
1797 //*****************************************************************************
1798 //
1799 // Get the card status function
1800 //
1801 //*****************************************************************************
1802 uint32_t
am_hal_card_status(am_hal_card_t * pCard,uint32_t * pui32Status)1803 am_hal_card_status(am_hal_card_t *pCard, uint32_t *pui32Status)
1804 {
1805 uint32_t ui32Status;
1806 am_hal_card_cmd_t cmd;
1807
1808 #ifndef AM_HAL_DISABLE_API_VALIDATION
1809
1810 if ( !pCard || !pCard->pHost )
1811 {
1812 return AM_HAL_STATUS_INVALID_ARG;
1813 }
1814
1815 #endif // AM_HAL_DISABLE_API_VALIDATION
1816
1817 if ( pCard->eState < AM_HAL_CARD_STATE_STDY )
1818 {
1819 return AM_HAL_STATUS_INVALID_OPERATION;
1820 }
1821
1822 am_hal_card_host_t *pHost = pCard->pHost;
1823
1824 memset(&cmd, 0, sizeof(cmd));
1825 cmd.ui8Idx = MMC_CMD_SEND_STATUS;
1826 cmd.ui32Arg = pCard->ui8RCA << 16;
1827 cmd.ui32RespType = MMC_RSP_R1;
1828
1829 if ( (ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL)) != AM_HAL_STATUS_SUCCESS )
1830 {
1831 return ui32Status;
1832 }
1833
1834 if ( cmd.eError == AM_HAL_CMD_ERR_NONE )
1835 {
1836 *pui32Status = cmd.ui32Resp[0];
1837 }
1838
1839 return ui32Status;
1840 }
1841
1842 //*****************************************************************************
1843 //
1844 // Get the card state function
1845 //
1846 //*****************************************************************************
am_hal_card_state(am_hal_card_t * pCard)1847 am_hal_card_state_e am_hal_card_state(am_hal_card_t *pCard)
1848 {
1849 uint32_t ui32Status = 0;
1850 uint32_t ui32State;
1851
1852 #ifndef AM_HAL_DISABLE_API_VALIDATION
1853
1854 if ( !pCard || !pCard->pHost )
1855 {
1856 return AM_HAL_CARD_STATE_ERROR;
1857 }
1858
1859 #endif // AM_HAL_DISABLE_API_VALIDATION
1860
1861 if ( am_hal_card_status(pCard, &ui32Status) != AM_HAL_STATUS_SUCCESS )
1862 {
1863 return AM_HAL_CARD_STATE_ERROR;
1864 }
1865 else
1866 {
1867 ui32State = ui32Status >> 9 & 0xF;
1868 if ( ui32State <= 10 )
1869 {
1870 pCard->eState = (am_hal_card_state_e)(ui32State + 2);
1871 }
1872 else
1873 {
1874 return AM_HAL_CARD_STATE_ERROR;
1875 }
1876 }
1877
1878 return pCard->eState;
1879 }
1880
1881 //*****************************************************************************
1882 //
1883 // CMD6 - Mode switch
1884 //
1885 //*****************************************************************************
1886 uint32_t
am_hal_card_mode_switch(am_hal_card_t * pCard,uint32_t ui32Mode,uint32_t ui32Timeout)1887 am_hal_card_mode_switch(am_hal_card_t *pCard, uint32_t ui32Mode, uint32_t ui32Timeout)
1888 {
1889 uint32_t ui32Status;
1890 uint32_t ui32CardStatus;
1891 am_hal_card_cmd_t cmd;
1892
1893 #ifndef AM_HAL_DISABLE_API_VALIDATION
1894
1895 if ( !pCard || !pCard->pHost )
1896 {
1897 return AM_HAL_STATUS_INVALID_ARG;
1898 }
1899
1900 #endif // AM_HAL_DISABLE_API_VALIDATION
1901
1902 if ( pCard->eState != AM_HAL_CARD_STATE_TRANS )
1903 {
1904 return AM_HAL_STATUS_INVALID_OPERATION;
1905 }
1906
1907 am_hal_card_host_t *pHost = pCard->pHost;
1908
1909 memset(&cmd, 0, sizeof(cmd));
1910 cmd.ui8Idx = MMC_CMD_SWITCH;
1911 cmd.ui32Arg = ui32Mode;
1912 pCard->bExtCsdValid = 0;
1913
1914 if ( pCard->eType == AM_HAL_CARD_TYPE_MMC || pCard->eType == AM_HAL_CARD_TYPE_EMMC )
1915 {
1916 cmd.bCheckBusyCmd = true;
1917 cmd.ui32RespType = MMC_RSP_R1b;
1918 }
1919 else
1920 {
1921 cmd.ui32RespType = MMC_RSP_R1;
1922 }
1923
1924 if ( (ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL)) != AM_HAL_STATUS_SUCCESS )
1925 {
1926 return ui32Status;
1927 }
1928
1929 if ( pCard->eType == AM_HAL_CARD_TYPE_MMC || pCard->eType == AM_HAL_CARD_TYPE_EMMC )
1930 {
1931 if ((ui32Status = pHost->ops->card_busy(pHost->pHandle, 10)) != AM_HAL_STATUS_SUCCESS)
1932 {
1933 return ui32Status;
1934 }
1935 }
1936
1937 ui32CardStatus = 0x0;
1938
1939 do
1940 {
1941 ui32Status = am_hal_card_status(pCard, &ui32CardStatus);
1942 if (ui32Status == AM_HAL_STATUS_SUCCESS && (ui32CardStatus & MMC_STATUS_SWITCH_ERROR))
1943 {
1944 AM_HAL_CARD_DEBUG("switch failed - mode is 0x%x !\n", ui32Mode);
1945 return AM_HAL_STATUS_FAIL;
1946 }
1947 if (ui32Status == AM_HAL_STATUS_SUCCESS && (ui32CardStatus & MMC_STATUS_RDY_FOR_DATA))
1948 {
1949 AM_HAL_CARD_DEBUG("switch succeeded - mode is 0x%x !\n", ui32Mode);
1950 return AM_HAL_STATUS_SUCCESS;
1951 }
1952 am_util_delay_ms(1);
1953 } while (ui32Timeout--);
1954
1955 return ui32Timeout ? AM_HAL_STATUS_SUCCESS : AM_HAL_STATUS_FAIL;
1956 }
1957
1958 //*****************************************************************************
1959 //
1960 // Read blocks of data from the card (GEN_CMD)
1961 //
1962 //*****************************************************************************
1963 static uint32_t
am_hal_card_cmd56_read(am_hal_card_t * pCard,uint32_t ui32Arg,uint8_t * pui8Buf,bool bASync)1964 am_hal_card_cmd56_read(am_hal_card_t *pCard, uint32_t ui32Arg, uint8_t *pui8Buf, bool bASync)
1965 {
1966 uint32_t ui32Status;
1967
1968 am_hal_card_host_t *pHost;
1969 am_hal_card_cmd_t cmd;
1970 am_hal_card_cmd_data_t cmd_data;
1971
1972 #ifndef AM_HAL_DISABLE_API_VALIDATION
1973
1974 if ( !pCard || !pCard->pHost )
1975 {
1976 return AM_HAL_STATUS_INVALID_ARG;
1977 }
1978
1979 #endif // AM_HAL_DISABLE_API_VALIDATION
1980
1981 if ( pCard->eState != AM_HAL_CARD_STATE_TRANS )
1982 {
1983 return AM_HAL_STATUS_INVALID_OPERATION;
1984 }
1985
1986 pHost = pCard->pHost;
1987
1988 memset((void *)&cmd, 0x0, sizeof(cmd));
1989 cmd.ui8Idx = MMC_CMD_CMD56;
1990 cmd.ui32Arg = ui32Arg;
1991 cmd.ui32RespType = MMC_RSP_R1;
1992 cmd.bASync = bASync;
1993
1994 memset((void *)&cmd_data, 0x0, sizeof(cmd_data));
1995 cmd_data.pui8Buf = pui8Buf;
1996 cmd_data.ui32BlkCnt = 1;
1997 cmd_data.ui32BlkSize = 512;
1998 cmd_data.dir = AM_HAL_DATA_DIR_READ;
1999
2000 if ( cmd.bASync )
2001 {
2002 pHost->AsyncCmd = cmd;
2003 pHost->AsyncCmdData = cmd_data;
2004 }
2005
2006 ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, &cmd_data);
2007
2008 return ui32Status;
2009 }
2010
2011 //*****************************************************************************
2012 //
2013 // Read blocks of data from the card (GEN_CMD) asynchronously
2014 //
2015 //*****************************************************************************
2016 uint32_t
am_hal_card_cmd56_read_async(am_hal_card_t * pCard,uint32_t ui32Arg,uint8_t * pui8Buf)2017 am_hal_card_cmd56_read_async(am_hal_card_t *pCard, uint32_t ui32Arg, uint8_t *pui8Buf)
2018 {
2019 return am_hal_card_cmd56_read(pCard, ui32Arg, pui8Buf, true);
2020 }
2021
2022 //*****************************************************************************
2023 //
2024 // Read blocks of data from the card (GEN_CMD) synchronously
2025 //
2026 //*****************************************************************************
2027 uint32_t
am_hal_card_cmd56_read_sync(am_hal_card_t * pCard,uint32_t ui32Arg,uint8_t * pui8Buf)2028 am_hal_card_cmd56_read_sync(am_hal_card_t *pCard, uint32_t ui32Arg, uint8_t *pui8Buf)
2029 {
2030 return am_hal_card_cmd56_read(pCard, ui32Arg, pui8Buf, false);
2031 }
2032
2033 //*****************************************************************************
2034 //
2035 // register the card event call back function
2036 //
2037 //*****************************************************************************
2038 uint32_t
am_hal_card_register_evt_callback(am_hal_card_t * pCard,am_hal_host_event_cb_t pfunCallback)2039 am_hal_card_register_evt_callback(am_hal_card_t *pCard, am_hal_host_event_cb_t pfunCallback)
2040 {
2041 #ifndef AM_HAL_DISABLE_API_VALIDATION
2042 if ( !pCard || !pCard->pHost )
2043 {
2044 AM_HAL_CARD_DEBUG("both Card and Host are needed to be initialized firstly\n");
2045 return AM_HAL_STATUS_INVALID_ARG;
2046 }
2047 #endif // AM_HAL_DISABLE_API_VALIDATION
2048
2049 pCard->pHost->pfunEvtCallback = pfunCallback;
2050
2051 return AM_HAL_STATUS_SUCCESS;
2052 }
2053
2054 //*****************************************************************************
2055 //
2056 // card cid information parse function
2057 //
2058 //*****************************************************************************
2059 uint32_t
am_hal_card_get_cid_field(am_hal_card_t * pCard,uint16_t ui16Offset,uint8_t ui8Size)2060 am_hal_card_get_cid_field(am_hal_card_t *pCard, uint16_t ui16Offset, uint8_t ui8Size)
2061 {
2062 #ifndef AM_HAL_DISABLE_API_VALIDATION
2063 if ( !pCard || !pCard->bCidValid )
2064 {
2065 return 0xFFFFFFFF;
2066 }
2067 #endif // AM_HAL_DISABLE_API_VALIDATION
2068
2069 return am_hal_unstuff_bits(pCard->ui32CID, ui16Offset, ui8Size);
2070
2071
2072 }
2073
2074 //*****************************************************************************
2075 //
2076 // card csd information parse function
2077 //
2078 //*****************************************************************************
2079 uint32_t
am_hal_card_get_csd_field(am_hal_card_t * pCard,uint16_t ui16Offset,uint8_t ui8Size)2080 am_hal_card_get_csd_field(am_hal_card_t *pCard, uint16_t ui16Offset, uint8_t ui8Size)
2081 {
2082 #ifndef AM_HAL_DISABLE_API_VALIDATION
2083 if ( !pCard || !pCard->bCsdValid )
2084 {
2085 return 0xFFFFFFFF;
2086 }
2087 #endif // AM_HAL_DISABLE_API_VALIDATION
2088
2089 return am_hal_unstuff_bits(pCard->ui32CSD, ui16Offset, ui8Size);
2090
2091 }
2092
2093 //*****************************************************************************
2094 //
2095 // card ext csd information parse function
2096 //
2097 //*****************************************************************************
2098 uint32_t
am_hal_card_get_ext_csd_field(am_hal_card_t * pCard,uint16_t ui16Offset,uint8_t ui8Size)2099 am_hal_card_get_ext_csd_field(am_hal_card_t *pCard, uint16_t ui16Offset, uint8_t ui8Size)
2100 {
2101
2102 #ifndef AM_HAL_DISABLE_API_VALIDATION
2103
2104 if ( !pCard || !pCard->pHost)
2105 {
2106 return 0xFFFFFFFF;
2107 }
2108
2109 #endif // AM_HAL_DISABLE_API_VALIDATION
2110
2111 if ( !pCard->bExtCsdValid )
2112 {
2113 if (am_hal_sdmmc_cmd8_send_ext_csd(pCard) != AM_HAL_CMD_ERR_NONE)
2114 {
2115 return 0xFFFFFFFF;
2116 }
2117 pCard->bExtCsdValid = 1;
2118 }
2119
2120 return am_hal_unstuff_bytes(pCard->ui32ExtCSD, ui16Offset, ui8Size);
2121
2122 }
2123
2124 //*****************************************************************************
2125 //
2126 // Get the card information function
2127 //
2128 //*****************************************************************************
2129 uint32_t
am_hal_card_get_info(am_hal_card_t * pCard,am_hal_card_info_t * pCardInfo)2130 am_hal_card_get_info(am_hal_card_t *pCard, am_hal_card_info_t *pCardInfo)
2131 {
2132 #ifndef AM_HAL_DISABLE_API_VALIDATION
2133 if ( !pCard || !pCard->pHost )
2134 {
2135 AM_HAL_CARD_DEBUG("both Card and Host are needed to be initialized firstly\n");
2136 return AM_HAL_STATUS_INVALID_ARG;
2137 }
2138 #endif // AM_HAL_DISABLE_API_VALIDATION
2139
2140 pCardInfo->eType = pCard->eType;
2141 pCardInfo->ui16CmdClass = pCard->ui16CmdClass;
2142 pCardInfo->ui8RCA = pCard->ui8RCA;
2143 pCardInfo->ui32MaxBlks = pCard->ui32MaxBlks;
2144 pCardInfo->ui32BlkSize = pCard->ui32BlkSize;
2145 if ( pCard->bHighCapcity )
2146 {
2147 pCardInfo->ui32LogiMaxBlks = pCard->ui32MaxBlks;
2148 pCardInfo->ui32LogiBlkSize = pCard->ui32BlkSize;
2149 }
2150 else
2151 {
2152 pCardInfo->ui32LogiMaxBlks = (pCard->ui32MaxBlks) * ((pCard->ui32BlkSize) / 512);
2153 pCardInfo->ui32LogiBlkSize = 512;
2154 }
2155
2156 return AM_HAL_STATUS_SUCCESS;
2157 }
2158
2159 uint32_t
am_hal_card_block_rpmb_rw(am_hal_card_t * pCard,uint8_t * pui8Buf,bool bRead,bool bRelWrite)2160 am_hal_card_block_rpmb_rw(am_hal_card_t *pCard, uint8_t *pui8Buf, bool bRead, bool bRelWrite)
2161 {
2162 uint32_t ui32Status;
2163
2164 am_hal_card_host_t *pHost;
2165 am_hal_card_cmd_t cmd;
2166 am_hal_card_cmd_data_t cmd_data;
2167
2168 #ifndef AM_HAL_DISABLE_API_VALIDATION
2169
2170 if ( !pCard || !pCard->pHost )
2171 {
2172 return AM_HAL_STATUS_INVALID_ARG;
2173 }
2174
2175 #endif // AM_HAL_DISABLE_API_VALIDATION
2176
2177 if ( pCard->eState != AM_HAL_CARD_STATE_TRANS )
2178 {
2179 return AM_HAL_STATUS_INVALID_OPERATION;
2180 }
2181
2182 pHost = pCard->pHost;
2183
2184 //
2185 // Send CMD23 firstly for mulitple blocks transfer
2186 //
2187 memset((void *)&cmd, 0x0, sizeof(cmd));
2188
2189 cmd.ui8Idx = MMC_CMD_SET_BLOCK_COUNT;
2190 cmd.ui32RespType = MMC_RSP_R1;
2191 cmd.ui32Arg = 1;
2192
2193 if ( bRelWrite )
2194 {
2195 cmd.ui32Arg |= ((uint32_t)0x01 << 31);
2196 }
2197
2198 if ( (ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, NULL)) != AM_HAL_STATUS_SUCCESS )
2199 {
2200 return ui32Status;
2201 }
2202
2203 memset((void *)&cmd, 0x0, sizeof(cmd));
2204 memset((void *)&cmd_data, 0x0, sizeof(cmd_data));
2205 if ( bRead )
2206 {
2207 cmd.ui8Idx = MMC_CMD_READ_MULTIPLE_BLOCK;
2208 }
2209 else
2210 {
2211 cmd.ui8Idx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
2212 }
2213
2214 cmd.ui32Arg = 0;
2215 cmd.ui32RespType = MMC_RSP_R1;
2216 cmd.bASync = false;
2217 cmd.bAutoCMD23 = false;
2218
2219 cmd_data.ui32BlkCnt = 1;
2220 cmd_data.pui8Buf = pui8Buf;
2221 cmd_data.ui32BlkSize = 512;
2222 cmd_data.dir = bRead ? AM_HAL_DATA_DIR_READ : AM_HAL_DATA_DIR_WRITE;
2223
2224 ui32Status = pHost->ops->execute_cmd(pHost->pHandle, &cmd, &cmd_data);
2225
2226 return ui32Status;
2227 }
2228
2229 //*****************************************************************************
2230 //
2231 // End Doxygen group.
2232 //! @}
2233 //
2234 //*****************************************************************************
2235