nu_fmi.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920
  1. /**************************************************************************//**
  2. * @file fmi.c
  3. * @brief N9H30 FMI eMMC driver source file
  4. *
  5. * @note
  6. * SPDX-License-Identifier: Apache-2.0
  7. * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved.
  8. *****************************************************************************/
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include "N9H30.h"
  13. #include "nu_sys.h"
  14. #include "nu_fmi.h"
  15. /** @addtogroup N9H30_Device_Driver N9H30 Device Driver
  16. @{
  17. */
  18. /** @addtogroup N9H30_FMI_Driver FMI Driver
  19. @{
  20. */
  21. /** @addtogroup N9H30_FMI_EXPORTED_FUNCTIONS FMI Exported Functions
  22. @{
  23. */
  24. /// @cond HIDDEN_SYMBOLS
  25. #define FMI_BLOCK_SIZE 512
  26. // global variables
  27. // For response R3 (such as ACMD41, CRC-7 is invalid; but FMI controller will still
  28. // calculate CRC-7 and get an error result, software should ignore this error and clear INTSTS [CRC_IF] flag
  29. // _fmi_uR3_CMD is the flag for it. 1 means software should ignore CRC-7 error
  30. unsigned int _fmi_uR3_CMD = 0;
  31. unsigned int _fmi_uR7_CMD = 0;
  32. unsigned char volatile _fmi_eMMCDataReady = FALSE;
  33. unsigned char *_fmi_peMMCBuffer;
  34. unsigned int gFMIReferenceClock;
  35. #ifdef __ICCARM__
  36. #pragma data_alignment = 4096
  37. unsigned char _fmi_uceMMCBuffer[512];
  38. #else
  39. unsigned char _fmi_uceMMCBuffer[512] __attribute__((aligned(4096)));
  40. #endif
  41. int emmc_ok = 0;
  42. unsigned char peMMC_offset = 0;
  43. EMMC_INFO_T eMMC;
  44. void eMMC_CheckRB()
  45. {
  46. while (1)
  47. {
  48. outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) | FMI_EMMCCTL_CLK8OEN_Msk);
  49. while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_CLK8OEN_Msk);
  50. if (inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_DAT0STS_Msk)
  51. break;
  52. }
  53. }
  54. int eMMC_Command(EMMC_INFO_T *pSD, unsigned char ucCmd, unsigned int uArg)
  55. {
  56. volatile int buf;
  57. outpw(REG_FMI_EMMCCMD, uArg);
  58. buf = (inpw(REG_FMI_EMMCCTL) & (~FMI_EMMCCTL_CMDCODE_Msk)) | (ucCmd << 8) | (FMI_EMMCCTL_COEN_Msk);
  59. outpw(REG_FMI_EMMCCTL, buf);
  60. while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_COEN_Msk)
  61. {
  62. if (pSD->IsCardInsert == FALSE)
  63. return EMMC_NO_CARD;
  64. }
  65. return 0;
  66. }
  67. int eMMC_CmdAndRsp(EMMC_INFO_T *pSD, unsigned char ucCmd, unsigned int uArg, int ntickCount)
  68. {
  69. volatile int buf;
  70. outpw(REG_FMI_EMMCCMD, uArg);
  71. buf = (inpw(REG_FMI_EMMCCTL) & (~FMI_EMMCCTL_CMDCODE_Msk)) | (ucCmd << 8) | (FMI_EMMCCTL_COEN_Msk | FMI_EMMCCTL_RIEN_Msk);
  72. outpw(REG_FMI_EMMCCTL, buf);
  73. if (ntickCount > 0)
  74. {
  75. while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_RIEN_Msk)
  76. {
  77. if (ntickCount-- == 0)
  78. {
  79. outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) | FMI_EMMCCTL_CTLRST_Msk); // reset SD engine
  80. return 2;
  81. }
  82. if (pSD->IsCardInsert == FALSE)
  83. return EMMC_NO_CARD;
  84. }
  85. }
  86. else
  87. {
  88. while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_RIEN_Msk)
  89. {
  90. if (pSD->IsCardInsert == FALSE)
  91. return EMMC_NO_CARD;
  92. }
  93. }
  94. if (_fmi_uR7_CMD)
  95. {
  96. if (((inpw(REG_FMI_EMMCRESP1) & 0xff) != 0x55) && ((inpw(REG_FMI_EMMCRESP0) & 0xf) != 0x01))
  97. {
  98. _fmi_uR7_CMD = 0;
  99. return EMMC_CMD8_ERROR;
  100. }
  101. }
  102. if (!_fmi_uR3_CMD)
  103. {
  104. if (inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_CRC7_Msk) // check CRC7
  105. return 0;
  106. else
  107. return EMMC_CRC7_ERROR;
  108. }
  109. else // ignore CRC error for R3 case
  110. {
  111. _fmi_uR3_CMD = 0;
  112. outpw(REG_FMI_EMMCINTSTS, FMI_EMMCINTSTS_CRCIF_Msk);
  113. return 0;
  114. }
  115. }
  116. int eMMC_Swap32(int val)
  117. {
  118. int buf;
  119. buf = val;
  120. val <<= 24;
  121. val |= (buf << 8) & 0xff0000;
  122. val |= (buf >> 8) & 0xff00;
  123. val |= (buf >> 24) & 0xff;
  124. return val;
  125. }
  126. // Get 16 bytes CID or CSD
  127. int eMMC_CmdAndRsp2(EMMC_INFO_T *pSD, unsigned char ucCmd, unsigned int uArg, unsigned int *puR2ptr)
  128. {
  129. unsigned int i, buf;
  130. unsigned int tmpBuf[5];
  131. outpw(REG_FMI_EMMCCMD, uArg);
  132. buf = (inpw(REG_FMI_EMMCCTL) & (~FMI_EMMCCTL_CMDCODE_Msk)) | (ucCmd << 8) | (FMI_EMMCCTL_COEN_Msk | FMI_EMMCCTL_R2EN_Msk);
  133. outpw(REG_FMI_EMMCCTL, buf);
  134. while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_R2EN_Msk)
  135. {
  136. if (pSD->IsCardInsert == FALSE)
  137. return EMMC_NO_CARD;
  138. }
  139. if (inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_CRC7_Msk)
  140. {
  141. for (i = 0; i < 5; i++)
  142. tmpBuf[i] = eMMC_Swap32(*(int *)(FMI_BA + i * 4));
  143. for (i = 0; i < 4; i++)
  144. *puR2ptr++ = ((tmpBuf[i] & 0x00ffffff) << 8) | ((tmpBuf[i + 1] & 0xff000000) >> 24);
  145. return 0;
  146. }
  147. else
  148. return EMMC_CRC7_ERROR;
  149. }
  150. int eMMC_CmdAndRspDataIn(EMMC_INFO_T *pSD, unsigned char ucCmd, unsigned int uArg)
  151. {
  152. volatile int buf;
  153. outpw(REG_FMI_EMMCCMD, uArg);
  154. buf = (inpw(REG_FMI_EMMCCTL) & (~FMI_EMMCCTL_CMDCODE_Msk)) | (ucCmd << 8) | (FMI_EMMCCTL_COEN_Msk | FMI_EMMCCTL_RIEN_Msk | FMI_EMMCCTL_DIEN_Msk);
  155. outpw(REG_FMI_EMMCCTL, buf);
  156. while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_RIEN_Msk)
  157. {
  158. if (pSD->IsCardInsert == FALSE)
  159. return EMMC_NO_CARD;
  160. }
  161. while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_DIEN_Msk)
  162. {
  163. if (pSD->IsCardInsert == FALSE)
  164. return EMMC_NO_CARD;
  165. }
  166. if (!(inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_CRC7_Msk)) // check CRC7
  167. {
  168. return EMMC_CRC7_ERROR;
  169. }
  170. if (!(inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_CRC16_Msk)) // check CRC16
  171. {
  172. return EMMC_CRC16_ERROR;
  173. }
  174. return 0;
  175. }
  176. // there are 3 bits for divider N0, maximum is 8
  177. #define EMMC_CLK_DIV0_MAX 8
  178. // there are 8 bits for divider N1, maximum is 256
  179. #define EMMC_CLK_DIV1_MAX 256
  180. void eMMC_Set_clock(unsigned int clock_khz)
  181. {
  182. UINT32 rate, div0, div1, i;
  183. //--- calculate the rate that 2 divider have to divide
  184. // _fmi_uFMIReferenceClock is the input clock with unit KHz like as APLL/UPLL and
  185. if (clock_khz > gFMIReferenceClock)
  186. {
  187. //sysprintf("ERROR: wrong eMMC clock %dKHz since it is faster than input clock %dKHz !\n", clock_khz, gFMIReferenceClock);
  188. return;
  189. }
  190. rate = gFMIReferenceClock / clock_khz;
  191. // choose slower clock if system clock cannot divisible by wanted clock
  192. if (gFMIReferenceClock % clock_khz != 0)
  193. rate++;
  194. if (rate > (EMMC_CLK_DIV0_MAX * EMMC_CLK_DIV1_MAX)) // the maximum divider for EMMC_CLK is (EMMC_CLK_DIV0_MAX * EMMC_CLK_DIV1_MAX)
  195. {
  196. //sysprintf("ERROR: wrong SD clock %dKHz since it is slower than input clock %dKHz/%d !\n", clock_khz, gFMIReferenceClock, EMMC_CLK_DIV0_MAX * EMMC_CLK_DIV1_MAX);
  197. return;
  198. }
  199. //--- choose a suitable value for first divider
  200. for (div0 = EMMC_CLK_DIV0_MAX; div0 > 0; div0--) // choose the maximum value if can exact division
  201. {
  202. if (rate % div0 == 0)
  203. break;
  204. }
  205. if (div0 == 0) // cannot exact division
  206. {
  207. // if rate <= EMMC_CLK_DIV1_MAX, set div0 to 1 since div1 can exactly divide input clock
  208. div0 = (rate <= EMMC_CLK_DIV1_MAX) ? 1 : EMMC_CLK_DIV0_MAX;
  209. }
  210. //--- calculate the second divider
  211. div1 = rate / div0;
  212. div1 &= 0xFF;
  213. //sysprintf("Set_clock(): wanted clock=%d, rate=%d, div0=%d, div1=%d\n", clock_khz, rate, div0, div1);
  214. //--- setup register
  215. outpw(REG_CLK_DIVCTL3, (inpw(REG_CLK_DIVCTL3) & ~0x18) | (0x3 << 3));
  216. outpw(REG_CLK_DIVCTL3, (inpw(REG_CLK_DIVCTL3) & ~0x7) | (div0 - 1));
  217. outpw(REG_CLK_DIVCTL3, (inpw(REG_CLK_DIVCTL3) & ~0xff00) | ((div1 - 1) << 8));
  218. for (i = 0; i < 1000; i++); // waiting for clock become stable
  219. return;
  220. }
  221. // Initial
  222. int eMMC_Init(EMMC_INFO_T *pSD)
  223. {
  224. int volatile i, status;
  225. unsigned int resp;
  226. unsigned int CIDBuffer[4];
  227. unsigned int volatile u32CmdTimeOut;
  228. // set the clock to 300KHz
  229. eMMC_Set_clock(300);
  230. // power ON 74 clock
  231. outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) | FMI_EMMCCTL_CLK74OEN_Msk);
  232. while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_CLK74OEN_Msk);
  233. eMMC_Command(pSD, 0, 0); // reset all cards
  234. for (i = 0x1000; i > 0; i--);
  235. // initial SDHC
  236. _fmi_uR7_CMD = 1;
  237. u32CmdTimeOut = 5000;
  238. i = eMMC_CmdAndRsp(pSD, 8, 0x00000155, u32CmdTimeOut);
  239. if (i == 0)
  240. {
  241. // SD 2.0
  242. eMMC_CmdAndRsp(pSD, 55, 0x00, u32CmdTimeOut);
  243. _fmi_uR3_CMD = 1;
  244. eMMC_CmdAndRsp(pSD, 41, 0x40ff8000, u32CmdTimeOut); // 2.7v-3.6v
  245. resp = inpw(REG_FMI_EMMCRESP0);
  246. while (!(resp & 0x00800000)) // check if card is ready
  247. {
  248. eMMC_CmdAndRsp(pSD, 55, 0x00, u32CmdTimeOut);
  249. _fmi_uR3_CMD = 1;
  250. eMMC_CmdAndRsp(pSD, 41, 0x40ff8000, u32CmdTimeOut); // 3.0v-3.4v
  251. resp = inpw(REG_FMI_EMMCRESP0);
  252. }
  253. if (resp & 0x00400000)
  254. pSD->CardType = EMMC_TYPE_SD_HIGH;
  255. else
  256. pSD->CardType = EMMC_TYPE_SD_LOW;
  257. }
  258. else
  259. {
  260. // SD 1.1
  261. eMMC_Command(pSD, 0, 0); // reset all cards
  262. for (i = 0x100; i > 0; i--);
  263. i = eMMC_CmdAndRsp(pSD, 55, 0x00, u32CmdTimeOut);
  264. if (i == 2) // MMC memory
  265. {
  266. eMMC_Command(pSD, 0, 0); // reset
  267. for (i = 0x100; i > 0; i--);
  268. _fmi_uR3_CMD = 1;
  269. if (eMMC_CmdAndRsp(pSD, 1, 0x40ff8000, u32CmdTimeOut) != 2) // eMMC memory
  270. {
  271. resp = inpw(REG_FMI_EMMCRESP0);
  272. while (!(resp & 0x00800000)) // check if card is ready
  273. {
  274. _fmi_uR3_CMD = 1;
  275. eMMC_CmdAndRsp(pSD, 1, 0x40ff8000, u32CmdTimeOut); // high voltage
  276. resp = inpw(REG_FMI_EMMCRESP0);
  277. }
  278. if (resp & 0x00400000)
  279. pSD->CardType = EMMC_TYPE_EMMC;
  280. else
  281. pSD->CardType = EMMC_TYPE_MMC;
  282. }
  283. else
  284. {
  285. pSD->CardType = EMMC_TYPE_UNKNOWN;
  286. return EMMC_ERR_DEVICE;
  287. }
  288. }
  289. else if (i == 0) // SD Memory
  290. {
  291. _fmi_uR3_CMD = 1;
  292. eMMC_CmdAndRsp(pSD, 41, 0x00ff8000, u32CmdTimeOut); // 3.0v-3.4v
  293. resp = inpw(REG_FMI_EMMCRESP0);
  294. while (!(resp & 0x00800000)) // check if card is ready
  295. {
  296. eMMC_CmdAndRsp(pSD, 55, 0x00, u32CmdTimeOut);
  297. _fmi_uR3_CMD = 1;
  298. eMMC_CmdAndRsp(pSD, 41, 0x00ff8000, u32CmdTimeOut); // 3.0v-3.4v
  299. resp = inpw(REG_FMI_EMMCRESP0);
  300. }
  301. pSD->CardType = EMMC_TYPE_SD_LOW;
  302. }
  303. else
  304. {
  305. pSD->CardType = EMMC_TYPE_UNKNOWN;
  306. return EMMC_INIT_ERROR;
  307. }
  308. }
  309. // CMD2, CMD3
  310. if (pSD->CardType != EMMC_TYPE_UNKNOWN)
  311. {
  312. eMMC_CmdAndRsp2(pSD, 2, 0x00, CIDBuffer);
  313. if ((pSD->CardType == EMMC_TYPE_MMC) || (pSD->CardType == EMMC_TYPE_EMMC))
  314. {
  315. if ((status = eMMC_CmdAndRsp(pSD, 3, 0x10000, 0)) != 0) // set RCA
  316. return status;
  317. pSD->RCA = 0x10000;
  318. }
  319. else
  320. {
  321. if ((status = eMMC_CmdAndRsp(pSD, 3, 0x00, 0)) != 0) // get RCA
  322. return status;
  323. else
  324. pSD->RCA = (inpw(REG_FMI_EMMCRESP0) << 8) & 0xffff0000;
  325. }
  326. }
  327. #if 0
  328. if (pSD->CardType == EMMC_TYPE_SD_HIGH)
  329. sysprintf("This is high capacity SD memory card\n");
  330. if (pSD->CardType == EMMC_TYPE_SD_LOW)
  331. sysprintf("This is standard capacity SD memory card\n");
  332. if (pSD->CardType == EMMC_TYPE_EMMC)
  333. sysprintf("This is eMMC memory card\n");
  334. #endif
  335. return 0;
  336. }
  337. int eMMC_SwitchToHighSpeed(EMMC_INFO_T *pSD)
  338. {
  339. int volatile status = 0;
  340. unsigned short current_comsumption, busy_status0;
  341. outpw(REG_FMI_DMASA, (unsigned int)_fmi_peMMCBuffer); // set DMA transfer starting address
  342. outpw(REG_FMI_EMMCBLEN, 63); // 512 bit
  343. if ((status = eMMC_CmdAndRspDataIn(pSD, 6, 0x00ffff01)) != 0)
  344. return 1;
  345. current_comsumption = _fmi_peMMCBuffer[0] << 8 | _fmi_peMMCBuffer[1];
  346. if (!current_comsumption)
  347. return 1;
  348. busy_status0 = _fmi_peMMCBuffer[28] << 8 | _fmi_peMMCBuffer[29];
  349. if (!busy_status0) // function ready
  350. {
  351. outpw(REG_FMI_DMASA, (unsigned int)_fmi_peMMCBuffer); // set DMA transfer starting address
  352. outpw(REG_FMI_EMMCBLEN, 63); // 512 bit
  353. if ((status = eMMC_CmdAndRspDataIn(pSD, 6, 0x80ffff01)) != 0)
  354. return 1;
  355. // function change timing: 8 clocks
  356. outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) | FMI_EMMCCTL_CLK8OEN_Msk);
  357. while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_CLK8OEN_Msk);
  358. current_comsumption = _fmi_peMMCBuffer[0] << 8 | _fmi_peMMCBuffer[1];
  359. if (!current_comsumption)
  360. return 1;
  361. return 0;
  362. }
  363. else
  364. return 1;
  365. }
  366. int eMMC_SelectCardType(EMMC_INFO_T *pSD)
  367. {
  368. int volatile status = 0;
  369. //unsigned int arg;
  370. if ((status = eMMC_CmdAndRsp(pSD, 7, pSD->RCA, 0)) != 0)
  371. return status;
  372. eMMC_CheckRB();
  373. // if SD card set 4bit
  374. if (pSD->CardType == EMMC_TYPE_SD_HIGH)
  375. {
  376. _fmi_peMMCBuffer = (unsigned char *)((unsigned int)_fmi_uceMMCBuffer);
  377. outpw(REG_FMI_DMASA, (unsigned int)_fmi_peMMCBuffer); // set DMA transfer starting address
  378. outpw(REG_FMI_EMMCBLEN, 0x07); // 64 bit
  379. if ((status = eMMC_CmdAndRsp(pSD, 55, pSD->RCA, 0)) != 0)
  380. return status;
  381. if ((status = eMMC_CmdAndRspDataIn(pSD, 51, 0x00)) != 0)
  382. return status;
  383. if ((_fmi_uceMMCBuffer[0] & 0xf) == 0x2)
  384. {
  385. status = eMMC_SwitchToHighSpeed(pSD);
  386. if (status == 0)
  387. {
  388. /* divider */
  389. eMMC_Set_clock(SDHC_FREQ);
  390. }
  391. }
  392. if ((status = eMMC_CmdAndRsp(pSD, 55, pSD->RCA, 0)) != 0)
  393. return status;
  394. if ((status = eMMC_CmdAndRsp(pSD, 6, 0x02, 0)) != 0) // set bus width
  395. return status;
  396. outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) | FMI_EMMCCTL_DBW_Msk);
  397. }
  398. else if (pSD->CardType == EMMC_TYPE_SD_LOW)
  399. {
  400. _fmi_peMMCBuffer = (unsigned char *)((unsigned int)_fmi_uceMMCBuffer);
  401. outpw(REG_FMI_DMASA, (unsigned int) _fmi_peMMCBuffer); // set DMA transfer starting address
  402. outpw(REG_FMI_EMMCBLEN, 0x07); // 64 bit
  403. if ((status = eMMC_CmdAndRsp(pSD, 55, pSD->RCA, 0)) != 0)
  404. return status;
  405. if ((status = eMMC_CmdAndRspDataIn(pSD, 51, 0x00)) != 0)
  406. return status;
  407. // set data bus width. ACMD6 for SD card, SDCR_DBW for host.
  408. if ((status = eMMC_CmdAndRsp(pSD, 55, pSD->RCA, 0)) != 0)
  409. return status;
  410. if ((status = eMMC_CmdAndRsp(pSD, 6, 0x02, 0)) != 0) // set bus width
  411. return status;
  412. outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) | FMI_EMMCCTL_DBW_Msk);
  413. }
  414. else if (pSD->CardType == EMMC_TYPE_MMC)
  415. {
  416. outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) & ~FMI_EMMCCTL_DBW_Msk);
  417. }
  418. else if (pSD->CardType == EMMC_TYPE_EMMC)
  419. {
  420. //--- sent CMD6 to MMC card to set bus width to 4 bits mode, skymedi only support 1-bit
  421. // set CMD6 argument Access field to 3, Index to 183, Value to 1 (4-bit mode)
  422. // arg = (3 << 24) | (183 << 16) | (1 << 8);
  423. // if ((status = eMMC_CmdAndRsp(pSD, 6, arg, 0)) != 0)
  424. // return status;
  425. // eMMC_CheckRB();
  426. // outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL)| FMI_EMMCCTL_DBW_Msk);
  427. outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) & ~FMI_EMMCCTL_DBW_Msk);
  428. }
  429. if ((status = eMMC_CmdAndRsp(pSD, 16, FMI_BLOCK_SIZE, 0)) != 0) // set block length
  430. return status;
  431. outpw(REG_FMI_EMMCBLEN, FMI_BLOCK_SIZE - 1); // set the block size
  432. eMMC_Command(pSD, 7, 0);
  433. outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) | FMI_EMMCCTL_CLK8OEN_Msk);
  434. while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_CLK8OEN_Msk);
  435. outpw(REG_FMI_EMMCINTEN, inpw(REG_FMI_EMMCINTEN) | FMI_EMMCINTEN_BLKDIEN_Msk);
  436. return 0;
  437. }
  438. void eMMC_Get_info(EMMC_INFO_T *pSD)
  439. {
  440. unsigned int R_LEN, C_Size, MULT, size;
  441. unsigned int Buffer[4];
  442. unsigned char *ptr;
  443. eMMC_CmdAndRsp2(pSD, 9, pSD->RCA, Buffer);
  444. if ((pSD->CardType == EMMC_TYPE_MMC) || (pSD->CardType == EMMC_TYPE_EMMC))
  445. {
  446. // for MMC/eMMC card
  447. if ((Buffer[0] & 0xc0000000) == 0xc0000000)
  448. {
  449. // CSD_STRUCTURE [127:126] is 3
  450. // CSD version depend on EXT_CSD register in eMMC v4.4 for card size > 2GB
  451. eMMC_CmdAndRsp(pSD, 7, pSD->RCA, 0);
  452. ptr = (unsigned char *)((unsigned int)_fmi_uceMMCBuffer);
  453. outpw(REG_FMI_DMASA, (unsigned int)ptr); // set DMA transfer starting address
  454. outpw(REG_FMI_EMMCBLEN, 511); // read 512 bytes for EXT_CSD
  455. if (eMMC_CmdAndRspDataIn(pSD, 8, 0x00) != 0)
  456. return;
  457. eMMC_Command(pSD, 7, 0);
  458. outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) | FMI_EMMCCTL_CLK8OEN_Msk);
  459. while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_CLK8OEN_Msk);
  460. pSD->totalSectorN = (*(unsigned int *)(ptr + 212));
  461. pSD->diskSize = pSD->totalSectorN / 2;
  462. }
  463. else
  464. {
  465. // CSD version v1.0/1.1/1.2 in eMMC v4.4 spec for card size <= 2GB
  466. R_LEN = (Buffer[1] & 0x000f0000) >> 16;
  467. C_Size = ((Buffer[1] & 0x000003ff) << 2) | ((Buffer[2] & 0xc0000000) >> 30);
  468. MULT = (Buffer[2] & 0x00038000) >> 15;
  469. size = (C_Size + 1) * (1 << (MULT + 2)) * (1 << R_LEN);
  470. pSD->diskSize = size / 1024;
  471. pSD->totalSectorN = size / 512;
  472. }
  473. }
  474. else
  475. {
  476. if (Buffer[0] & 0xc0000000)
  477. {
  478. C_Size = ((Buffer[1] & 0x0000003f) << 16) | ((Buffer[2] & 0xffff0000) >> 16);
  479. size = (C_Size + 1) * 512; // Kbytes
  480. pSD->diskSize = size;
  481. pSD->totalSectorN = size << 1;
  482. }
  483. else
  484. {
  485. R_LEN = (Buffer[1] & 0x000f0000) >> 16;
  486. C_Size = ((Buffer[1] & 0x000003ff) << 2) | ((Buffer[2] & 0xc0000000) >> 30);
  487. MULT = (Buffer[2] & 0x00038000) >> 15;
  488. size = (C_Size + 1) * (1 << (MULT + 2)) * (1 << R_LEN);
  489. pSD->diskSize = size / 1024;
  490. pSD->totalSectorN = size / 512;
  491. }
  492. }
  493. pSD->sectorSize = 512;
  494. //sysprintf("The size is %d KB\n", pSD->diskSize);
  495. }
  496. /// @endcond HIDDEN_SYMBOLS
  497. /**
  498. * @brief This function use to tell FMI eMMC engine clock.
  499. *
  500. * @param[in] u32Clock Set current eMMC engine clock
  501. *
  502. * @return None
  503. */
  504. void FMI_SetReferenceClock(unsigned int u32Clock)
  505. {
  506. gFMIReferenceClock = u32Clock; // kHz
  507. }
  508. /**
  509. * @brief This function use to reset FMI eMMC function.
  510. *
  511. * @return None
  512. */
  513. void eMMC_Open(void)
  514. {
  515. // enable DMAC
  516. outpw(REG_FMI_DMACTL, FMI_DMACTL_DMARST_Msk);
  517. while (inpw(REG_FMI_DMACTL) & FMI_DMACTL_DMARST_Msk);
  518. outpw(REG_FMI_DMACTL, FMI_DMACTL_DMAEN_Msk);
  519. //Reset Global
  520. outpw(REG_FMI_CTL, FMI_CTL_CTLRST_Msk);
  521. while (inpw(REG_FMI_CTL) & FMI_CTL_CTLRST_Msk);
  522. // enable eMMC
  523. outpw(REG_FMI_CTL, FMI_CTL_EMMCEN_Msk);
  524. outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) | FMI_EMMCCTL_CTLRST_Msk);
  525. while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_CTLRST_Msk);
  526. memset(&eMMC, 0, sizeof(EMMC_INFO_T));
  527. eMMC.IsCardInsert = 1;
  528. }
  529. /**
  530. * @brief This function use to initial eMMC card.
  531. *
  532. * @return None
  533. */
  534. void eMMC_Probe(void)
  535. {
  536. // Disable FMI interrupt
  537. outpw(REG_FMI_INTEN, 0);
  538. outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) & ~(FMI_EMMCCTL_SDNWR_Msk | FMI_EMMCCTL_BLKCNT_Msk | FMI_EMMCCTL_DBW_Msk));
  539. outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) | (0x09 << FMI_EMMCCTL_SDNWR_Pos) | (0x01 << FMI_EMMCCTL_BLKCNT_Pos));
  540. if (eMMC_Init(&eMMC) < 0)
  541. return;
  542. /* divider */
  543. if ((eMMC.CardType == EMMC_TYPE_MMC) || (eMMC.CardType == EMMC_TYPE_EMMC))
  544. eMMC_Set_clock(MMC_FREQ);
  545. else
  546. eMMC_Set_clock(SD_FREQ);
  547. eMMC_Get_info(&eMMC);
  548. if (eMMC_SelectCardType(&eMMC))
  549. return;
  550. emmc_ok = 1;
  551. }
  552. /**
  553. * @brief This function use to read data from eMMC card.
  554. *
  555. * @param[out] pu8BufAddr The buffer to receive the data from eMMC card.
  556. * @param[in] u32StartSec The start read sector address.
  557. * @param[in] u32SecCount The the read sector number of data
  558. *
  559. * @return None
  560. */
  561. unsigned int eMMC_Read(unsigned char *pu8BufAddr, unsigned int u32StartSec, unsigned int u32SecCount)
  562. {
  563. char volatile bIsSendCmd = FALSE;
  564. unsigned int volatile reg;
  565. int volatile i, loop, status;
  566. unsigned int blksize = FMI_BLOCK_SIZE;
  567. EMMC_INFO_T *pSD;
  568. pSD = &eMMC;
  569. //--- check input parameters
  570. if (u32SecCount == 0)
  571. return EMMC_SELECT_ERROR;
  572. if ((status = eMMC_CmdAndRsp(pSD, 7, pSD->RCA, 0)) != 0)
  573. return status;
  574. eMMC_CheckRB();
  575. outpw(REG_FMI_EMMCBLEN, blksize - 1); // the actual byte count is equal to (BLEN+1)
  576. if ((pSD->CardType == EMMC_TYPE_SD_HIGH) || (pSD->CardType == EMMC_TYPE_EMMC))
  577. outpw(REG_FMI_EMMCCMD, u32StartSec);
  578. else
  579. outpw(REG_FMI_EMMCCMD, u32StartSec * blksize);
  580. outpw(REG_FMI_DMASA, (unsigned int)pu8BufAddr);
  581. loop = u32SecCount / 255;
  582. for (i = 0; i < loop; i++)
  583. {
  584. _fmi_eMMCDataReady = FALSE;
  585. reg = inpw(REG_FMI_EMMCCTL) & ~FMI_EMMCCTL_CMDCODE_Msk;
  586. reg = reg | 0xff0000;
  587. if (bIsSendCmd == FALSE)
  588. {
  589. outpw(REG_FMI_EMMCCTL, reg | (18 << 8) | (FMI_EMMCCTL_COEN_Msk | FMI_EMMCCTL_RIEN_Msk | FMI_EMMCCTL_DIEN_Msk));
  590. bIsSendCmd = TRUE;
  591. }
  592. else
  593. outpw(REG_FMI_EMMCCTL, reg | FMI_EMMCCTL_DIEN_Msk);
  594. while (!_fmi_eMMCDataReady)
  595. {
  596. // if ((inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_BLKDIF_Msk) && (!(inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_DIEN_Msk))) {
  597. // outpw(REG_FMI_EMMCINTSTS, FMI_EMMCINTSTS_BLKDIF_Msk);
  598. // break;
  599. // }
  600. if (pSD->IsCardInsert == FALSE)
  601. return EMMC_NO_CARD;
  602. }
  603. if (!(inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_CRC7_Msk)) // check CRC7
  604. {
  605. return EMMC_CRC7_ERROR;
  606. }
  607. if (!(inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_CRC16_Msk)) // check CRC16
  608. {
  609. return EMMC_CRC16_ERROR;
  610. }
  611. }
  612. loop = u32SecCount % 255;
  613. if (loop != 0)
  614. {
  615. _fmi_eMMCDataReady = FALSE;
  616. reg = inpw(REG_FMI_EMMCCTL) & (~FMI_EMMCCTL_CMDCODE_Msk);
  617. reg = reg & (~FMI_EMMCCTL_BLKCNT_Msk);
  618. reg |= (loop << 16);
  619. if (bIsSendCmd == FALSE)
  620. {
  621. outpw(REG_FMI_EMMCCTL, reg | (18 << 8) | (FMI_EMMCCTL_COEN_Msk | FMI_EMMCCTL_RIEN_Msk | FMI_EMMCCTL_DIEN_Msk));
  622. bIsSendCmd = TRUE;
  623. }
  624. else
  625. outpw(REG_FMI_EMMCCTL, reg | FMI_EMMCCTL_DIEN_Msk);
  626. while (!_fmi_eMMCDataReady)
  627. {
  628. // if ((inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_BLKDIF_Msk) && (!(inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_DIEN_Msk))) {
  629. // outpw(REG_FMI_EMMCINTSTS, FMI_EMMCINTSTS_BLKDIF_Msk);
  630. // break;
  631. // }
  632. if (pSD->IsCardInsert == FALSE)
  633. return EMMC_NO_CARD;
  634. }
  635. if (!(inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_CRC7_Msk)) // check CRC7
  636. {
  637. return EMMC_CRC7_ERROR;
  638. }
  639. if (!(inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_CRC16_Msk)) // check CRC16
  640. {
  641. return EMMC_CRC16_ERROR;
  642. }
  643. }
  644. if (eMMC_CmdAndRsp(pSD, 12, 0, 0)) // stop command
  645. {
  646. //sysprintf("stop command fail !!\n");
  647. return EMMC_CRC7_ERROR;
  648. }
  649. eMMC_CheckRB();
  650. eMMC_Command(pSD, 7, 0);
  651. outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) | FMI_EMMCCTL_CLK8OEN_Msk);
  652. while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_CLK8OEN_Msk);
  653. return 0;
  654. }
  655. /**
  656. * @brief This function use to write data to eMMC card.
  657. *
  658. * @param[in] pu8BufAddr The buffer to send the data to SD card.
  659. * @param[in] u32StartSec The start write sector address.
  660. * @param[in] u32SecCount The the write sector number of data.
  661. *
  662. * @return - \ref EMMC_SELECT_ERROR u32SecCount is zero.
  663. * - \ref EMMC_NO_CARD SD card be removed.
  664. * - \ref EMMC_CRC_ERROR CRC error happen.
  665. * - \ref EMMC_CRC7_ERROR CRC7 error happen.
  666. * - \ref Successful Write data to eMMC card success.
  667. */
  668. unsigned int eMMC_Write(unsigned char *pu8BufAddr, unsigned int u32StartSec, unsigned int u32SecCount)
  669. {
  670. char volatile bIsSendCmd = FALSE;
  671. unsigned int volatile reg;
  672. int volatile i, loop, status;
  673. EMMC_INFO_T *pSD;
  674. pSD = &eMMC;
  675. //--- check input parameters
  676. if (u32SecCount == 0)
  677. return EMMC_SELECT_ERROR;
  678. if ((status = eMMC_CmdAndRsp(pSD, 7, pSD->RCA, 0)) != 0)
  679. return status;
  680. eMMC_CheckRB();
  681. // According to SD Spec v2.0/ eMMC v4.4, the write CMD block size MUST be 512, and the start address MUST be 512*n.
  682. outpw(REG_FMI_EMMCBLEN, FMI_BLOCK_SIZE - 1); // set the block size
  683. if ((pSD->CardType == EMMC_TYPE_SD_HIGH) || (pSD->CardType == EMMC_TYPE_EMMC))
  684. outpw(REG_FMI_EMMCCMD, u32StartSec);
  685. else
  686. outpw(REG_FMI_EMMCCMD, u32StartSec * FMI_BLOCK_SIZE); // set start address for CMD
  687. outpw(REG_FMI_DMASA, (unsigned int)pu8BufAddr);
  688. loop = u32SecCount / 255; // the maximum block count is 0xFF=255
  689. for (i = 0; i < loop; i++)
  690. {
  691. _fmi_eMMCDataReady = FALSE;
  692. reg = inpw(REG_FMI_EMMCCTL) & 0xff00c080;
  693. reg = reg | 0xff0000;
  694. if (!bIsSendCmd)
  695. {
  696. outpw(REG_FMI_EMMCCTL, reg | (25 << 8) | (FMI_EMMCCTL_COEN_Msk | FMI_EMMCCTL_RIEN_Msk | FMI_EMMCCTL_DOEN_Msk));
  697. bIsSendCmd = TRUE;
  698. }
  699. else
  700. outpw(REG_FMI_EMMCCTL, reg | FMI_EMMCCTL_DOEN_Msk);
  701. while (!_fmi_eMMCDataReady)
  702. {
  703. // if ((inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_BLKDIF_Msk) && (!(inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_DOEN_Msk))) {
  704. // outpw(REG_FMI_EMMCINTSTS, FMI_EMMCINTSTS_BLKDIF_Msk);
  705. // break;
  706. // }
  707. if (pSD->IsCardInsert == FALSE)
  708. return EMMC_NO_CARD;
  709. }
  710. if ((inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_CRCIF_Msk) != 0) // check CRC
  711. {
  712. outpw(REG_FMI_EMMCINTSTS, FMI_EMMCINTSTS_CRCIF_Msk);
  713. return EMMC_CRC_ERROR;
  714. }
  715. }
  716. loop = u32SecCount % 255;
  717. if (loop != 0)
  718. {
  719. _fmi_eMMCDataReady = FALSE;
  720. reg = (inpw(REG_FMI_EMMCCTL) & 0xff00c080) | (loop << 16);
  721. if (!bIsSendCmd)
  722. {
  723. outpw(REG_FMI_EMMCCTL, reg | (25 << 8) | (FMI_EMMCCTL_COEN_Msk | FMI_EMMCCTL_RIEN_Msk | FMI_EMMCCTL_DOEN_Msk));
  724. bIsSendCmd = TRUE;
  725. }
  726. else
  727. outpw(REG_FMI_EMMCCTL, reg | FMI_EMMCCTL_DOEN_Msk);
  728. while (!_fmi_eMMCDataReady)
  729. {
  730. // if ((inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_BLKDIF_Msk) && (!(inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_DOEN_Msk))) {
  731. // outpw(REG_FMI_EMMCINTSTS, FMI_EMMCINTSTS_BLKDIF_Msk);
  732. // break;
  733. // }
  734. if (pSD->IsCardInsert == FALSE)
  735. return EMMC_NO_CARD;
  736. }
  737. if ((inpw(REG_FMI_EMMCINTSTS) & FMI_EMMCINTSTS_CRCIF_Msk) != 0) // check CRC
  738. {
  739. outpw(REG_FMI_EMMCINTSTS, FMI_EMMCINTSTS_CRCIF_Msk);
  740. return EMMC_CRC_ERROR;
  741. }
  742. }
  743. outpw(REG_FMI_EMMCINTSTS, FMI_EMMCINTSTS_CRCIF_Msk);
  744. if (eMMC_CmdAndRsp(pSD, 12, 0, 0)) // stop command
  745. {
  746. return EMMC_CRC7_ERROR;
  747. }
  748. eMMC_CheckRB();
  749. eMMC_Command(pSD, 7, 0);
  750. outpw(REG_FMI_EMMCCTL, inpw(REG_FMI_EMMCCTL) | FMI_EMMCCTL_CLK8OEN_Msk);
  751. while (inpw(REG_FMI_EMMCCTL) & FMI_EMMCCTL_CLK8OEN_Msk);
  752. return 0;
  753. }
  754. /*@}*/ /* end of group N9H30_FMI_EXPORTED_FUNCTIONS */
  755. /*@}*/ /* end of group N9H30_FMI_Driver */
  756. /*@}*/ /* end of group N9H30_Device_Driver */
  757. /*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/