1 /**************************************************************************//**
2  * @file     sdh.c
3  * @version  V1.00
4  * @brief    SDH driver source file
5  *
6  * @copyright SPDX-License-Identifier: Apache-2.0
7  * @copyright Copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
8  *****************************************************************************/
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include "NuMicro.h"
13 
14 #if defined (__ICCARM__)
15 # pragma diag_suppress=Pm073, Pm143        /* Misra C 2004 rule 14.7 */
16 #endif
17 
18 
19 /** @addtogroup Standard_Driver Standard Driver
20   @{
21 */
22 
23 /** @addtogroup SDH_Driver SDH Driver
24   @{
25 */
26 
27 /** @addtogroup SDH_EXPORTED_FUNCTIONS SDH Exported Functions
28   @{
29 */
30 
31 #define SDH_BLOCK_SIZE   512UL
32 
33 /* #define DEBUG_PRINTF printf */
34 #define DEBUG_PRINTF(...)
35 
36 /** @cond HIDDEN_SYMBOLS */
37 
38 /* global variables */
39 /* For response R3 (such as ACMD41, CRC-7 is invalid; but SD controller will still */
40 /* calculate CRC-7 and get an error result, software should ignore this error and clear SDISR [CRC_IF] flag */
41 /* _sd_uR3_CMD is the flag for it. 1 means software should ignore CRC-7 error */
42 uint8_t g_u8R3Flag = 0UL;
43 uint8_t volatile g_u8SDDataReadyFlag = (uint8_t)FALSE;
44 
45 static uint32_t _SDH_uR7_CMD = 0UL;
46 static uint32_t _SDH_ReferenceClock;
47 
48 #if defined ( __ICCARM__ ) /*!< IAR Compiler */
49 #pragma data_alignment = 4
50 static uint8_t _SDH_ucSDHCBuffer[512];
51 #else
52 static __attribute__((aligned)) uint8_t _SDH_ucSDHCBuffer[512];
53 #endif
54 
55 /* Declare these functions here to avoid MISRA C 2004 rule 8.1 error */
56 void SDH_CheckRB(SDH_T *sdh);
57 uint32_t SDH_SDCommand(SDH_T *sdh, uint32_t u32Cmd, uint32_t u32Arg);
58 uint32_t SDH_SDCmdAndRsp(SDH_T *sdh, uint32_t u32Cmd, uint32_t u32Arg, uint32_t u32TickCount);
59 uint32_t SDH_Swap32(uint32_t u32Val);
60 uint32_t SDH_SDCmdAndRsp2(SDH_T *sdh, uint32_t u32Cmd, uint32_t u32Arg, uint32_t pu32R2ptr[]);
61 uint32_t SDH_SDCmdAndRspDataIn(SDH_T *sdh, uint32_t u32Cmd, uint32_t u32Arg);
62 void SDH_Set_clock(SDH_T *sdh, uint32_t u32SDClockKhz);
63 uint32_t SDH_CardDetection(SDH_T *sdh);
64 uint32_t SDH_Init(SDH_T *sdh);
65 uint32_t SDH_SwitchToHighSpeed(SDH_T *sdh, SDH_INFO_T *pSD);
66 uint32_t SDH_SelectCardType(SDH_T *sdh);
67 void SDH_Get_SD_info(SDH_T *sdh);
68 
69 SDH_INFO_T SD0;
70 
SDH_CheckRB(SDH_T * sdh)71 void SDH_CheckRB(SDH_T *sdh)
72 {
73     while(1)
74     {
75         sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
76         while(sdh->CTL & SDH_CTL_CLK8OEN_Msk) {}
77         if(sdh->INTSTS & SDH_INTSTS_DAT0STS_Msk)
78         {
79             break;
80         }
81     }
82 }
83 
84 
SDH_SDCommand(SDH_T * sdh,uint32_t u32Cmd,uint32_t u32Arg)85 uint32_t SDH_SDCommand(SDH_T *sdh, uint32_t u32Cmd, uint32_t u32Arg)
86 {
87     SDH_INFO_T *pSD;
88     volatile uint32_t u32Status = Successful;
89 
90     /* Only support SDH0 here*/
91     pSD = &SD0;
92 
93     sdh->CMDARG = u32Arg;
94     sdh->CTL = (sdh->CTL & (~SDH_CTL_CMDCODE_Msk)) | (u32Cmd << 8) | (SDH_CTL_COEN_Msk);
95 
96     while(sdh->CTL & SDH_CTL_COEN_Msk)
97     {
98         if(pSD->IsCardInsert == (uint32_t)FALSE)
99         {
100             u32Status = SDH_NO_SD_CARD;
101         }
102     }
103     return u32Status;
104 }
105 
106 
SDH_SDCmdAndRsp(SDH_T * sdh,uint32_t u32Cmd,uint32_t u32Arg,uint32_t u32TickCount)107 uint32_t SDH_SDCmdAndRsp(SDH_T *sdh, uint32_t u32Cmd, uint32_t u32Arg, uint32_t u32TickCount)
108 {
109     SDH_INFO_T *pSD;
110 
111     /* Only support SDH0 here*/
112     pSD = &SD0;
113 
114     sdh->CMDARG = u32Arg;
115     sdh->CTL = (sdh->CTL & (~SDH_CTL_CMDCODE_Msk)) | (u32Cmd << 8) | (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk);
116 
117     if(u32TickCount > 0UL)
118     {
119         while(sdh->CTL & SDH_CTL_RIEN_Msk)
120         {
121             if(u32TickCount-- == 0UL)
122             {
123                 sdh->CTL |= SDH_CTL_CTLRST_Msk; /* reset SD engine */
124                 return 2UL;
125             }
126             if(pSD->IsCardInsert == (uint8_t)FALSE)
127             {
128                 return SDH_NO_SD_CARD;
129             }
130         }
131     }
132     else
133     {
134         while(sdh->CTL & SDH_CTL_RIEN_Msk)
135         {
136             if(pSD->IsCardInsert == (uint8_t)FALSE)
137             {
138                 return SDH_NO_SD_CARD;
139             }
140         }
141     }
142 
143     if(_SDH_uR7_CMD)
144     {
145         if((sdh->RESP1 & 0xffUL) != 0x55UL)
146         {
147             if((sdh->RESP0 & 0xfUL) != 0x01UL)
148             {
149                 _SDH_uR7_CMD = 0UL;
150                 return SDH_CMD8_ERROR;
151             }
152         }
153     }
154 
155     if(!g_u8R3Flag)
156     {
157         if(sdh->INTSTS & SDH_INTSTS_CRC7_Msk)      /* check CRC7 */
158         {
159             return Successful;
160         }
161         else
162         {
163             return SDH_CRC7_ERROR;
164         }
165     }
166     else     /* ignore CRC error for R3 case */
167     {
168         g_u8R3Flag = 0UL;
169         sdh->INTSTS = SDH_INTSTS_CRCIF_Msk;
170         return Successful;
171     }
172 }
173 
174 
SDH_Swap32(uint32_t u32Val)175 uint32_t SDH_Swap32(uint32_t u32Val)
176 {
177     uint32_t u32Buf;
178 
179     u32Buf = u32Val;
180     u32Val <<= 24;
181     u32Val |= (u32Buf << 8) & 0xff0000UL;
182     u32Val |= (u32Buf >> 8) & 0xff00UL;
183     u32Val |= (u32Buf >> 24) & 0xffUL;
184     return u32Val;
185 }
186 
187 /* Get 16 bytes CID or CSD */
SDH_SDCmdAndRsp2(SDH_T * sdh,uint32_t u32Cmd,uint32_t u32Arg,uint32_t pu32R2ptr[])188 uint32_t SDH_SDCmdAndRsp2(SDH_T *sdh, uint32_t u32Cmd, uint32_t u32Arg, uint32_t pu32R2ptr[])
189 {
190     uint32_t i;
191     uint32_t au32TmpBuf[5];
192     SDH_INFO_T *pSD;
193 
194     /* Only support SDH0 here*/
195     pSD = &SD0;
196 
197     sdh->CMDARG = u32Arg;
198     sdh->CTL = (sdh->CTL & (~SDH_CTL_CMDCODE_Msk)) | (u32Cmd << 8) | (SDH_CTL_COEN_Msk | SDH_CTL_R2EN_Msk);
199 
200     while(sdh->CTL & SDH_CTL_R2EN_Msk)
201     {
202         if(pSD->IsCardInsert == (uint8_t)FALSE)
203         {
204             return SDH_NO_SD_CARD;
205         }
206     }
207 
208     if(sdh->INTSTS & SDH_INTSTS_CRC7_Msk)
209     {
210         for(i = 0UL; i < 5UL; i++)
211         {
212             au32TmpBuf[i] = SDH_Swap32(sdh->FB[i]);
213         }
214         for(i = 0UL; i < 4UL; i++)
215         {
216             pu32R2ptr[i] = ((au32TmpBuf[i] & 0x00ffffffUL) << 8) | ((au32TmpBuf[i + 1UL] & 0xff000000UL) >> 24);
217         }
218         return Successful;
219     }
220     else
221     {
222         return SDH_CRC7_ERROR;
223     }
224 }
225 
226 
SDH_SDCmdAndRspDataIn(SDH_T * sdh,uint32_t u32Cmd,uint32_t u32Arg)227 uint32_t SDH_SDCmdAndRspDataIn(SDH_T *sdh, uint32_t u32Cmd, uint32_t u32Arg)
228 {
229     SDH_INFO_T *pSD;
230 
231     /* Only support SDH0 here*/
232     pSD = &SD0;
233 
234     sdh->CMDARG = u32Arg;
235     sdh->CTL = (sdh->CTL & (~SDH_CTL_CMDCODE_Msk)) | ((uint32_t)u32Cmd << 8) |
236                (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DIEN_Msk);
237 
238     while(sdh->CTL & SDH_CTL_RIEN_Msk)
239     {
240         if(pSD->IsCardInsert == (uint32_t)FALSE)
241         {
242             return SDH_NO_SD_CARD;
243         }
244     }
245 
246     while(sdh->CTL & SDH_CTL_DIEN_Msk)
247     {
248         if(pSD->IsCardInsert == (uint32_t)FALSE)
249         {
250             return SDH_NO_SD_CARD;
251         }
252     }
253 
254     if(!(sdh->INTSTS & SDH_INTSTS_CRC7_Msk))       /* check CRC7 */
255     {
256         return SDH_CRC7_ERROR;
257     }
258 
259     if(!(sdh->INTSTS & SDH_INTSTS_CRC16_Msk))      /* check CRC16 */
260     {
261         return SDH_CRC16_ERROR;
262     }
263 
264     return Successful;
265 }
266 
267 /* there are 8 bits for divider0, maximum is 256 */
268 #define SDH_CLK_DIV0_MAX     256UL
269 
SDH_Set_clock(SDH_T * sdh,uint32_t u32SDClockKhz)270 void SDH_Set_clock(SDH_T *sdh, uint32_t u32SDClockKhz)
271 {
272     (void)sdh;
273     if(!(__PC() & (1UL << 28)))
274     {
275         uint32_t u32Rate, u32Div1;
276         static uint32_t u32SDClkSrc = 0UL;
277 
278         /* Only support SDH0 here*/
279         u32SDClkSrc = (CLK->CLKSEL0 & CLK_CLKSEL0_SDH0SEL_Msk);
280         if(u32SDClkSrc == CLK_CLKSEL0_SDH0SEL_HXT)
281         {
282             _SDH_ReferenceClock = (CLK_GetHXTFreq() / 1000UL);
283         }
284         else if(u32SDClkSrc == CLK_CLKSEL0_SDH0SEL_HIRC)
285         {
286             _SDH_ReferenceClock = (__HIRC / 1000UL);
287         }
288         else if(u32SDClkSrc == CLK_CLKSEL0_SDH0SEL_PLL)
289         {
290             _SDH_ReferenceClock = (CLK_GetPLLClockFreq() / 1000UL);
291         }
292         else if(u32SDClkSrc == CLK_CLKSEL0_SDH0SEL_HCLK)
293         {
294             _SDH_ReferenceClock = (CLK_GetHCLKFreq() / 1000UL);
295         }
296 
297         if(u32SDClockKhz >= 50000UL)
298         {
299             u32SDClockKhz = 50000UL;
300         }
301         u32Rate = _SDH_ReferenceClock / u32SDClockKhz;
302 
303         /* choose slower clock if system clock cannot divisible by wanted clock */
304         if(_SDH_ReferenceClock % u32SDClockKhz != 0UL)
305         {
306             u32Rate++;
307         }
308 
309         if(u32Rate >= SDH_CLK_DIV0_MAX)
310         {
311             u32Rate = SDH_CLK_DIV0_MAX;
312         }
313 
314         /* --- calculate the second divider CLKDIV0[SDHOST_N] */
315         if(u32Rate == 0UL)
316         {
317             u32Div1 = 0UL;
318         }
319         else
320         {
321             u32Div1 = ((u32Rate - 1UL) & 0xFFUL);
322         }
323 
324         /* --- setup register */
325         /* Only support SDH0 here*/
326         CLK->CLKDIV0 &= ~CLK_CLKDIV0_SDH0DIV_Msk;
327         CLK->CLKDIV0 |= (u32Div1 << CLK_CLKDIV0_SDH0DIV_Pos);
328     }
329 }
330 
SDH_CardDetection(SDH_T * sdh)331 uint32_t SDH_CardDetection(SDH_T *sdh)
332 {
333     uint32_t i, u32Status = (uint32_t)TRUE;
334     SDH_INFO_T *pSD;
335 
336     /* Only support SDH0 here*/
337     pSD = &SD0;
338 
339     if(sdh->INTEN & SDH_INTEN_CDSRC_Msk)   /* Card detect pin from GPIO */
340     {
341         if(sdh->INTSTS & SDH_INTSTS_CDSTS_Msk)   /* Card remove */
342         {
343             pSD->IsCardInsert = (uint8_t)FALSE;
344             u32Status = (uint32_t)FALSE;
345         }
346         else
347         {
348             pSD->IsCardInsert = (uint8_t)TRUE;
349         }
350     }
351     else if(!(sdh->INTEN & SDH_INTEN_CDSRC_Msk))
352     {
353         sdh->CTL |= SDH_CTL_CLKKEEP_Msk;
354         for(i = 0UL; i < 5000UL; i++) {}
355 
356         if(sdh->INTSTS & SDH_INTSTS_CDSTS_Msk) /* Card insert */
357         {
358             pSD->IsCardInsert = (uint8_t)TRUE;
359         }
360         else
361         {
362             pSD->IsCardInsert = (uint8_t)FALSE;
363             u32Status = (uint32_t)FALSE;
364         }
365 
366         sdh->CTL &= ~SDH_CTL_CLKKEEP_Msk;
367     }
368 
369     return u32Status;
370 }
371 
372 
373 /* Initial */
SDH_Init(SDH_T * sdh)374 uint32_t SDH_Init(SDH_T *sdh)
375 {
376     uint32_t volatile i, u32Status;
377     uint32_t u32Resp;
378     uint32_t au32CIDBuffer[4];
379     uint32_t volatile u32CmdTimeOut;
380     SDH_INFO_T *pSD;
381 
382     /* Only support SDH0 here*/
383     pSD = &SD0;
384 
385     /* set the clock to 300KHz */
386     SDH_Set_clock(sdh, 300UL);
387 
388     /* power ON 74 clock */
389     sdh->CTL |= SDH_CTL_CLK74OEN_Msk;
390 
391     while(sdh->CTL & SDH_CTL_CLK74OEN_Msk)
392     {
393         if(pSD->IsCardInsert == (uint8_t)FALSE)
394         {
395             return SDH_NO_SD_CARD;
396         }
397     }
398 
399     SDH_SDCommand(sdh, 0UL, 0UL);        /* reset all cards */
400     for(i = 0x1000UL; i > 0UL; i--) {}
401 
402     /* initial SDHC */
403     _SDH_uR7_CMD = 1UL;
404     u32CmdTimeOut = 0xFFFFFUL;
405 
406     i = SDH_SDCmdAndRsp(sdh, 8UL, 0x00000155UL, u32CmdTimeOut);
407     if(i == Successful)
408     {
409         /* SD 2.0 */
410         SDH_SDCmdAndRsp(sdh, 55UL, 0x00UL, u32CmdTimeOut);
411         g_u8R3Flag = 1UL;
412         SDH_SDCmdAndRsp(sdh, 41UL, 0x40ff8000UL, u32CmdTimeOut); /* 2.7v-3.6v */
413         u32Resp = sdh->RESP0;
414 
415         while(!(u32Resp & 0x00800000UL))         /* check if card is ready */
416         {
417             SDH_SDCmdAndRsp(sdh, 55UL, 0x00UL, u32CmdTimeOut);
418             g_u8R3Flag = 1UL;
419             SDH_SDCmdAndRsp(sdh, 41UL, 0x40ff8000UL, u32CmdTimeOut); /* 3.0v-3.4v */
420             u32Resp = sdh->RESP0;
421         }
422         if(u32Resp & 0x00400000UL)
423         {
424             pSD->CardType = SDH_TYPE_SD_HIGH;
425         }
426         else
427         {
428             pSD->CardType = SDH_TYPE_SD_LOW;
429         }
430     }
431     else
432     {
433         /* SD 1.1 */
434         SDH_SDCommand(sdh, 0UL, 0UL);        /* reset all cards */
435         for(i = 0x100UL; i > 0UL; i--) {}
436 
437         i = SDH_SDCmdAndRsp(sdh, 55UL, 0x00UL, u32CmdTimeOut);
438         if(i == 2UL)      /* MMC memory */
439         {
440             SDH_SDCommand(sdh, 0UL, 0UL);        /* reset */
441             for(i = 0x100UL; i > 0UL; i--) {}
442 
443             g_u8R3Flag = 1UL;
444 
445             if(SDH_SDCmdAndRsp(sdh, 1UL, 0x40ff8000UL, u32CmdTimeOut) != 2UL)     /* eMMC memory */
446             {
447                 u32Resp = sdh->RESP0;
448                 while(!(u32Resp & 0x00800000UL))         /* check if card is ready */
449                 {
450                     g_u8R3Flag = 1UL;
451 
452                     SDH_SDCmdAndRsp(sdh, 1UL, 0x40ff8000UL, u32CmdTimeOut);      /* high voltage */
453                     u32Resp = sdh->RESP0;
454                 }
455 
456                 if(u32Resp & 0x00400000UL)
457                 {
458                     pSD->CardType = SDH_TYPE_EMMC;
459                 }
460                 else
461                 {
462                     pSD->CardType = SDH_TYPE_MMC;
463                 }
464             }
465             else
466             {
467                 pSD->CardType = SDH_TYPE_UNKNOWN;
468                 return SDH_ERR_DEVICE;
469             }
470         }
471         else if(i == 0UL)      /* SD Memory */
472         {
473             g_u8R3Flag = 1UL;
474             SDH_SDCmdAndRsp(sdh, 41UL, 0x00ff8000UL, u32CmdTimeOut); /* 3.0v-3.4v */
475             u32Resp = sdh->RESP0;
476             while(!(u32Resp & 0x00800000UL))         /* check if card is ready */
477             {
478                 SDH_SDCmdAndRsp(sdh, 55UL, 0x00UL, u32CmdTimeOut);
479                 g_u8R3Flag = 1UL;
480                 SDH_SDCmdAndRsp(sdh, 41UL, 0x00ff8000UL, u32CmdTimeOut); /* 3.0v-3.4v */
481                 u32Resp = sdh->RESP0;
482             }
483             pSD->CardType = SDH_TYPE_SD_LOW;
484         }
485         else
486         {
487             pSD->CardType = SDH_TYPE_UNKNOWN;
488             return SDH_INIT_ERROR;
489         }
490     }
491 
492     /* CMD2, CMD3 */
493     if(pSD->CardType != SDH_TYPE_UNKNOWN)
494     {
495         SDH_SDCmdAndRsp2(sdh, 2UL, 0x00UL, au32CIDBuffer);
496         if((pSD->CardType == SDH_TYPE_MMC) || (pSD->CardType == SDH_TYPE_EMMC))
497         {
498             if((u32Status = SDH_SDCmdAndRsp(sdh, 3UL, 0x10000UL, 0UL)) != Successful)         /* set RCA */
499             {
500                 return u32Status;
501             }
502             pSD->RCA = 0x10000UL;
503         }
504         else
505         {
506             if((u32Status = SDH_SDCmdAndRsp(sdh, 3UL, 0x00UL, 0UL)) != Successful)        /* get RCA */
507             {
508                 return u32Status;
509             }
510             else
511             {
512                 pSD->RCA = (sdh->RESP0 << 8) & 0xffff0000UL;
513             }
514         }
515     }
516 
517     return Successful;
518 }
519 
520 
SDH_SwitchToHighSpeed(SDH_T * sdh,SDH_INFO_T * pSD)521 uint32_t SDH_SwitchToHighSpeed(SDH_T *sdh, SDH_INFO_T *pSD)
522 {
523     uint32_t volatile u32Status = 0UL;
524     uint16_t u16CurrentComsumption, u16BusyStatus0;
525 
526     (void)pSD;
527     sdh->DMASA = (uint32_t)_SDH_ucSDHCBuffer;    /* set DMA transfer starting address */
528     sdh->BLEN = 63UL;    /* 512 bit */
529 
530     if((u32Status = SDH_SDCmdAndRspDataIn(sdh, 6UL, 0x00ffff01UL)) != Successful)
531     {
532         return Fail;
533     }
534 
535     u16CurrentComsumption = (uint16_t)(_SDH_ucSDHCBuffer[0] << 8);
536     u16CurrentComsumption |= (uint16_t)_SDH_ucSDHCBuffer[1];
537     if(!u16CurrentComsumption)
538     {
539         return Fail;
540     }
541 
542     u16BusyStatus0 = (uint16_t)(_SDH_ucSDHCBuffer[28] << 8);
543     u16BusyStatus0 |= (uint16_t)_SDH_ucSDHCBuffer[29];
544 
545     if(!u16BusyStatus0)    /* function ready */
546     {
547         sdh->DMASA = (uint32_t)_SDH_ucSDHCBuffer;        /* set DMA transfer starting address */
548         sdh->BLEN = 63UL;    /* 512 bit */
549 
550         if((u32Status = SDH_SDCmdAndRspDataIn(sdh, 6UL, 0x80ffff01UL)) != Successful)
551         {
552             return Fail;
553         }
554 
555         /* function change timing: 8 clocks */
556         sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
557         while(sdh->CTL & SDH_CTL_CLK8OEN_Msk) {}
558 
559         u16CurrentComsumption = (uint16_t)(_SDH_ucSDHCBuffer[0] << 8);
560         u16CurrentComsumption |= (uint16_t)_SDH_ucSDHCBuffer[1];
561         if(!u16CurrentComsumption)
562         {
563             return Fail;
564         }
565 
566         return Successful;
567     }
568     else
569     {
570         return Fail;
571     }
572 }
573 
574 
SDH_SelectCardType(SDH_T * sdh)575 uint32_t SDH_SelectCardType(SDH_T *sdh)
576 {
577     uint32_t volatile u32Status = 0UL;
578     uint32_t u32Param;
579     SDH_INFO_T *pSD;
580 
581     /* Only support SDH0 here*/
582     pSD = &SD0;
583 
584     if((u32Status = SDH_SDCmdAndRsp(sdh, 7UL, pSD->RCA, 0UL)) != Successful)
585     {
586         return u32Status;
587     }
588 
589     SDH_CheckRB(sdh);
590 
591     /* if SD card set 4bit */
592     if(pSD->CardType == SDH_TYPE_SD_HIGH)
593     {
594         sdh->DMASA = (uint32_t)_SDH_ucSDHCBuffer;    /* set DMA transfer starting address */
595         sdh->BLEN = 0x07UL;  /* 64 bit */
596 
597         if((u32Status = SDH_SDCmdAndRsp(sdh, 55UL, pSD->RCA, 0UL)) != Successful)
598         {
599             return u32Status;
600         }
601 
602         sdh->DMACTL |= 0x2;
603         while(sdh->DMACTL & 0x2) {}
604 
605         if((u32Status = SDH_SDCmdAndRspDataIn(sdh, 51UL, 0x00UL)) != Successful)
606         {
607             return u32Status;
608         }
609 
610         if((_SDH_ucSDHCBuffer[0] & 0xfUL) == 0xfUL)
611         {
612             u32Status = SDH_SwitchToHighSpeed(sdh, pSD);
613             if(u32Status == Successful)
614             {
615                 /* divider */
616                 SDH_Set_clock(sdh, SDHC_FREQ);
617             }
618         }
619 
620         if((u32Status = SDH_SDCmdAndRsp(sdh, 55UL, pSD->RCA, 0UL)) != Successful)
621         {
622             return u32Status;
623         }
624         if((u32Status = SDH_SDCmdAndRsp(sdh, 6UL, 0x02UL, 0UL)) != Successful)    /* set bus width */
625         {
626             return u32Status;
627         }
628 
629         sdh->CTL |= SDH_CTL_DBW_Msk;
630     }
631     else if(pSD->CardType == SDH_TYPE_SD_LOW)
632     {
633         sdh->DMASA = (uint32_t) _SDH_ucSDHCBuffer; /* set DMA transfer starting address */
634         sdh->BLEN = 0x07UL;  /* 64 bit */
635 
636         if((u32Status = SDH_SDCmdAndRsp(sdh, 55UL, pSD->RCA, 0UL)) != Successful)
637         {
638             return u32Status;
639         }
640         if((u32Status = SDH_SDCmdAndRspDataIn(sdh, 51UL, 0x00UL)) != Successful)
641         {
642             return u32Status;
643         }
644 
645         /* set data bus width. ACMD6 for SD card, SDCR_DBW for host. */
646         if((u32Status = SDH_SDCmdAndRsp(sdh, 55UL, pSD->RCA, 0UL)) != Successful)
647         {
648             return u32Status;
649         }
650 
651         if((u32Status = SDH_SDCmdAndRsp(sdh, 6UL, 0x02UL, 0UL)) != Successful)    /* set bus width */
652         {
653             return u32Status;
654         }
655 
656         sdh->CTL |= SDH_CTL_DBW_Msk;
657     }
658     else if((pSD->CardType == SDH_TYPE_MMC) || (pSD->CardType == SDH_TYPE_EMMC))
659     {
660 
661         if(pSD->CardType == SDH_TYPE_MMC)
662         {
663             sdh->CTL &= ~SDH_CTL_DBW_Msk;
664         }
665 
666         /* --- sent CMD6 to MMC card to set bus width to 4 bits mode */
667         /* set CMD6 argument Access field to 3, Index to 183, Value to 1 (4-bit mode) */
668         u32Param = (3UL << 24) | (183UL << 16) | (1UL << 8);
669         if((u32Status = SDH_SDCmdAndRsp(sdh, 6UL, u32Param, 0UL)) != Successful)
670         {
671             return u32Status;
672         }
673         SDH_CheckRB(sdh);
674 
675         sdh->CTL |= SDH_CTL_DBW_Msk; /* set bus width to 4-bit mode for SD host controller */
676     }
677 
678     if((u32Status = SDH_SDCmdAndRsp(sdh, 16UL, SDH_BLOCK_SIZE, 0UL)) != Successful)  /* set block length */
679     {
680         return u32Status;
681     }
682     sdh->BLEN = SDH_BLOCK_SIZE - 1UL;           /* set the block size */
683 
684     SDH_SDCommand(sdh, 7UL, 0UL);
685     sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
686     while(sdh->CTL & SDH_CTL_CLK8OEN_Msk) {}
687 
688     sdh->INTEN |= SDH_INTEN_BLKDIEN_Msk;
689 
690     return Successful;
691 }
692 
SDH_Get_SD_info(SDH_T * sdh)693 void SDH_Get_SD_info(SDH_T *sdh)
694 {
695     uint32_t u32RLen, u32CSize, u32Mult, u32Size;
696     uint32_t au32Buffer[4];
697     SDH_INFO_T *pSD;
698 
699     /* Only support SDH0 here*/
700     pSD = &SD0;
701 
702     SDH_SDCmdAndRsp2(sdh, 9UL, pSD->RCA, au32Buffer);
703 
704     if((pSD->CardType == SDH_TYPE_MMC) || (pSD->CardType == SDH_TYPE_EMMC))
705     {
706         /* for MMC/eMMC card */
707         if((au32Buffer[0] & 0xc0000000UL) == 0xc0000000UL)
708         {
709             /* CSD_STRUCTURE [127:126] is 3 */
710             /* CSD version depend on EXT_CSD register in eMMC v4.4 for card size > 2GB */
711             SDH_SDCmdAndRsp(sdh, 7UL, pSD->RCA, 0UL);
712 
713             sdh->DMASA = (uint32_t)_SDH_ucSDHCBuffer;  /* set DMA transfer starting address */
714             sdh->BLEN = 511UL;  /* read 512 bytes for EXT_CSD */
715 
716             if(SDH_SDCmdAndRspDataIn(sdh, 8UL, 0x00UL) != Successful)
717             {
718                 return;
719             }
720 
721             SDH_SDCommand(sdh, 7UL, 0UL);
722             sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
723             while(sdh->CTL & SDH_CTL_CLK8OEN_Msk) {}
724 
725             pSD->totalSectorN = (uint32_t)_SDH_ucSDHCBuffer[215] << 24;
726             pSD->totalSectorN |= (uint32_t)_SDH_ucSDHCBuffer[214] << 16;
727             pSD->totalSectorN |= (uint32_t)_SDH_ucSDHCBuffer[213] << 8;
728             pSD->totalSectorN |= (uint32_t)_SDH_ucSDHCBuffer[212];
729             pSD->diskSize = pSD->totalSectorN / 2UL;
730         }
731         else
732         {
733             /* CSD version v1.0/1.1/1.2 in eMMC v4.4 spec for card size <= 2GB */
734             u32RLen = (au32Buffer[1] & 0x000f0000UL) >> 16;
735             u32CSize = ((au32Buffer[1] & 0x000003ffUL) << 2) | ((au32Buffer[2] & 0xc0000000UL) >> 30);
736             u32Mult = (au32Buffer[2] & 0x00038000UL) >> 15;
737             u32Size = (u32CSize + 1UL) * (1UL << (u32Mult + 2UL)) * (1UL << u32RLen);
738 
739             pSD->diskSize = u32Size / 1024UL;
740             pSD->totalSectorN = u32Size / 512UL;
741         }
742     }
743     else
744     {
745         if(au32Buffer[0] & 0xc0000000UL)
746         {
747             u32CSize = ((au32Buffer[1] & 0x0000003fUL) << 16) | ((au32Buffer[2] & 0xffff0000UL) >> 16);
748             u32Size = (u32CSize + 1UL) * 512UL;  /* Kbytes */
749 
750             pSD->diskSize = u32Size;
751             pSD->totalSectorN = u32Size << 1;
752         }
753         else
754         {
755             u32RLen = (au32Buffer[1] & 0x000f0000UL) >> 16;
756             u32CSize = ((au32Buffer[1] & 0x000003ffUL) << 2) | ((au32Buffer[2] & 0xc0000000UL) >> 30);
757             u32Mult = (au32Buffer[2] & 0x00038000UL) >> 15;
758             u32Size = (u32CSize + 1UL) * (1UL << (u32Mult + 2UL)) * (1UL << u32RLen);
759 
760             pSD->diskSize = u32Size / 1024UL;
761             pSD->totalSectorN = u32Size / 512UL;
762         }
763     }
764     pSD->sectorSize = (int)512UL;
765 }
766 
767 /** @endcond HIDDEN_SYMBOLS */
768 
769 
770 /**
771  *  @brief  This function use to reset SD function and select card detection source and pin.
772  *
773  *  @param[in]  sdh    The pointer of the specified SDH module.
774  *  @param[in]  u32CardDetSrc   Select card detection pin from GPIO or DAT3 pin. ( \ref CardDetect_From_GPIO / \ref CardDetect_From_DAT3)
775  *
776  *  @return None
777  */
SDH_Open(SDH_T * sdh,uint32_t u32CardDetSrc)778 void SDH_Open(SDH_T *sdh, uint32_t u32CardDetSrc)
779 {
780     /* enable DMAC */
781     sdh->DMACTL = SDH_DMACTL_DMARST_Msk;
782     while(sdh->DMACTL & SDH_DMACTL_DMARST_Msk) {}
783 
784     sdh->DMACTL = SDH_DMACTL_DMAEN_Msk;
785 
786     /* Reset FMI */
787     sdh->GCTL = SDH_GCTL_GCTLRST_Msk | SDH_GCTL_SDEN_Msk;        /* Start reset FMI controller. */
788     while(sdh->GCTL & SDH_GCTL_GCTLRST_Msk) {}
789 
790     memset(&SD0, 0, sizeof(SDH_INFO_T));
791 
792     /* enable SD */
793     sdh->GCTL = SDH_GCTL_SDEN_Msk;
794 
795     if(u32CardDetSrc & CardDetect_From_DAT3)
796     {
797         sdh->INTEN &= ~SDH_INTEN_CDSRC_Msk;
798     }
799     else
800     {
801         sdh->INTEN |= SDH_INTEN_CDSRC_Msk;
802     }
803     sdh->INTEN |= SDH_INTEN_CDIEN_Msk;
804 
805     sdh->CTL |= SDH_CTL_CTLRST_Msk;     /* SD software reset */
806     while(sdh->CTL & SDH_CTL_CTLRST_Msk) {}
807 
808 }
809 
810 /**
811  *  @brief  This function use to initial SD card.
812  *
813  *  @param[in]    sdh    The pointer of the specified SDH module.
814  *
815  *  @return None
816  *
817  *  @details This function is used to initial SD card.
818  *           SD initial state needs 400KHz clock output, driver will use HIRC for SD initial clock source.
819  *           And then switch back to the user's setting.
820  */
SDH_Probe(SDH_T * sdh)821 uint32_t SDH_Probe(SDH_T *sdh)
822 {
823     uint32_t u32Val;
824 
825     /* Disable FMI/SD host interrupt */
826     sdh->GINTEN = 0UL;
827 
828     sdh->CTL &= ~SDH_CTL_SDNWR_Msk;
829     sdh->CTL |=  0x09UL << SDH_CTL_SDNWR_Pos;         /* set SDNWR = 9 */
830     sdh->CTL &= ~SDH_CTL_BLKCNT_Msk;
831     sdh->CTL |=  0x01UL << SDH_CTL_BLKCNT_Pos;           /* set BLKCNT = 1 */
832     sdh->CTL &= ~SDH_CTL_DBW_Msk;               /* SD 1-bit data bus */
833 
834     if(!(SDH_CardDetection(sdh)))
835     {
836         return SDH_NO_SD_CARD;
837     }
838 
839     if((u32Val = SDH_Init(sdh)) != 0UL)
840     {
841         return u32Val;
842     }
843 
844     /* divider */
845     if(SD0.CardType == SDH_TYPE_MMC)
846     {
847         SDH_Set_clock(sdh, MMC_FREQ);
848     }
849     else
850     {
851         SDH_Set_clock(sdh, SD_FREQ);
852     }
853     SDH_Get_SD_info(sdh);
854 
855     if((u32Val = SDH_SelectCardType(sdh)) != 0UL)
856     {
857         return u32Val;
858     }
859 
860     return 0UL;
861 }
862 
863 /**
864  *  @brief  This function use to read data from SD card.
865  *
866  *  @param[in]     sdh           The pointer of the specified SDH module.
867  *  @param[out]    pu8BufAddr    The buffer to receive the data from SD card.
868  *  @param[in]     u32StartSec   The start read sector address.
869  *  @param[in]     u32SecCount   The the read sector number of data
870  *
871  *  @return None
872  */
SDH_Read(SDH_T * sdh,uint8_t * pu8BufAddr,uint32_t u32StartSec,uint32_t u32SecCount)873 uint32_t SDH_Read(SDH_T *sdh, uint8_t *pu8BufAddr, uint32_t u32StartSec, uint32_t u32SecCount)
874 {
875     uint32_t volatile u32IsSendCmd = (uint32_t)FALSE;
876     uint32_t volatile u32Reg;
877     uint32_t volatile u32Loop, u32Status;
878     uint32_t u32BlkSize = SDH_BLOCK_SIZE;
879 
880     SDH_INFO_T *pSD;
881 
882     /* Only support SDH0 here*/
883     pSD = &SD0;
884 
885     /* --- check input parameters */
886     if(u32SecCount == 0UL)
887     {
888         return SDH_SELECT_ERROR;
889     }
890 
891     if((u32Status = SDH_SDCmdAndRsp(sdh, 7UL, pSD->RCA, 0UL)) != Successful)
892     {
893         return u32Status;
894     }
895     SDH_CheckRB(sdh);
896 
897     sdh->BLEN = u32BlkSize - 1UL;       /* the actual byte count is equal to (SDBLEN+1) */
898 
899     if((pSD->CardType == SDH_TYPE_SD_HIGH) || (pSD->CardType == SDH_TYPE_EMMC))
900     {
901         sdh->CMDARG = u32StartSec;
902     }
903     else
904     {
905         sdh->CMDARG = u32StartSec * u32BlkSize;
906     }
907 
908     sdh->DMASA = (uint32_t)pu8BufAddr;
909 
910     u32Loop = u32SecCount / 255UL;
911     while(u32Loop > 0UL)
912     {
913         g_u8SDDataReadyFlag = (uint8_t)FALSE;
914         u32Reg = sdh->CTL & ~SDH_CTL_CMDCODE_Msk;
915         u32Reg = u32Reg | 0xff0000UL;   /* set BLK_CNT to 255 */
916         if(u32IsSendCmd == (uint32_t)FALSE)
917         {
918             sdh->CTL = u32Reg | (18UL << 8) | (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DIEN_Msk);
919             u32IsSendCmd = (uint32_t)TRUE;
920         }
921         else
922         {
923             sdh->CTL = u32Reg | SDH_CTL_DIEN_Msk;
924         }
925 
926         while(!g_u8SDDataReadyFlag)
927         {
928             if(g_u8SDDataReadyFlag)
929             {
930                 break;
931             }
932             if(pSD->IsCardInsert == (uint8_t)FALSE)
933             {
934                 return SDH_NO_SD_CARD;
935             }
936         }
937 
938         if(!(sdh->INTSTS & SDH_INTSTS_CRC7_Msk))     /* check CRC7 */
939         {
940             return SDH_CRC7_ERROR;
941         }
942 
943         if(!(sdh->INTSTS & SDH_INTSTS_CRC16_Msk))    /* check CRC16 */
944         {
945             return SDH_CRC16_ERROR;
946         }
947         u32Loop--;
948     }
949 
950     u32Loop = u32SecCount % 255UL;
951     if(u32Loop != 0UL)
952     {
953         uint32_t u32RegTmp;
954         g_u8SDDataReadyFlag = (uint8_t)FALSE;
955         u32Reg = sdh->CTL & (~SDH_CTL_CMDCODE_Msk);
956         u32Reg = u32Reg & (~SDH_CTL_BLKCNT_Msk);
957         u32RegTmp = (u32Loop << 16);
958         u32Reg |= u32RegTmp;    /* setup SDCR_BLKCNT */
959 
960         if(u32IsSendCmd == (uint32_t)FALSE)
961         {
962             sdh->CTL = u32Reg | (18UL << 8) | (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DIEN_Msk);
963             u32IsSendCmd = (uint32_t)TRUE;
964         }
965         else
966         {
967             sdh->CTL = u32Reg | SDH_CTL_DIEN_Msk;
968         }
969 
970         while(!g_u8SDDataReadyFlag)
971         {
972             if(pSD->IsCardInsert == (uint8_t)FALSE)
973             {
974                 return SDH_NO_SD_CARD;
975             }
976         }
977 
978         if(!(sdh->INTSTS & SDH_INTSTS_CRC7_Msk))     /* check CRC7 */
979         {
980             return SDH_CRC7_ERROR;
981         }
982 
983         if(!(sdh->INTSTS & SDH_INTSTS_CRC16_Msk))     /* check CRC16 */
984         {
985             return SDH_CRC16_ERROR;
986         }
987     }
988 
989     if(SDH_SDCmdAndRsp(sdh, 12UL, 0UL, 0UL))     /* stop command */
990     {
991         return SDH_CRC7_ERROR;
992     }
993     SDH_CheckRB(sdh);
994 
995     SDH_SDCommand(sdh, 7UL, 0UL);
996     sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
997     while(sdh->CTL & SDH_CTL_CLK8OEN_Msk) {}
998 
999     return Successful;
1000 }
1001 
1002 /**
1003  *  @brief  This function use to write data to SD card.
1004  *
1005  *  @param[in]    sdh           The pointer of the specified SDH module.
1006  *  @param[in]    pu8BufAddr    The buffer to send the data to SD card.
1007  *  @param[in]    u32StartSec   The start write sector address.
1008  *  @param[in]    u32SecCount   The the write sector number of data.
1009  *
1010  *  @return   \ref SDH_SELECT_ERROR : u32SecCount is zero. \n
1011  *            \ref SDH_NO_SD_CARD : SD card be removed. \n
1012  *            \ref SDH_CRC_ERROR : CRC error happen. \n
1013  *            \ref SDH_CRC7_ERROR : CRC7 error happen. \n
1014  *            \ref Successful : Write data to SD card success.
1015  */
SDH_Write(SDH_T * sdh,uint8_t * pu8BufAddr,uint32_t u32StartSec,uint32_t u32SecCount)1016 uint32_t SDH_Write(SDH_T *sdh, uint8_t *pu8BufAddr, uint32_t u32StartSec, uint32_t u32SecCount)
1017 {
1018     uint32_t volatile u32IsSendCmd = (uint32_t)FALSE;
1019     uint32_t volatile u32Reg;
1020     uint32_t volatile u32Loop, u32Status;
1021 
1022     SDH_INFO_T *pSD;
1023 
1024     /* Only support SDH0 here*/
1025     pSD = &SD0;
1026 
1027     /* --- check input parameters */
1028     if(u32SecCount == 0UL)
1029     {
1030         return SDH_SELECT_ERROR;
1031     }
1032 
1033     if((u32Status = SDH_SDCmdAndRsp(sdh, 7UL, pSD->RCA, 0UL)) != Successful)
1034     {
1035         return u32Status;
1036     }
1037 
1038     SDH_CheckRB(sdh);
1039 
1040     /* According to SD Spec v2.0, the write CMD block size MUST be 512, and the start address MUST be 512*n. */
1041     sdh->BLEN = SDH_BLOCK_SIZE - 1UL;           /* set the block size */
1042 
1043     if((pSD->CardType == SDH_TYPE_SD_HIGH) || (pSD->CardType == SDH_TYPE_EMMC))
1044     {
1045         sdh->CMDARG = u32StartSec;
1046     }
1047     else
1048     {
1049         sdh->CMDARG = u32StartSec * SDH_BLOCK_SIZE;  /* set start address for SD CMD */
1050     }
1051 
1052     sdh->DMASA = (uint32_t)pu8BufAddr;
1053     u32Loop = u32SecCount / 255UL;   /* the maximum block count is 0xFF=255 for register SDCR[BLK_CNT] */
1054     while(u32Loop > 0UL)
1055     {
1056         g_u8SDDataReadyFlag = (uint8_t)FALSE;
1057         u32Reg = sdh->CTL & 0xff00c080UL;
1058         u32Reg = u32Reg | 0xff0000UL;   /* set BLK_CNT to 0xFF=255 */
1059         if(!u32IsSendCmd)
1060         {
1061             sdh->CTL = u32Reg | (25UL << 8) | (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DOEN_Msk);
1062             u32IsSendCmd = (uint32_t)TRUE;
1063         }
1064         else
1065         {
1066             sdh->CTL = u32Reg | SDH_CTL_DOEN_Msk;
1067         }
1068 
1069         while(!g_u8SDDataReadyFlag)
1070         {
1071             if(pSD->IsCardInsert == (uint8_t)FALSE)
1072             {
1073                 return SDH_NO_SD_CARD;
1074             }
1075         }
1076 
1077         if((sdh->INTSTS & SDH_INTSTS_CRCIF_Msk) != 0UL)      /* check CRC */
1078         {
1079             sdh->INTSTS = SDH_INTSTS_CRCIF_Msk;
1080             return SDH_CRC_ERROR;
1081         }
1082         u32Loop--;
1083     }
1084 
1085     u32Loop = u32SecCount % 255UL;
1086     if(u32Loop != 0UL)
1087     {
1088         uint32_t u32RegTmp;
1089         g_u8SDDataReadyFlag = (uint8_t)FALSE;
1090         u32RegTmp = (u32Loop << 16);
1091         u32Reg = (sdh->CTL & 0xff00c080UL) | u32RegTmp;
1092         if(!u32IsSendCmd)
1093         {
1094             sdh->CTL = u32Reg | (25UL << 8) | (SDH_CTL_COEN_Msk | SDH_CTL_RIEN_Msk | SDH_CTL_DOEN_Msk);
1095             u32IsSendCmd = (uint32_t)TRUE;
1096         }
1097         else
1098         {
1099             sdh->CTL = u32Reg | SDH_CTL_DOEN_Msk;
1100         }
1101 
1102         while(!g_u8SDDataReadyFlag)
1103         {
1104             if(pSD->IsCardInsert == (uint8_t)FALSE)
1105             {
1106                 return SDH_NO_SD_CARD;
1107             }
1108         }
1109 
1110         if((sdh->INTSTS & SDH_INTSTS_CRCIF_Msk) != 0UL)      /* check CRC */
1111         {
1112             sdh->INTSTS = SDH_INTSTS_CRCIF_Msk;
1113             return SDH_CRC_ERROR;
1114         }
1115     }
1116     sdh->INTSTS = SDH_INTSTS_CRCIF_Msk;
1117 
1118     if(SDH_SDCmdAndRsp(sdh, 12UL, 0UL, 0UL))       /* stop command */
1119     {
1120         return SDH_CRC7_ERROR;
1121     }
1122     SDH_CheckRB(sdh);
1123 
1124     SDH_SDCommand(sdh, 7UL, 0UL);
1125     sdh->CTL |= SDH_CTL_CLK8OEN_Msk;
1126     while(sdh->CTL & SDH_CTL_CLK8OEN_Msk) {}
1127 
1128     return Successful;
1129 }
1130 
1131 
1132 /**@}*/ /* end of group SDH_EXPORTED_FUNCTIONS */
1133 
1134 /**@}*/ /* end of group SDH_Driver */
1135 
1136 /**@}*/ /* end of group Standard_Driver */
1137