drv_sdhci.c 35 KB

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