drv_sdcard.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-05-05 vandoul first
  9. */
  10. #include <rtthread.h>
  11. #include "cy_gpio.h"
  12. #include "cyhal_gpio.h"
  13. #include "cyhal_sdhc.h"
  14. #ifdef BSP_USING_SDCARD
  15. //#define DRV_DEBUG
  16. #define LOG_TAG "drv.sdio"
  17. #include <drv_log.h>
  18. #define SDIO_BLOCK_SIZE (512)
  19. #if BSP_USING_SDCARD_LED_CTRL_ENANBLE
  20. #define SDCARD_LED_CTRL_ENABLE true
  21. #else
  22. #define SDCARD_LED_CTRL_ENABLE false
  23. #endif
  24. #if BSP_USING_SDCARD_EMMC_ENANBLE
  25. #define SDCARD_EMMC_ENABLE true
  26. #else
  27. #define SDCARD_EMMC_ENABLE false
  28. #endif
  29. struct _cy_sdio_pin_and_name_config
  30. {
  31. const char *name;
  32. cyhal_gpio_t cmd; /**< The pin connected to the command signal. */
  33. cyhal_gpio_t clk; /**< The pin connected to the clock signal. */
  34. cyhal_gpio_t data0; /**< The pin connected to the data0 signal. */
  35. cyhal_gpio_t data1; /**< The pin connected to the data1 signal. */
  36. cyhal_gpio_t data2; /**< The pin connected to the data2 signal. */
  37. cyhal_gpio_t data3; /**< The pin connected to the data3 signal. */
  38. cyhal_gpio_t data4; /**< The pin connected to the data4 signal; pass NC when unused. */
  39. cyhal_gpio_t data5; /**< The pin connected to the data5 signal; pass NC when unused. */
  40. cyhal_gpio_t data6; /**< The pin connected to the data6 signal; pass NC when unused. */
  41. cyhal_gpio_t data7; /**< The pin connected to the data7 signal; pass NC when unused. */
  42. cyhal_gpio_t card_detect; /**< The pin connected to the card detect signal. */
  43. cyhal_gpio_t io_volt_sel; /**< The pin connected to the voltage select signal. */
  44. cyhal_gpio_t card_if_pwr_en; /**< The pin connected to the card interface power enable signal. */
  45. cyhal_gpio_t card_mech_write_prot; /**< The pin connected to the write protect signal. */
  46. cyhal_gpio_t led_ctrl; /**< The pin connected to the LED control signal. */
  47. cyhal_gpio_t card_emmc_reset; /**< The pin connected to the eMMC card reset signal. */
  48. };
  49. static const struct _cy_sdio_pin_and_name_config _sdcard_config =
  50. {
  51. .name = "sd0",
  52. .cmd = BSP_USING_SDCARD_CMD_PIN,
  53. .clk = BSP_USING_SDCARD_CLK_PIN,
  54. .data0 = BSP_USING_SDCARD_DAT0_PIN,
  55. .data1 = BSP_USING_SDCARD_DAT1_PIN,
  56. .data2 = BSP_USING_SDCARD_DAT2_PIN,
  57. .data3 = BSP_USING_SDCARD_DAT3_PIN,
  58. .data4 = BSP_USING_SDCARD_DAT4_PIN,
  59. .data5 = BSP_USING_SDCARD_DAT5_PIN,
  60. .data6 = BSP_USING_SDCARD_DAT6_PIN,
  61. .data7 = BSP_USING_SDCARD_DAT7_PIN,
  62. .card_detect = BSP_USING_SDCARD_DETECT_PIN,
  63. .io_volt_sel = BSP_USING_SDCARD_IO_VOLT_SEL_PIN,
  64. .card_if_pwr_en = BSP_USING_SDCARD_CARD_IF_PWR_EN_PIN,
  65. .card_mech_write_prot = BSP_USING_SDCARD_CARD_MECH_WRITE_PROT_PIN,
  66. #if BSP_USING_SDCARD_LED_CTRL_PIN
  67. .led_ctrl = BSP_USING_SDCARD_LED_CTRL_PIN,
  68. #else
  69. .led_ctrl = -1,
  70. #endif
  71. .card_emmc_reset = BSP_USING_SDCARD_CARD_EMMC_RESET_PIN,
  72. };
  73. #include <dfs_fs.h>
  74. #include <drivers/mmcsd_core.h>
  75. #include <drivers/gpt.h>
  76. struct rthw_sdio
  77. {
  78. struct rt_device parent;
  79. cyhal_sdhc_t sdhc_obj; /**< Object for use with the SDHC HAL driver. */
  80. cyhal_sdhc_config_t sdhc_config; /**< Card configuration structure to be passed to the HAL driver. */
  81. const struct _cy_sdio_pin_config *pins_cfg;
  82. struct dfs_partition part;
  83. struct rt_device_blk_geometry geometry;
  84. };
  85. static rt_err_t rt_mmcsd_init(rt_device_t dev)
  86. {
  87. return RT_EOK;
  88. }
  89. static rt_err_t rt_mmcsd_open(rt_device_t dev, rt_uint16_t oflag)
  90. {
  91. return RT_EOK;
  92. }
  93. static rt_err_t rt_mmcsd_close(rt_device_t dev)
  94. {
  95. return RT_EOK;
  96. }
  97. static rt_err_t rt_mmcsd_control(rt_device_t dev, int cmd, void *args)
  98. {
  99. struct rthw_sdio *sdio = (struct rthw_sdio *)dev;
  100. struct dfs_partition *part = &sdio->part;
  101. struct rt_device_blk_geometry *geometry = &sdio->geometry;
  102. struct mmcsd_blk_device *blk_dev = (struct mmcsd_blk_device *)dev->user_data;
  103. switch (cmd)
  104. {
  105. case RT_DEVICE_CTRL_BLK_GETGEOME:
  106. rt_memcpy(args, geometry, sizeof(struct rt_device_blk_geometry));
  107. break;
  108. case RT_DEVICE_CTRL_BLK_PARTITION:
  109. rt_memcpy(args, part, sizeof(struct dfs_partition));
  110. default:
  111. break;
  112. }
  113. return RT_EOK;
  114. }
  115. static rt_ssize_t rt_mmcsd_read(rt_device_t dev,
  116. rt_off_t pos,
  117. void *buffer,
  118. rt_size_t size)
  119. {
  120. rt_err_t err = 0;
  121. void *rd_ptr = (void *)buffer;
  122. struct rthw_sdio *sdio = (struct rthw_sdio *)dev;
  123. cyhal_sdhc_t *hw_sdio = &sdio->sdhc_obj;
  124. off_t offset = sdio->part.offset;
  125. LOG_D("mmc read: off:%d pos:%d size:%d", offset, pos, size);
  126. if (dev == RT_NULL)
  127. {
  128. rt_set_errno(-RT_EINVAL);
  129. return 0;
  130. }
  131. rt_sem_take(sdio->part.lock, RT_WAITING_FOREVER);
  132. do {
  133. size_t block_count = size;
  134. uint32_t addr = (offset + pos);
  135. cy_rslt_t result = cyhal_sdhc_read_async(hw_sdio, addr, buffer, &block_count);
  136. if(CY_RSLT_SUCCESS != result)
  137. {
  138. err = -RT_ERROR;
  139. break;
  140. }
  141. /* Waits on a semaphore until the transfer completes, when RTOS_AWARE component is defined. */
  142. result = cyhal_sdhc_wait_transfer_complete(hw_sdio);
  143. if(CY_RSLT_SUCCESS != result)
  144. {
  145. err = -RT_ERROR;
  146. break;
  147. }
  148. }while(0);
  149. rt_sem_release(sdio->part.lock);
  150. /* the length of reading must align to SECTOR SIZE */
  151. if (err)
  152. {
  153. rt_set_errno(-RT_EIO);
  154. return 0;
  155. }
  156. return size;
  157. }
  158. static rt_ssize_t rt_mmcsd_write(rt_device_t dev,
  159. rt_off_t pos,
  160. const void *buffer,
  161. rt_size_t size)
  162. {
  163. rt_err_t err = 0;
  164. void *rd_ptr = (void *)buffer;
  165. struct rthw_sdio *sdio = (struct rthw_sdio *)dev;
  166. cyhal_sdhc_t *hw_sdio = &sdio->sdhc_obj;
  167. off_t offset = sdio->part.offset;
  168. LOG_D("mmc write: off:%d pos:%d size:%d", offset, pos, size);
  169. if (dev == RT_NULL)
  170. {
  171. rt_set_errno(-RT_EINVAL);
  172. return 0;
  173. }
  174. rt_sem_take(sdio->part.lock, RT_WAITING_FOREVER);
  175. do {
  176. size_t block_count = size ;
  177. uint32_t addr = (offset + pos);
  178. cy_rslt_t result = cyhal_sdhc_write_async(hw_sdio, addr, buffer, &block_count);
  179. if(CY_RSLT_SUCCESS != result)
  180. {
  181. err = -RT_ERROR;
  182. break;
  183. }
  184. /* Waits on a semaphore until the transfer completes, when RTOS_AWARE component is defined. */
  185. result = cyhal_sdhc_wait_transfer_complete(hw_sdio);
  186. if(CY_RSLT_SUCCESS != result)
  187. {
  188. err = -RT_ERROR;
  189. break;
  190. }
  191. }while(0);
  192. rt_sem_release(sdio->part.lock);
  193. /* the length of reading must align to SECTOR SIZE */
  194. if (err)
  195. {
  196. rt_set_errno(-RT_EIO);
  197. return 0;
  198. }
  199. return size;
  200. }
  201. #ifdef RT_USING_DEVICE_OPS
  202. const static struct rt_device_ops mmcsd_blk_ops =
  203. {
  204. rt_mmcsd_init,
  205. rt_mmcsd_open,
  206. rt_mmcsd_close,
  207. rt_mmcsd_read,
  208. rt_mmcsd_write,
  209. rt_mmcsd_control
  210. };
  211. #endif
  212. int rt_hw_sdio_init(void)
  213. {
  214. struct rthw_sdio *sdio = RT_NULL;
  215. struct _cy_sdio_pin_config *pins_cfg;
  216. char sname[16];
  217. sdio = rt_malloc(sizeof(struct rthw_sdio));
  218. if (sdio == RT_NULL)
  219. {
  220. LOG_E("malloc rthw_sdio fail");
  221. return RT_NULL;
  222. }
  223. rt_memset(sdio, 0, sizeof(struct rthw_sdio));
  224. LOG_D("sdio pins: cmd=%d,clk=%d,d0=%d,d1=%d,d2=%d,d3=%d,d4=%d,d5=%d,d6=%d,d7=%d",
  225. _sdio1_pins_and_name.cmd, _sdio1_pins_and_name.clk,
  226. _sdio1_pins_and_name.data0, _sdio1_pins_and_name.data1, _sdio1_pins_and_name.data2, _sdio1_pins_and_name.data3,
  227. _sdio1_pins_and_name.data4, _sdio1_pins_and_name.data5, _sdio1_pins_and_name.data6, _sdio1_pins_and_name.data7
  228. );
  229. LOG_D("\tdetect=%d,volt_sel=%d,pwr_en=%d,write_prot=%d,led_ctrl=%d,emmc_reset=%d",
  230. _sdio1_pins_and_name.card_detect, _sdio1_pins_and_name.io_volt_sel, _sdio1_pins_and_name.card_if_pwr_en,
  231. _sdio1_pins_and_name.card_mech_write_prot, _sdio1_pins_and_name.led_ctrl, _sdio1_pins_and_name.card_emmc_reset
  232. );
  233. /* register mmcsd device */
  234. sdio->parent.type = RT_Device_Class_Block;
  235. #ifdef RT_USING_DEVICE_OPS
  236. sdio->parent.ops = &mmcsd_blk_ops;
  237. #else
  238. sdio->parent.init = rt_mmcsd_init;
  239. sdio->parent.open = rt_mmcsd_open;
  240. sdio->parent.close = rt_mmcsd_close;
  241. sdio->parent.read = rt_mmcsd_read;
  242. sdio->parent.write = rt_mmcsd_write;
  243. sdio->parent.control = rt_mmcsd_control;
  244. #endif
  245. do {
  246. sdio->sdhc_config.enableLedControl = SDCARD_LED_CTRL_ENABLE;
  247. sdio->sdhc_config.isEmmc = SDCARD_EMMC_ENABLE;
  248. sdio->sdhc_config.lowVoltageSignaling = false;
  249. sdio->sdhc_config.busWidth = BSP_USING_SDCARD_BUS_WIDTH;
  250. /* Initialize the SD Card interface. */
  251. int rslt = cyhal_sdhc_init_hw(&sdio->sdhc_obj, &sdio->sdhc_config, _sdcard_config.cmd, _sdcard_config.clk,
  252. _sdcard_config.data0, _sdcard_config.data1, _sdcard_config.data2, _sdcard_config.data3,
  253. _sdcard_config.data4, _sdcard_config.data5, _sdcard_config.data6, _sdcard_config.data7,
  254. _sdcard_config.card_detect, _sdcard_config.io_volt_sel, _sdcard_config.card_if_pwr_en,
  255. _sdcard_config.card_mech_write_prot, _sdcard_config.led_ctrl, _sdcard_config.card_emmc_reset, RT_NULL);
  256. if(rslt != CY_RSLT_SUCCESS)
  257. {
  258. LOG_E("sdhc hw init fail: (0x%x)", rslt);
  259. break;
  260. }
  261. rslt = cyhal_sdhc_init_card(&sdio->sdhc_obj);
  262. if(rslt != CY_RSLT_SUCCESS)
  263. {
  264. LOG_E("sdhc init fail: (0x%x)", rslt);
  265. break;
  266. }
  267. rt_uint32_t block_count;
  268. rslt = cyhal_sdhc_get_block_count(&sdio->sdhc_obj, &block_count);
  269. if(rslt != CY_RSLT_SUCCESS)
  270. {
  271. LOG_E("get block count fail: (0x%x)", rslt);
  272. break;
  273. }
  274. LOG_D("block count:%d(0x%x)", block_count, block_count);
  275. sdio->geometry.bytes_per_sector = 512;
  276. sdio->geometry.block_size = 512;
  277. sdio->geometry.sector_count = block_count;
  278. rt_snprintf(sname, sizeof(sname) - 1, "sem_%s%d", _sdcard_config.name, 0);
  279. sdio->part.lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO);
  280. if(sdio->part.lock == RT_NULL)
  281. {
  282. LOG_E("create part.lock fail");
  283. break;
  284. }
  285. rt_uint8_t *sector = rt_malloc(512);
  286. if(sector == RT_NULL)
  287. {
  288. LOG_E("malloc sector fail");
  289. break;
  290. }
  291. if(rt_mmcsd_read(&sdio->parent, 0, sector, 1) < 0)
  292. {
  293. LOG_E("rt_mmcsd_read fail");
  294. rt_free(sector);
  295. break;
  296. }
  297. rslt = dfs_filesystem_get_partition(&sdio->part, sector, 0);
  298. rt_free(sector);
  299. if(rslt != RT_EOK)
  300. {
  301. LOG_E("partition not found!");
  302. break;
  303. }
  304. rslt = rt_device_register(&(sdio->parent), _sdcard_config.name,
  305. RT_DEVICE_FLAG_RDWR);
  306. if(rslt != RT_EOK)
  307. {
  308. LOG_E("register device fail!");
  309. break;
  310. }
  311. return RT_EOK;
  312. }while(0);
  313. if(sdio)
  314. {
  315. cyhal_sdhc_free(&sdio->sdhc_obj);
  316. if(sdio->part.lock)
  317. {
  318. rt_sem_delete(sdio->part.lock);
  319. }
  320. rt_free(sdio);
  321. }
  322. return -RT_ERROR;
  323. }
  324. INIT_DEVICE_EXPORT(rt_hw_sdio_init);
  325. #endif