drv_sdhci.c 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096
  1. /*
  2. * Copyright (c) 2006-2024, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2024/04/05 flyingcys first version
  9. */
  10. #include <rthw.h>
  11. #include <rtthread.h>
  12. #include <rtdevice.h>
  13. #include <mmu.h>
  14. #include <stdbool.h>
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include "board.h"
  18. #include "cache.h"
  19. #define DBG_TAG "drv.sdio"
  20. #define DBG_LEVEL DBG_INFO
  21. #include <rtdbg.h>
  22. #include <drivers/dev_mmcsd_core.h>
  23. #include <drivers/dev_sdio.h>
  24. #include "drv_sdhci.h"
  25. #define SDMMC_DMA_ALIGN_CACHE 64
  26. struct rthw_sdhci
  27. {
  28. struct rt_mmcsd_host *host;
  29. rt_ubase_t base;
  30. rt_uint32_t irq;
  31. volatile rt_err_t cmd_error;
  32. volatile rt_err_t data_error;
  33. rt_uint32_t response_type;
  34. volatile rt_uint32_t response[4];
  35. char name[RT_NAME_MAX];
  36. rt_sem_t sem_cmd;
  37. rt_sem_t sem_data;
  38. };
  39. static uint32_t sdhci_set_card_clock(rt_ubase_t base, uint32_t srcClock_Hz, uint32_t target_HZ)
  40. {
  41. uintptr_t BASE = (uintptr_t)base;
  42. uint32_t divider = 1U;
  43. uint32_t i;
  44. RT_ASSERT(target_HZ > 0);
  45. if (srcClock_Hz <= target_HZ )
  46. {
  47. divider = 0;
  48. }
  49. else
  50. {
  51. for (divider = 0x1; divider < 0x3FF; divider++)
  52. {
  53. if(srcClock_Hz / (2*divider) <= target_HZ)
  54. break;
  55. }
  56. if(divider == 0x3FF)
  57. {
  58. LOG_D("Warning: Can't set the freq to %d, divider is filled!!!", target_HZ);
  59. }
  60. }
  61. RT_ASSERT(divider <= 0x3FF);
  62. if (mmio_read_16(BASE + SDIF_HOST_CONTROL2) & 1<<15)
  63. {
  64. LOG_D("Use SDCLK Preset Value.");
  65. }
  66. else
  67. {
  68. mmio_write_16(BASE + SDIF_CLK_CTRL,
  69. mmio_read_16(BASE + SDIF_CLK_CTRL) & ~0x9); // disable INTERNAL_CLK_EN and PLL_ENABLE
  70. mmio_write_16(BASE + SDIF_CLK_CTRL,
  71. (mmio_read_16(BASE + SDIF_CLK_CTRL) & 0x3F) | ((divider & 0xff) << 8) | ((divider & 0x300) >> 2)); // set clk div
  72. mmio_write_16(BASE + SDIF_CLK_CTRL,
  73. mmio_read_16(BASE + SDIF_CLK_CTRL) | 0x1); // set INTERNAL_CLK_EN
  74. for (i = 0; i <= 150000; i += 100)
  75. {
  76. if (mmio_read_16(BASE + SDIF_CLK_CTRL) & 0x2)
  77. {
  78. break;
  79. }
  80. rt_hw_us_delay(100);
  81. }
  82. if (i > 150000)
  83. {
  84. LOG_D("SD INTERNAL_CLK_EN seting FAILED!");
  85. RT_ASSERT(0);
  86. }
  87. mmio_write_16(BASE + SDIF_CLK_CTRL,
  88. mmio_read_16(BASE + SDIF_CLK_CTRL) | 0x8); // set PLL_ENABLE
  89. for (i = 0; i <= 150000; i += 100)
  90. {
  91. if (mmio_read_16(BASE + SDIF_CLK_CTRL) & 0x2)
  92. {
  93. return target_HZ;
  94. }
  95. rt_hw_us_delay(100);
  96. }
  97. }
  98. LOG_E("SD PLL seting FAILED!\n");
  99. return -1;
  100. }
  101. static uint32_t SDIF_ChangeCardClock(rt_ubase_t base, uint32_t srcClock_Hz, uint32_t target_HZ)
  102. {
  103. uintptr_t BASE = (uintptr_t)base;
  104. uint32_t divider = 1U;
  105. uint32_t i;
  106. if (target_HZ <= 0)
  107. {
  108. mmio_write_16(BASE + SDIF_CLK_CTRL, mmio_read_32(BASE + SDIF_CLK_CTRL) & ~(0x1<<2)); // stop SD clock
  109. // mmio_write_16(BASE + 0x31e, 0x00);
  110. return -1;
  111. }
  112. if (srcClock_Hz <= target_HZ )
  113. {
  114. divider = 0;
  115. }
  116. else
  117. {
  118. for (divider = 0x1; divider < 0x3FF; divider++)
  119. {
  120. if(srcClock_Hz / (2*divider) <= target_HZ)
  121. break;
  122. }
  123. if(divider == 0x3FF)
  124. {
  125. LOG_D("Warning: Can't set the freq to %d, divider is filled!!!", target_HZ);
  126. }
  127. }
  128. RT_ASSERT(divider <= 0x3FF);
  129. mmio_write_16(BASE + SDIF_CLK_CTRL, mmio_read_16(BASE + SDIF_CLK_CTRL) & ~(0x1<<2)); // stop SD clock
  130. // mmio_write_16(BASE + 0x31e, 0x10);
  131. mmio_write_16(BASE + SDIF_CLK_CTRL, mmio_read_16(BASE + SDIF_CLK_CTRL) & ~0x8); // disable PLL_ENABLE
  132. if (mmio_read_16(BASE + SDIF_HOST_CONTROL2) & 1<<15)
  133. {
  134. LOG_D("Use SDCLK Preset Value.");
  135. // 4 need recheck?
  136. mmio_write_16(BASE + SDIF_HOST_CONTROL2, mmio_read_16(BASE + SDIF_HOST_CONTROL2) & ~0x7); // clr UHS_MODE_SEL
  137. }
  138. else
  139. {
  140. mmio_write_16(BASE + SDIF_CLK_CTRL, (mmio_read_16(BASE + SDIF_CLK_CTRL) & 0x3F) | ((divider & 0xff) << 8) | ((divider & 0x300) >> 2)); // set clk div
  141. mmio_write_16(BASE + SDIF_CLK_CTRL, mmio_read_16(BASE + SDIF_CLK_CTRL) & ~(0x1 << 5)); // CLK_GEN_SELECT
  142. }
  143. mmio_write_16(BASE + SDIF_CLK_CTRL, mmio_read_16(BASE + SDIF_CLK_CTRL) | 0xc); // enable PLL_ENABLE
  144. //LOG_D("mmio_read_16(BASE + SDIF_CLK_CTRL) = 0x%x", mmio_read_16(BASE + SDIF_CLK_CTRL));
  145. for (i = 0; i <= 150000; i += 100)
  146. {
  147. if (mmio_read_16(BASE + SDIF_CLK_CTRL) & 0x2)
  148. {
  149. return target_HZ;
  150. }
  151. rt_hw_us_delay(100);
  152. }
  153. LOG_E("SD PLL seting FAILED!\n");
  154. return -1;
  155. }
  156. static void sdhci_wait_cmd_complete(struct rthw_sdhci *sdhci)
  157. {
  158. rt_err_t ret = RT_EOK;
  159. rt_uint32_t intmask;
  160. uintptr_t BASE = (uintptr_t)sdhci->base;
  161. ret = rt_sem_take(sdhci->sem_cmd, rt_tick_from_millisecond(3000));
  162. if (ret != RT_EOK)
  163. {
  164. LOG_E("wait cmd complete timeout ...");
  165. sdhci->cmd_error = -RT_ETIMEOUT;
  166. return;
  167. }
  168. }
  169. static void sdhci_wait_data_complete(struct rthw_sdhci *sdhci)
  170. {
  171. rt_err_t ret = RT_EOK;
  172. rt_uint32_t intmask;
  173. uintptr_t BASE = (uintptr_t)sdhci->base;
  174. ret = rt_sem_take(sdhci->sem_data, rt_tick_from_millisecond(3000));
  175. if (ret != RT_EOK)
  176. {
  177. LOG_E("wait data complete timeout ...");
  178. sdhci->data_error = -RT_ETIMEOUT;
  179. return;
  180. }
  181. }
  182. static uint32_t sdhci_prepare_data(struct rthw_sdhci *sdhci, struct rt_mmcsd_cmd *cmd, struct rt_mmcsd_data *data, rt_ubase_t start_addr, rt_uint32_t load_len)
  183. {
  184. uintptr_t BASE = (uintptr_t)sdhci->base;
  185. uint32_t block_cnt, blksz;
  186. uint8_t tmp;
  187. rt_ubase_t dma_addr;
  188. blksz = data->blksize;
  189. block_cnt = data->blks;
  190. rt_hw_cpu_dcache_clean((void *)start_addr, load_len);
  191. #ifdef RT_USING_SMART
  192. dma_addr = (rt_ubase_t)rt_kmem_v2p((void *)start_addr);
  193. #else
  194. dma_addr = start_addr;
  195. #endif
  196. mmio_write_32(BASE + SDIF_ADMA_SA_LOW, dma_addr);
  197. mmio_write_32(BASE + SDIF_ADMA_SA_HIGH, (dma_addr >> 32));
  198. mmio_write_32(BASE + SDIF_DMA_ADDRESS, block_cnt);
  199. mmio_write_16(BASE + SDIF_BLOCK_COUNT, 0);
  200. mmio_write_16(BASE + SDIF_BLOCK_SIZE, SDIF_MAKE_BLKSZ(7, blksz));
  201. // select SDMA
  202. tmp = mmio_read_8(BASE + SDIF_HOST_CONTROL);
  203. tmp &= ~SDIF_CTRL_DMA_MASK;
  204. tmp |= SDIF_CTRL_SDMA;
  205. mmio_write_8(BASE + SDIF_HOST_CONTROL, tmp);
  206. return 0;
  207. }
  208. static inline void *align_alloc(uint64_t align, uint32_t size, void **mem_unalign)
  209. {
  210. void *mem;
  211. uint64_t offset;
  212. size+=2*align;
  213. *mem_unalign = (void *)rt_malloc(size);
  214. if (!*mem_unalign)
  215. {
  216. LOG_E("sdio memalign error!\n");
  217. return NULL;
  218. }
  219. offset = (uint64_t)*mem_unalign % align;
  220. if (offset == 0)
  221. mem = (void *)*mem_unalign;
  222. else
  223. mem = (void *)(*mem_unalign + (align - offset));
  224. return mem;
  225. }
  226. static rt_err_t sdhci_send_data_cmd(struct rthw_sdhci *sdhci, struct rt_mmcsd_cmd *cmd, struct rt_mmcsd_data *data)
  227. {
  228. uintptr_t BASE = (uintptr_t)sdhci->base;
  229. uint32_t mode = 0;
  230. uint32_t flags = 0;
  231. int end_time = 0;
  232. int start_time = rt_tick_get_millisecond();
  233. sdhci_dma_config_t dma_config;
  234. while(1)
  235. {
  236. if (!(mmio_read_32(BASE + SDIF_PRESENT_STATE) & SDIF_CMD_INHIBIT))
  237. break;
  238. end_time = rt_tick_get_millisecond();
  239. if (end_time - start_time >= 2000)
  240. return -RT_ETIMEOUT;
  241. }
  242. rt_ubase_t start_addr;
  243. void *src_unalign = NULL;
  244. if (data)
  245. {
  246. dma_config.dma_des_buffer_len = data->blksize * data->blks;
  247. if (data->flags & DATA_DIR_READ)
  248. {
  249. if ((uint64_t)data->buf & (SDMMC_DMA_ALIGN_CACHE - 1))
  250. {
  251. start_addr = (rt_ubase_t)align_alloc(SDMMC_DMA_ALIGN_CACHE, dma_config.dma_des_buffer_len, (void **)&src_unalign);
  252. }
  253. else
  254. {
  255. start_addr = (rt_ubase_t)data->buf;
  256. }
  257. }
  258. else
  259. {
  260. start_addr = (rt_ubase_t)data->buf;
  261. }
  262. sdhci_prepare_data(sdhci, cmd, data, start_addr, dma_config.dma_des_buffer_len);
  263. mode = SDIF_TRNS_DMA;
  264. if (mmc_op_multi(cmd->cmd_code) || data->blks > 1)
  265. mode |= SDIF_TRNS_MULTI | SDIF_TRNS_BLK_CNT_EN;
  266. if (data->flags & DATA_DIR_READ)
  267. mode |= SDIF_TRNS_READ;
  268. else
  269. mode &= ~SDIF_TRNS_READ;
  270. mmio_write_16(BASE + SDIF_TRANSFER_MODE, mode);
  271. }
  272. // set cmd flags
  273. if (resp_type(cmd) == RESP_NONE)
  274. flags |= SDIF_CMD_RESP_NONE;
  275. else if (resp_type(cmd) == RESP_R2)
  276. flags |= SDIF_CMD_RESP_LONG;
  277. else if (resp_type(cmd) == RESP_R1B)
  278. flags |= SDIF_CMD_RESP_SHORT_BUSY;
  279. else
  280. flags |= SDIF_CMD_RESP_SHORT;
  281. if (data)
  282. {
  283. flags |= SDIF_CMD_CRC;
  284. flags |= SDIF_CMD_INDEX;
  285. flags |= SDIF_CMD_DATA;
  286. }
  287. mmio_write_32(BASE + SDIF_ARGUMENT, cmd->arg);
  288. // issue the cmd
  289. mmio_write_16(BASE + SDIF_COMMAND, SDIF_MAKE_CMD(cmd->cmd_code, flags));
  290. sdhci_wait_cmd_complete(sdhci);
  291. if (sdhci->cmd_error != RT_EOK)
  292. {
  293. LOG_E("cmd error: %d\n", sdhci->cmd_error);
  294. return sdhci->cmd_error;
  295. }
  296. memcpy((void *)cmd->resp, (void *)sdhci->response, sizeof(sdhci->response));
  297. if (data)
  298. {
  299. sdhci_wait_data_complete(sdhci);
  300. if (sdhci->data_error != RT_EOK)
  301. {
  302. LOG_E("sdio data error!\n");
  303. return sdhci->data_error;
  304. }
  305. if (data->flags & DATA_DIR_READ)
  306. {
  307. rt_hw_cpu_dcache_invalidate((void *)start_addr, dma_config.dma_des_buffer_len);
  308. if (src_unalign)
  309. {
  310. memcpy((void *)data->buf, (void *)start_addr, dma_config.dma_des_buffer_len);
  311. rt_free(src_unalign);
  312. src_unalign = NULL;
  313. }
  314. }
  315. }
  316. return RT_EOK;
  317. }
  318. static void sdhci_cmd_irq(struct rthw_sdhci *sdhci, uint32_t intmask)
  319. {
  320. int i;
  321. uintptr_t BASE = (uintptr_t)sdhci->base;
  322. if (intmask & (SDIF_INT_TIMEOUT | SDIF_INT_CRC |
  323. SDIF_INT_END_BIT | SDIF_INT_INDEX))
  324. {
  325. if (intmask & SDIF_INT_TIMEOUT)
  326. {
  327. sdhci->cmd_error = -RT_ETIMEOUT;
  328. LOG_E("SDIF_INT_TIMEOUT");
  329. }
  330. return;
  331. }
  332. if (intmask & SDIF_INT_RESPONSE)
  333. {
  334. if (sdhci->response_type == RESP_R2)
  335. {
  336. /* CRC is stripped so we need to do some shifting. */
  337. for (i = 0; i < 4; i++) {
  338. sdhci->response[i] = mmio_read_32(BASE + SDIF_RESPONSE_01 + (3-i)*4) << 8;
  339. if (i != 3)
  340. sdhci->response[i] |= mmio_read_8(BASE + SDIF_RESPONSE_01 + (3-i)*4-1);
  341. }
  342. LOG_D("sdhci->response: [%08x %08x %08x %08x]", sdhci->response[0], sdhci->response[1], sdhci->response[2], sdhci->response[3]);
  343. }
  344. else
  345. {
  346. sdhci->response[0] = mmio_read_32(BASE + SDIF_RESPONSE_01);
  347. LOG_D("sdhci->response: [%08x]", sdhci->response[0]);
  348. }
  349. rt_sem_release(sdhci->sem_cmd);
  350. }
  351. }
  352. static void sdhci_data_irq(struct rthw_sdhci *sdhci, uint32_t intmask)
  353. {
  354. uintptr_t BASE = (uintptr_t)sdhci->base;
  355. uint32_t command;
  356. /* CMD19 generates _only_ Buffer Read Ready interrupt */
  357. if (intmask & SDIF_INT_DATA_AVAIL)
  358. {
  359. command = SDIF_GET_CMD(mmio_read_16(BASE + SDIF_COMMAND));
  360. if (command == MMC_CMD19 ||
  361. command == MMC_CMD21) {
  362. //host->tuning_done = 1;
  363. return;
  364. }
  365. }
  366. if ((intmask & SDIF_INT_DATA_TIMEOUT) || (intmask & SDIF_INT_DATA_END_BIT) || (intmask & SDIF_INT_DATA_CRC) || (intmask & SDIF_INT_ADMA_ERROR))
  367. {
  368. sdhci->data_error = -RT_ERROR;
  369. return;
  370. }
  371. if (intmask & SDIF_INT_DATA_END)
  372. {
  373. sdhci->data_error = RT_EOK;
  374. return;
  375. }
  376. if (intmask & SDIF_INT_DMA_END)
  377. {
  378. uint64_t dma_addr;
  379. dma_addr = mmio_read_32(BASE + SDIF_ADMA_SA_LOW);
  380. mmio_write_32(BASE + SDIF_ADMA_SA_LOW, dma_addr);
  381. mmio_write_32(BASE + SDIF_ADMA_SA_HIGH, 0);
  382. }
  383. return;
  384. }
  385. static void sdhci_transfer_handle_irq(int irqno, void *param)
  386. {
  387. struct rthw_sdhci *sdhci = (struct rthw_sdhci *)param;
  388. uintptr_t BASE = (uintptr_t)sdhci->base;
  389. int max_loop = 16;
  390. uint32_t intmask;
  391. uint32_t mask;
  392. uint32_t unexpected;
  393. intmask = mmio_read_32(BASE + SDIF_INT_STATUS);
  394. if (!intmask || intmask == 0xffffffff)
  395. {
  396. LOG_E("never be here!\n");
  397. return;
  398. }
  399. do
  400. {
  401. mask = intmask & (SDIF_INT_CMD_MASK | SDIF_INT_DATA_MASK | SDIF_INT_BUS_POWER);
  402. mmio_write_32(BASE + SDIF_INT_STATUS, mask);
  403. if (intmask & SDIF_INT_CMD_MASK)
  404. {
  405. sdhci_cmd_irq(sdhci, intmask & SDIF_INT_CMD_MASK);
  406. }
  407. if (intmask & SDIF_INT_DMA_END)
  408. {
  409. uint64_t dma_addr;
  410. dma_addr = mmio_read_32(BASE + SDIF_ADMA_SA_LOW);
  411. mmio_write_32(BASE + SDIF_ADMA_SA_LOW, dma_addr);
  412. mmio_write_32(BASE + SDIF_ADMA_SA_HIGH, 0);
  413. return;
  414. }
  415. if (intmask & SDIF_INT_DATA_MASK)
  416. {
  417. sdhci_data_irq(sdhci, intmask & SDIF_INT_DATA_MASK);
  418. rt_sem_release(sdhci->sem_data);
  419. }
  420. if (intmask & SDIF_INT_CARD_INT)
  421. {
  422. LOG_D("init_card_init");
  423. }
  424. intmask &= ~(SDIF_INT_CARD_INSERT | SDIF_INT_CARD_REMOVE |
  425. SDIF_INT_CMD_MASK | SDIF_INT_DATA_MASK |
  426. SDIF_INT_ERROR | SDIF_INT_BUS_POWER |
  427. SDIF_INT_RETUNE | SDIF_INT_CARD_INT);
  428. if (intmask)
  429. {
  430. unexpected = intmask;
  431. mmio_write_32(BASE + SDIF_INT_STATUS, intmask);
  432. LOG_D("unexpected interrupt: 0x%08x.", unexpected);
  433. }
  434. intmask = mmio_read_32(BASE + SDIF_INT_STATUS);
  435. } while (intmask && --max_loop);
  436. }
  437. static uint32_t sdhci_set_clock(rt_ubase_t base, uint32_t target_hz)
  438. {
  439. uint32_t source_clock_hz;
  440. uint32_t ret;
  441. source_clock_hz = 375 * 1000 * 1000;
  442. if (target_hz <= 400000)
  443. ret = sdhci_set_card_clock(base, source_clock_hz, target_hz);
  444. else
  445. ret = SDIF_ChangeCardClock(base, source_clock_hz, target_hz);
  446. return ret;
  447. }
  448. static void sdhci_set_bus_width(rt_ubase_t base, uint8_t bus_width)
  449. {
  450. uintptr_t BASE = (uintptr_t)base;
  451. uint32_t ctrl;
  452. uint16_t ctrl_2;
  453. ctrl = mmio_read_8(BASE + SDIF_HOST_CONTROL);
  454. if (bus_width == MMCSD_BUS_WIDTH_1)
  455. ctrl &= ~SDIF_DAT_XFER_WIDTH;
  456. else if (bus_width == MMCSD_BUS_WIDTH_4)
  457. ctrl |= SDIF_DAT_XFER_WIDTH;
  458. ctrl |= SDIF_CTRL_HISPD;
  459. ctrl_2 = mmio_read_16(BASE + SDIF_HOST_CONTROL2);
  460. ctrl_2 &= ~SDIF_CTRL_UHS_MASK;
  461. ctrl_2 |= SDIF_CTRL_UHS_SDR25;
  462. mmio_write_16(BASE + SDIF_HOST_CONTROL2, ctrl_2);
  463. rt_thread_mdelay(1);
  464. mmio_write_8(BASE + SDIF_HOST_CONTROL, ctrl);
  465. }
  466. static void sdhci_enable_card_power(rt_ubase_t base, bool enable)
  467. {
  468. uintptr_t BASE = (uintptr_t)base;
  469. if (enable)
  470. {
  471. mmio_write_8(BASE + SDIF_PWR_CONTROL,mmio_read_8(BASE + SDIF_PWR_CONTROL) | 0x1);
  472. }
  473. else
  474. {
  475. mmio_write_8(BASE + SDIF_PWR_CONTROL,mmio_read_8(BASE+ SDIF_PWR_CONTROL) & ~0x1);
  476. }
  477. }
  478. static uint32_t sdhci_detect_card_insert(rt_ubase_t base, bool data3)
  479. {
  480. uintptr_t BASE = (uintptr_t)base;
  481. if (data3)
  482. {
  483. return (mmio_read_32(BASE+SDIF_PRESENT_STATE) & SDIF_CARD_STABLE) == SDIF_CARD_STABLE ? 0U : 1U;
  484. }
  485. else
  486. {
  487. return (mmio_read_32(BASE+SDIF_PRESENT_STATE) & SDIF_CARD_INSERTED) == SDIF_CARD_INSERTED ? 1U : 0U;
  488. }
  489. }
  490. static void sdhci_enable_card_clock(rt_ubase_t base, bool enable)
  491. {
  492. uintptr_t BASE = (uintptr_t)base;
  493. if (enable)
  494. {
  495. mmio_write_16(BASE + SDIF_CLK_CTRL, mmio_read_32(BASE + SDIF_CLK_CTRL) | (0x1<<2)); // stop SD clock
  496. }
  497. else
  498. {
  499. mmio_write_16(BASE + SDIF_CLK_CTRL, mmio_read_32(BASE + SDIF_CLK_CTRL) & ~(0x1<<2)); // stop SD clock
  500. }
  501. }
  502. static void sdhci_hw_reset(rt_ubase_t base)
  503. {
  504. uintptr_t BASE = (uintptr_t)base;
  505. mmio_write_16(BASE + SDIF_CLK_CTRL, (mmio_read_16(BASE + SDIF_CLK_CTRL) & 0x3F) | DEFAULT_DIV_SD_INIT_CLOCK << 8);
  506. rt_thread_mdelay(1);
  507. mmio_write_8(BASE + SDIF_SOFTWARE_RESET, 0x7);
  508. while (mmio_read_8(BASE + SDIF_SOFTWARE_RESET));
  509. }
  510. #define REG_TOP_SD_PWRSW_CTRL (0x1F4)
  511. static void sdhci_pad_setting(rt_ubase_t base)
  512. {
  513. uintptr_t BASE = (uintptr_t)base;
  514. if (BASE == (rt_ubase_t)SDIO0_BASE)
  515. {
  516. //set power for sd0
  517. mmio_write_32(TOP_BASE + REG_TOP_SD_PWRSW_CTRL, 0x9);
  518. rt_thread_mdelay(1);
  519. //set pu/down
  520. mmio_write_32(REG_SDIO0_CD_PAD_REG, (mmio_read_32(REG_SDIO0_CD_PAD_REG) & REG_SDIO0_PAD_MASK) | REG_SDIO0_CD_PAD_VALUE << REG_SDIO0_PAD_SHIFT);
  521. mmio_write_32(REG_SDIO0_PWR_EN_PAD_REG, (mmio_read_32(REG_SDIO0_PWR_EN_PAD_REG) & REG_SDIO0_PAD_MASK) | REG_SDIO0_PWR_EN_PAD_VALUE << REG_SDIO0_PAD_SHIFT);
  522. mmio_write_32(REG_SDIO0_CLK_PAD_REG, (mmio_read_32(REG_SDIO0_CLK_PAD_REG) & REG_SDIO0_PAD_MASK) | REG_SDIO0_CLK_PAD_VALUE << REG_SDIO0_PAD_SHIFT);
  523. mmio_write_32(REG_SDIO0_CMD_PAD_REG, (mmio_read_32(REG_SDIO0_CMD_PAD_REG) & REG_SDIO0_PAD_MASK) | REG_SDIO0_CMD_PAD_VALUE << REG_SDIO0_PAD_SHIFT);
  524. mmio_write_32(REG_SDIO0_DAT1_PAD_REG, (mmio_read_32(REG_SDIO0_DAT1_PAD_REG) & REG_SDIO0_PAD_MASK) | REG_SDIO0_DAT1_PAD_VALUE << REG_SDIO0_PAD_SHIFT);
  525. mmio_write_32(REG_SDIO0_DAT0_PAD_REG, (mmio_read_32(REG_SDIO0_DAT0_PAD_REG) & REG_SDIO0_PAD_MASK) | REG_SDIO0_DAT0_PAD_VALUE << REG_SDIO0_PAD_SHIFT);
  526. mmio_write_32(REG_SDIO0_DAT2_PAD_REG, (mmio_read_32(REG_SDIO0_DAT2_PAD_REG) & REG_SDIO0_PAD_MASK) | REG_SDIO0_DAT2_PAD_VALUE << REG_SDIO0_PAD_SHIFT);
  527. mmio_write_32(REG_SDIO0_DAT3_PAD_REG, (mmio_read_32(REG_SDIO0_DAT3_PAD_REG) & REG_SDIO0_PAD_MASK) | REG_SDIO0_DAT3_PAD_VALUE << REG_SDIO0_PAD_SHIFT);
  528. //set pinmux
  529. mmio_write_8(REG_SDIO0_CD_PIO_REG, REG_SDIO0_CD_PIO_VALUE);
  530. mmio_write_8(REG_SDIO0_PWR_EN_PIO_REG, REG_SDIO0_PWR_EN_PIO_VALUE);
  531. mmio_write_8(REG_SDIO0_CLK_PIO_REG, REG_SDIO0_CLK_PIO_VALUE);
  532. mmio_write_8(REG_SDIO0_CMD_PIO_REG, REG_SDIO0_CMD_PIO_VALUE);
  533. mmio_write_8(REG_SDIO0_DAT0_PIO_REG, REG_SDIO0_DAT0_PIO_VALUE);
  534. mmio_write_8(REG_SDIO0_DAT1_PIO_REG, REG_SDIO0_DAT1_PIO_VALUE);
  535. mmio_write_8(REG_SDIO0_DAT2_PIO_REG, REG_SDIO0_DAT2_PIO_VALUE);
  536. mmio_write_8(REG_SDIO0_DAT3_PIO_REG, REG_SDIO0_DAT3_PIO_VALUE);
  537. }
  538. else if(BASE == (rt_ubase_t)SDIO1_BASE)
  539. {
  540. // set rtc sdio1 related register
  541. mmio_write_32(RTCSYS_CTRL, 0x1);
  542. mmio_write_32(RTCSYS_CLKMUX, 0x10);
  543. mmio_write_32(RTCSYS_CLKBYP, 0xfffffffc);
  544. //mmio_write_32(RTCSYS_MCU51_ICTRL1, 0x0);
  545. mmio_write_32(REG_SDIO1_CLK_PAD_REG, (mmio_read_32(REG_SDIO1_CLK_PAD_REG) & REG_SDIO1_PAD_MASK) | REG_SDIO1_CLK_PAD_VALUE << REG_SDIO1_PAD_SHIFT);
  546. mmio_write_32(REG_SDIO1_CMD_PAD_REG, (mmio_read_32(REG_SDIO1_CMD_PAD_REG) & REG_SDIO1_PAD_MASK) | REG_SDIO1_CMD_PAD_VALUE << REG_SDIO1_PAD_SHIFT);
  547. mmio_write_32(REG_SDIO1_DAT1_PAD_REG, (mmio_read_32(REG_SDIO1_DAT1_PAD_REG) & REG_SDIO1_PAD_MASK) | REG_SDIO1_DAT1_PAD_VALUE << REG_SDIO1_PAD_SHIFT);
  548. mmio_write_32(REG_SDIO1_DAT0_PAD_REG, (mmio_read_32(REG_SDIO1_DAT0_PAD_REG) & REG_SDIO1_PAD_MASK) | REG_SDIO1_DAT0_PAD_VALUE << REG_SDIO1_PAD_SHIFT);
  549. mmio_write_32(REG_SDIO1_DAT2_PAD_REG, (mmio_read_32(REG_SDIO1_DAT2_PAD_REG) & REG_SDIO1_PAD_MASK) | REG_SDIO1_DAT2_PAD_VALUE << REG_SDIO1_PAD_SHIFT);
  550. mmio_write_32(REG_SDIO1_DAT3_PAD_REG, (mmio_read_32(REG_SDIO1_DAT3_PAD_REG) & REG_SDIO1_PAD_MASK) | REG_SDIO1_DAT3_PAD_VALUE << REG_SDIO1_PAD_SHIFT);
  551. mmio_write_32(RTCSYS_CTRL, 0x1); // enable rtc2ap_ahb;
  552. //set pinmux
  553. mmio_write_32(TOP_BASE + 0x294, (mmio_read_32(TOP_BASE + 0x294) & 0xFFFFFBFF));
  554. mmio_write_8(REG_SDIO1_CLK_PIO_REG, REG_SDIO1_CLK_PIO_VALUE);
  555. mmio_write_8(REG_SDIO1_CMD_PIO_REG, REG_SDIO1_CMD_PIO_VALUE);
  556. mmio_write_8(REG_SDIO1_DAT0_PIO_REG, REG_SDIO1_DAT0_PIO_VALUE);
  557. mmio_write_8(REG_SDIO1_DAT1_PIO_REG, REG_SDIO1_DAT1_PIO_VALUE);
  558. mmio_write_8(REG_SDIO1_DAT2_PIO_REG, REG_SDIO1_DAT2_PIO_VALUE);
  559. mmio_write_8(REG_SDIO1_DAT3_PIO_REG, REG_SDIO1_DAT3_PIO_VALUE);
  560. }
  561. else if(BASE == (rt_ubase_t)SDIO2_BASE)
  562. {
  563. //set pu/down
  564. mmio_write_32(REG_SDIO2_RSTN_PAD_REG, (mmio_read_32(REG_SDIO2_RSTN_PAD_REG) & REG_SDIO2_PAD_MASK) | REG_SDIO2_RSTN_PAD_VALUE << REG_SDIO2_PAD_SHIFT);
  565. mmio_write_32(REG_SDIO2_CLK_PAD_REG, (mmio_read_32(REG_SDIO2_CLK_PAD_REG) & REG_SDIO2_PAD_MASK) | REG_SDIO2_CLK_PAD_VALUE << REG_SDIO2_PAD_SHIFT);
  566. mmio_write_32(REG_SDIO2_CMD_PAD_REG, (mmio_read_32(REG_SDIO2_CMD_PAD_REG) & REG_SDIO2_PAD_MASK) | REG_SDIO2_CMD_PAD_VALUE << REG_SDIO2_PAD_SHIFT);
  567. mmio_write_32(REG_SDIO2_DAT0_PAD_REG, (mmio_read_32(REG_SDIO2_DAT0_PAD_REG) & REG_SDIO2_PAD_MASK) | REG_SDIO2_DAT0_PAD_VALUE << REG_SDIO2_PAD_SHIFT);
  568. mmio_write_32(REG_SDIO2_DAT1_PAD_REG, (mmio_read_32(REG_SDIO2_DAT1_PAD_REG) & REG_SDIO2_PAD_MASK) | REG_SDIO2_DAT1_PAD_VALUE << REG_SDIO2_PAD_SHIFT);
  569. mmio_write_32(REG_SDIO2_DAT2_PAD_REG, (mmio_read_32(REG_SDIO2_DAT2_PAD_REG) & REG_SDIO2_PAD_MASK) | REG_SDIO2_DAT2_PAD_VALUE << REG_SDIO2_PAD_SHIFT);
  570. mmio_write_32(REG_SDIO2_DAT3_PAD_REG, (mmio_read_32(REG_SDIO2_DAT3_PAD_REG) & REG_SDIO2_PAD_MASK) | REG_SDIO2_DAT3_PAD_VALUE << REG_SDIO2_PAD_SHIFT);
  571. //set pinmux
  572. mmio_write_8(REG_SDIO2_RSTN_PIO_REG, REG_SDIO2_RSTN_PIO_VALUE);
  573. mmio_write_8(REG_SDIO2_CLK_PIO_REG, REG_SDIO2_CLK_PIO_VALUE);
  574. mmio_write_8(REG_SDIO2_CMD_PIO_REG, REG_SDIO2_CMD_PIO_VALUE);
  575. mmio_write_8(REG_SDIO2_DAT0_PIO_REG, REG_SDIO2_DAT0_PIO_VALUE);
  576. mmio_write_8(REG_SDIO2_DAT1_PIO_REG, REG_SDIO2_DAT1_PIO_VALUE);
  577. mmio_write_8(REG_SDIO2_DAT2_PIO_REG, REG_SDIO2_DAT2_PIO_VALUE);
  578. mmio_write_8(REG_SDIO2_DAT3_PIO_REG, REG_SDIO2_DAT3_PIO_VALUE);
  579. }
  580. }
  581. static void sdhci_phy_init(rt_ubase_t base)
  582. {
  583. uintptr_t BASE = (uintptr_t)base;
  584. uintptr_t vendor_base = BASE + (mmio_read_16(BASE + P_VENDOR_SPECIFIC_AREA) & ((1<<12)-1));
  585. sdhci_hw_reset(base);
  586. rt_thread_mdelay(3);
  587. sdhci_pad_setting(base);
  588. if (BASE == (rt_ubase_t)SDIO2_BASE)
  589. {
  590. //reg_0x200[0] = 1 for sd2
  591. mmio_write_32(vendor_base, mmio_read_32(vendor_base) | BIT(0));
  592. }
  593. //reg_0x200[1] = 1
  594. mmio_write_32(vendor_base, mmio_read_32(vendor_base) | BIT(1));
  595. if (BASE == (rt_ubase_t)SDIO1_BASE)
  596. {
  597. //reg_0x200[16] = 1 for sd1
  598. mmio_write_32(vendor_base, mmio_read_32(vendor_base) | BIT(16));
  599. }
  600. mmio_write_32(vendor_base + SDIF_PHY_CONFIG, mmio_read_32(vendor_base + SDIF_PHY_CONFIG) | BIT(0));
  601. mmio_write_32(vendor_base + SDIF_PHY_TX_RX_DLY, 0x1000100);
  602. }
  603. static void sdhci_init(rt_ubase_t base)
  604. {
  605. uintptr_t BASE = (uintptr_t)base;
  606. mmio_write_8(BASE + SDIF_SOFTWARE_RESET, 0x6);
  607. mmio_write_8(BASE + SDIF_PWR_CONTROL, (0x7 << 1));
  608. mmio_write_8(BASE + SDIF_TOUT_CTRL, 0xe);
  609. mmio_write_16(BASE + SDIF_HOST_CONTROL2, mmio_read_16(BASE + SDIF_HOST_CONTROL2) | 1<<11);
  610. mmio_write_16(BASE + SDIF_CLK_CTRL, mmio_read_16(BASE + SDIF_CLK_CTRL) & ~(0x1 << 5));
  611. mmio_write_16(BASE + SDIF_HOST_CONTROL2, mmio_read_16(BASE + SDIF_HOST_CONTROL2) | SDIF_HOST_VER4_ENABLE);
  612. mmio_write_16(BASE + SDIF_HOST_CONTROL2, mmio_read_16(BASE + SDIF_HOST_CONTROL2) | 0x1<<13);
  613. if (mmio_read_32(BASE + SDIF_CAPABILITIES1) & (0x1<<29))
  614. {
  615. mmio_write_16(BASE + SDIF_HOST_CONTROL2, mmio_read_16(BASE + SDIF_HOST_CONTROL2) | (0x1<<14)); // enable async int
  616. }
  617. rt_thread_mdelay(20);
  618. mmio_write_16(BASE + SDIF_HOST_CONTROL2, mmio_read_16(BASE + SDIF_HOST_CONTROL2) & ~(0x1<<8)); // clr UHS2_IF_ENABLE
  619. mmio_write_8(BASE + SDIF_PWR_CONTROL, mmio_read_8(BASE + SDIF_PWR_CONTROL) | 0x1); // set SD_BUS_PWR_VDD1
  620. mmio_write_16(BASE + SDIF_HOST_CONTROL2, mmio_read_16(BASE + SDIF_HOST_CONTROL2) & ~0x7); // clr UHS_MODE_SEL
  621. rt_thread_mdelay(50);
  622. mmio_write_16(BASE + SDIF_CLK_CTRL, mmio_read_16(BASE + SDIF_CLK_CTRL) | (0x1<<2)); // supply SD clock
  623. rt_hw_us_delay(400); // wait for voltage ramp up time at least 74 cycle, 400us is 80 cycles for 200Khz
  624. mmio_write_16(BASE + SDIF_INT_STATUS, mmio_read_16(BASE + SDIF_INT_STATUS) | (0x1 << 6));
  625. mmio_write_16(BASE + SDIF_INT_STATUS_EN, mmio_read_16(BASE + SDIF_INT_STATUS_EN) | 0xFFFF);
  626. mmio_write_16(BASE + SDIF_ERR_INT_STATUS_EN, mmio_read_16(BASE + SDIF_ERR_INT_STATUS_EN) | 0xFFFF);
  627. }
  628. void rthw_sdhci_set_config(struct rthw_sdhci *sdhci)
  629. {
  630. uint32_t pio_irqs = SDIF_INT_DATA_AVAIL | SDIF_INT_SPACE_AVAIL;
  631. uint32_t dma_irqs = SDIF_INT_DMA_END | SDIF_INT_ADMA_ERROR;
  632. uint32_t int_status;
  633. uintptr_t BASE = (uintptr_t)sdhci->base;
  634. static bool sd0_clock_state = false;
  635. static bool sd1_clock_state = false;
  636. static bool sd2_clock_state = false;
  637. if (BASE == (rt_ubase_t)SDIO0_BASE)
  638. {
  639. LOG_D("MMC_FLAG_SDCARD.");
  640. if (sd0_clock_state == false)
  641. {
  642. mmio_write_32(MMC_SDIO0_PLL_REGISTER, MMC_MAX_CLOCK_DIV_VALUE);
  643. mmio_clrbits_32(CLOCK_BYPASS_SELECT_REGISTER, BIT(6));
  644. sd0_clock_state = true;
  645. }
  646. }
  647. else if (BASE == (rt_ubase_t)SDIO1_BASE)
  648. {
  649. LOG_D("MMC_FLAG_SDIO.");
  650. if (sd1_clock_state == false)
  651. {
  652. mmio_write_32(MMC_SDIO1_PLL_REGISTER, MMC_MAX_CLOCK_DIV_VALUE);
  653. mmio_clrbits_32(CLOCK_BYPASS_SELECT_REGISTER, BIT(7));
  654. sd1_clock_state = true;
  655. }
  656. }
  657. else if (BASE == (rt_ubase_t)SDIO2_BASE)
  658. {
  659. LOG_D("MMC_FLAG_EMMC.");
  660. if (sd2_clock_state == false)
  661. {
  662. mmio_write_32(MMC_SDIO2_PLL_REGISTER, MMC_MAX_CLOCK_DIV_VALUE);
  663. mmio_clrbits_32(CLOCK_BYPASS_SELECT_REGISTER, BIT(5));
  664. sd2_clock_state = true;
  665. }
  666. }
  667. sdhci_phy_init(sdhci->base);
  668. sdhci_init(sdhci->base);
  669. int_status = SDIF_INT_BUS_POWER | SDIF_INT_DATA_END_BIT |
  670. SDIF_INT_DATA_CRC | SDIF_INT_DATA_TIMEOUT |
  671. SDIF_INT_INDEX | SDIF_INT_END_BIT | SDIF_INT_CRC |
  672. SDIF_INT_TIMEOUT | SDIF_INT_DATA_END | SDIF_INT_RESPONSE;
  673. int_status = (int_status & ~pio_irqs) | dma_irqs;
  674. if (int_status)
  675. {
  676. rt_hw_interrupt_install(sdhci->irq, sdhci_transfer_handle_irq, sdhci, sdhci->name);
  677. rt_hw_interrupt_umask(sdhci->irq);
  678. mmio_write_32(BASE + SDIF_SIGNAL_ENABLE, int_status);
  679. }
  680. else
  681. {
  682. mmio_write_32(BASE + SDIF_SIGNAL_ENABLE, 0);
  683. }
  684. }
  685. static void rthw_sdhci_request(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
  686. {
  687. RT_ASSERT(host != RT_NULL);
  688. RT_ASSERT(req != RT_NULL);
  689. rt_err_t ret = RT_EOK;
  690. struct rthw_sdhci *sdhci = (struct rthw_sdhci *)host->private_data;
  691. if (req->cmd != RT_NULL)
  692. {
  693. struct rt_mmcsd_cmd *cmd = req->cmd;
  694. struct rt_mmcsd_data *data = req->data;
  695. LOG_D("[%s%s%s%s%s]REQ: CMD:%d ARG:0x%08x RES:%s%s%s%s%s%s%s%s%s rw:%c addr:%p, blks:%d, blksize:%d datalen:%d",
  696. (host->card == RT_NULL) ? "Unknown" : "",
  697. (host->card) && (host->card->card_type == CARD_TYPE_MMC) ? "MMC" : "",
  698. (host->card) && (host->card->card_type == CARD_TYPE_SD) ? "SD" : "",
  699. (host->card) && (host->card->card_type == CARD_TYPE_SDIO) ? "SDIO" : "",
  700. (host->card) && (host->card->card_type == CARD_TYPE_SDIO_COMBO) ? "SDIO_COMBO" : "",
  701. cmd->cmd_code,
  702. cmd->arg,
  703. resp_type(cmd) == RESP_NONE ? "NONE" : "",
  704. resp_type(cmd) == RESP_R1 ? "R1" : "",
  705. resp_type(cmd) == RESP_R1B ? "R1B" : "",
  706. resp_type(cmd) == RESP_R2 ? "R2" : "",
  707. resp_type(cmd) == RESP_R3 ? "R3" : "",
  708. resp_type(cmd) == RESP_R4 ? "R4" : "",
  709. resp_type(cmd) == RESP_R5 ? "R5" : "",
  710. resp_type(cmd) == RESP_R6 ? "R6" : "",
  711. resp_type(cmd) == RESP_R7 ? "R7" : "",
  712. data ? (data->flags & DATA_DIR_WRITE ? 'w' : 'r') : '-',
  713. data ? data->buf : 0,
  714. data ? data->blks : 0,
  715. data ? data->blksize : 0,
  716. data ? data->blks * data->blksize : 0);
  717. if (cmd->cmd_code == SD_IO_SEND_OP_COND)
  718. {
  719. cmd->err = -RT_ERROR;
  720. mmcsd_req_complete(host);
  721. return;
  722. }
  723. sdhci->response_type = resp_type(cmd);
  724. sdhci->cmd_error = RT_EOK;
  725. sdhci->data_error = RT_EOK;
  726. memset((void *)sdhci->response, 0, sizeof(sdhci->response));
  727. memset(cmd->resp, 0, sizeof(cmd->resp));
  728. ret = sdhci_send_data_cmd(sdhci, cmd, data);
  729. if (ret != RT_EOK)
  730. {
  731. memset(cmd->resp, 0, sizeof(cmd->resp));
  732. }
  733. cmd->err = ret;
  734. }
  735. if (req->stop != RT_NULL)
  736. {
  737. struct rt_mmcsd_cmd *stop = req->stop;
  738. stop->err = sdhci_send_data_cmd(sdhci, stop, RT_NULL);
  739. }
  740. mmcsd_req_complete(host);
  741. }
  742. static void rthw_sdhci_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
  743. {
  744. RT_ASSERT(host != RT_NULL);
  745. RT_ASSERT(io_cfg != RT_NULL);
  746. struct rthw_sdhci *sdhci = (struct rthw_sdhci *)host->private_data;
  747. rt_uint32_t clk = io_cfg->clock;
  748. LOG_D("clk:%d width:%s%s%s power:%s%s%s",
  749. clk,
  750. io_cfg->bus_width == MMCSD_BUS_WIDTH_8 ? "8" : "",
  751. io_cfg->bus_width == MMCSD_BUS_WIDTH_4 ? "4" : "",
  752. io_cfg->bus_width == MMCSD_BUS_WIDTH_1 ? "1" : "",
  753. io_cfg->power_mode == MMCSD_POWER_OFF ? "OFF" : "",
  754. io_cfg->power_mode == MMCSD_POWER_UP ? "UP" : "",
  755. io_cfg->power_mode == MMCSD_POWER_ON ? "ON" : ""
  756. );
  757. if (clk > host->freq_max)
  758. clk = host->freq_max;
  759. if (clk < host->freq_min)
  760. clk = host->freq_min;
  761. sdhci_set_clock(sdhci->base, clk);
  762. /* power mode */
  763. switch (io_cfg->power_mode)
  764. {
  765. case MMCSD_POWER_UP:
  766. case MMCSD_POWER_ON:
  767. sdhci_enable_card_power(sdhci->base, true);
  768. break;
  769. case MMCSD_POWER_OFF:
  770. sdhci_enable_card_power(sdhci->base, false);
  771. break;
  772. default:
  773. break;
  774. }
  775. /* bus width */
  776. switch (io_cfg->bus_width)
  777. {
  778. case MMCSD_BUS_WIDTH_1:
  779. case MMCSD_BUS_WIDTH_4:
  780. sdhci_set_bus_width(sdhci->base, io_cfg->bus_width);
  781. break;
  782. case MMCSD_BUS_WIDTH_8:
  783. default:
  784. LOG_E("invalid bus_width: %d", io_cfg->bus_width);
  785. break;
  786. }
  787. }
  788. static const struct rt_mmcsd_host_ops ops = {
  789. rthw_sdhci_request,
  790. rthw_sdhci_iocfg,
  791. RT_NULL,
  792. RT_NULL,
  793. };
  794. static int rthw_sdhci_init(void)
  795. {
  796. rt_err_t ret = RT_EOK;
  797. struct rt_mmcsd_host *host;
  798. struct rthw_sdhci *sdhci = RT_NULL;
  799. sdhci = rt_malloc(sizeof(struct rthw_sdhci));
  800. if (sdhci == RT_NULL)
  801. {
  802. LOG_E("malloc rthw_sdhci faile...");
  803. }
  804. rt_memset(sdhci, 0, sizeof(struct rthw_sdhci));
  805. sdhci->sem_cmd = rt_sem_create("sem_cmd", 0, RT_IPC_FLAG_FIFO);
  806. if (sdhci->sem_cmd == RT_NULL)
  807. {
  808. LOG_E("rt_sem_create sdhci event failed...");
  809. rt_free(sdhci);
  810. sdhci = RT_NULL;
  811. return ret;
  812. }
  813. sdhci->sem_data = rt_sem_create("sem_data", 0, RT_IPC_FLAG_FIFO);
  814. if (sdhci->sem_data == RT_NULL)
  815. {
  816. LOG_E("rt_sem_create sdhci event failed...");
  817. rt_sem_delete(sdhci->sem_cmd);
  818. rt_free(sdhci);
  819. sdhci = RT_NULL;
  820. return ret;
  821. }
  822. sdhci->base = (rt_ubase_t)SDIO0_BASE;
  823. sdhci->irq = SDIO0_IRQ;
  824. strcpy(sdhci->name, "sdio0");
  825. rthw_sdhci_set_config(sdhci);
  826. host = mmcsd_alloc_host();
  827. RT_ASSERT(host != RT_NULL);
  828. /* set host default attributes */
  829. host->ops = &ops;
  830. host->freq_min = 400000;
  831. host->freq_max = 50 * 1000 * 1000;
  832. host->valid_ocr = VDD_31_32 | VDD_32_33 | VDD_33_34;
  833. host->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED;
  834. host->max_seg_size = 512;
  835. host->max_dma_segs = 1;
  836. host->max_blk_size= 512;
  837. host->max_blk_count = 512;
  838. sdhci->host = host;
  839. host->private_data = sdhci;
  840. /* ready to change */
  841. mmcsd_change(host);
  842. return RT_EOK;
  843. }
  844. INIT_DEVICE_EXPORT(rthw_sdhci_init);
  845. void sdhci_reg_dump(uint8_t argc, char **argv)
  846. {
  847. rt_ubase_t base;
  848. if (argc < 2)
  849. {
  850. rt_kprintf("Usage: sdhci_reg_dump 0/1/2\n");
  851. return;
  852. }
  853. if (0 == atoi(argv[1]))
  854. base = (rt_ubase_t)SDIO0_BASE;
  855. else if (1 == atoi(argv[1]))
  856. base = (rt_ubase_t)SDIO1_BASE;
  857. else
  858. base = (rt_ubase_t)SDIO2_BASE;
  859. uintptr_t BASE = (uintptr_t)base;
  860. rt_kprintf("============ SDHCI REGISTER DUMP ===========\n");
  861. rt_kprintf("Sys addr: 0x%08x | Version: 0x%08x\n",
  862. mmio_read_32(BASE + SDIF_DMA_ADDRESS),
  863. mmio_read_16(BASE + SDIF_HOST_VERSION));
  864. rt_kprintf("Blk size: 0x%08x | Blk cnt: 0x%08x\n",
  865. mmio_read_16(BASE + SDIF_BLOCK_SIZE),
  866. mmio_read_16(BASE + SDIF_BLOCK_COUNT));
  867. rt_kprintf("Argument: 0x%08x | Trn mode: 0x%08x\n",
  868. mmio_read_32(BASE + SDIF_ARGUMENT),
  869. mmio_read_16(BASE + SDIF_TRANSFER_MODE));
  870. rt_kprintf("Present: 0x%08x | Host ctl: 0x%08x\n",
  871. mmio_read_32(BASE + SDIF_PRESENT_STATE),
  872. mmio_read_8(BASE + SDIF_HOST_CONTROL));
  873. rt_kprintf("Power: 0x%08x | Blk gap: 0x%08x\n",
  874. mmio_read_8(BASE + SDIF_PWR_CONTROL),
  875. mmio_read_8(BASE + SDIF_BLOCK_GAP_CONTROL));
  876. rt_kprintf("Wake-up: 0x%08x | Clock: 0x%08x\n",
  877. mmio_read_8(BASE + SDIF_WAKE_UP_CONTROL),
  878. mmio_read_16(BASE + SDIF_CLK_CTRL));
  879. rt_kprintf("Timeout: 0x%08x | Int stat: 0x%08x\n",
  880. mmio_read_8(BASE + SDIF_TOUT_CTRL),
  881. mmio_read_32(BASE + SDIF_INT_STATUS));
  882. rt_kprintf("Int enab: 0x%08x | Sig enab: 0x%08x\n",
  883. mmio_read_32(BASE + SDIF_INT_ENABLE),
  884. mmio_read_32(BASE + SDIF_SIGNAL_ENABLE));
  885. rt_kprintf("ACmd stat: 0x%08x | Slot int: 0x%08x\n",
  886. mmio_read_16(BASE + SDIF_AUTO_CMD_STATUS),
  887. mmio_read_16(BASE + SDIF_SLOT_INT_STATUS));
  888. rt_kprintf("Caps: 0x%08x | Caps_1: 0x%08x\n",
  889. mmio_read_32(BASE + SDIF_CAPABILITIES),
  890. mmio_read_32(BASE + SDIF_CAPABILITIES_1));
  891. rt_kprintf("Cmd: 0x%08x | Max curr: 0x%08x\n",
  892. mmio_read_16(BASE + SDIF_COMMAND),
  893. mmio_read_32(BASE + SDIF_MAX_CURRENT));
  894. rt_kprintf("Resp[0]: 0x%08x | Resp[1]: 0x%08x\n",
  895. mmio_read_32(BASE + SDIF_RESPONSE),
  896. mmio_read_32(BASE + SDIF_RESPONSE + 4));
  897. rt_kprintf("Resp[2]: 0x%08x | Resp[3]: 0x%08x\n",
  898. mmio_read_32(BASE + SDIF_RESPONSE + 8),
  899. mmio_read_32(BASE + SDIF_RESPONSE + 12));
  900. rt_kprintf("Host ctl2: 0x%08x\n",
  901. mmio_read_16(BASE + SDIF_HOST_CONTROL2));
  902. rt_kprintf("ADMA Err: 0x%08x | ADMA Ptr: 0x%08x%08x\n",
  903. mmio_read_32(BASE + SDIF_ADMA_ERROR),
  904. mmio_read_32(BASE + SDIF_ADMA_ADDRESS_HI),
  905. mmio_read_32(BASE + SDIF_ADMA_ADDRESS));
  906. rt_kprintf("============================================\n");
  907. }
  908. MSH_CMD_EXPORT(sdhci_reg_dump, dump sdhci register);