drv_spi.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. /*
  2.  * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
  3.  *
  4.  * SPDX-License-Identifier: Apache-2.0.
  5.  *
  6. * @Date: 2021-04-25 14:01:29
  7. * @LastEditTime: 2021-05-26 15:42:52
  8. * @Description:  This files is for
  9. *
  10. * @Modify History:
  11. * Ver   Who        Date         Changes
  12. * ----- ------     --------    --------------------------------------
  13. */
  14. #include "drv_spi.h"
  15. #include <rtthread.h>
  16. #include <rtdevice.h>
  17. #include <string.h>
  18. #include "ft_spi.h"
  19. #include "ft_mux.h"
  20. #include "ft_trace.h"
  21. #include "ft_generic_timer.h"
  22. #ifdef BSP_USE_SPI
  23. #define DRV_DEBUG
  24. #define LOG_TAG "drv.spi"
  25. #include <drv_log.h>
  26. typedef void (*spi_cs_handler_t)(const rt_bool_t select);
  27. typedef struct
  28. {
  29. FSpi_Ctrl_t spi_ctrl;
  30. struct rt_spi_bus spi_bus;
  31. rt_uint16_t spi_cs_pin;
  32. spi_cs_handler_t spi_cs_handler;
  33. } ft2004_spi_class;
  34. void ft2004_spi_cs(const rt_bool_t select);
  35. static ft2004_spi_class spi_obj = {
  36. .spi_cs_handler = ft2004_spi_cs,
  37. .spi_ctrl = {
  38. .CtrlId = SPI_CTRL_ID_0,
  39. .DevId = SPI_DEV_ID_0,
  40. .IsReady = FALSE,
  41. .CsPin = 5, /* use pin 5 in gpio group a as cs signal pin */
  42. },
  43. };
  44. static const FSpi_Conf_t spi_conf[NUM_OF_SPI_CTRL] =
  45. {
  46. {
  47. .DevAddr = {0x00, 0x00, 0x00, 0x00},
  48. .DevAddrLen = SPI_4_BYTE_ADDR,
  49. .WorkMode = SPI_CTRL_MASTER_MODE,
  50. /* mode 2 CPOL = 1, CPHA = 0 */
  51. .Cpol = SPI_CTRL_CPOL_HIGH,
  52. .Cpha = SPI_CTRL_CPHA_1EDGE,
  53. .BaudRDiv = SPI_SCKDV_4,
  54. },
  55. {
  56. .DevAddr = {0x00, 0x00, 0x00, 0x00},
  57. .DevAddrLen = SPI_4_BYTE_ADDR,
  58. .WorkMode = SPI_CTRL_MASTER_MODE,
  59. .Cpol = SPI_CTRL_CPOL_HIGH,
  60. .Cpha = SPI_CTRL_CPHA_1EDGE,
  61. .BaudRDiv = SPI_SCKDV_MAX,
  62. }};
  63. inline static ft2004_spi_class *ft2004_spi_get_class()
  64. {
  65. return &spi_obj;
  66. }
  67. inline static FSpi_Ctrl_t *ft2004_spi_get_ctrl()
  68. {
  69. return &(ft2004_spi_get_class()->spi_ctrl);
  70. }
  71. static const FSpi_Conf_t *ft2004_lookup_conf(FT_IN FSpi_CtrlId_t CtrlId)
  72. {
  73. return &spi_conf[CtrlId];
  74. }
  75. void ft2004_spi_cs(const rt_bool_t select)
  76. {
  77. FSpi_Ctrl_t *ctrl_p = ft2004_spi_get_ctrl();
  78. FSpi_SelectSlave(ctrl_p, ctrl_p->DevId, (bool_t)select);
  79. }
  80. /**spi flash operations***/
  81. u32 ft2004_spi_transcation(const u8 tx_data, u8 *rx_data_p)
  82. {
  83. FSpi_Ctrl_t *ctrl_p = ft2004_spi_get_ctrl();
  84. u32 ret = ERR_SPI_OK;
  85. ret = FSpi_ReadWriteByte(ctrl_p, tx_data, rx_data_p);
  86. return ret;
  87. }
  88. /**spi flash operations***/
  89. static rt_err_t ft2004_spi_init(struct rt_spi_configuration *cfg)
  90. {
  91. FSpi_Ctrl_t *ctrl_p = ft2004_spi_get_ctrl();
  92. FSpi_DevId_t dev_id;
  93. u32 ret = ERR_SPI_OK;
  94. //RT_ASSERT(cfg != RT_NULL);
  95. RT_ASSERT(ctrl_p != RT_NULL);
  96. dev_id = ctrl_p->DevId;
  97. /* get spi flash default config */
  98. ctrl_p->Config = *(ft2004_lookup_conf(dev_id));
  99. /* change config according to inputs, cfg could be RT_NULL */
  100. /* reset ctrl block */
  101. ctrl_p->IsReady = FALSE;
  102. /* set spi pin mux */
  103. Ft_setSpiMux(ctrl_p->CtrlId);
  104. /* init spi ctrl */
  105. ret = FSpi_Init(ctrl_p);
  106. if (ERR_SPI_OK == ret)
  107. {
  108. return RT_EOK;
  109. }
  110. else
  111. {
  112. return -RT_ERROR;
  113. }
  114. }
  115. static rt_uint32_t spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
  116. {
  117. rt_size_t message_length, loop;
  118. rt_uint8_t *recv_buf;
  119. const rt_uint8_t *send_buf;
  120. u32 tx_rx_result = ERR_SPI_OK;
  121. spi_cs_handler_t cs_handler = ft2004_spi_get_class()->spi_cs_handler;
  122. RT_ASSERT(device != RT_NULL);
  123. RT_ASSERT(device->bus != RT_NULL);
  124. RT_ASSERT(device->bus->parent.user_data != RT_NULL);
  125. RT_ASSERT(message != RT_NULL);
  126. if (message->cs_take && cs_handler)
  127. {
  128. cs_handler(TRUE);
  129. }
  130. message_length = message->length;
  131. recv_buf = message->recv_buf;
  132. send_buf = message->send_buf;
  133. /* handle msg */
  134. for (loop = 0; loop < message_length; loop++)
  135. {
  136. /* start data exchange */
  137. if ((message->recv_buf) && (message->send_buf))
  138. {
  139. /* need tx and rx */
  140. tx_rx_result |= ft2004_spi_transcation(*send_buf, recv_buf);
  141. send_buf++;
  142. recv_buf++;
  143. }
  144. else if (message->send_buf)
  145. {
  146. /* tx only */
  147. tx_rx_result |= ft2004_spi_transcation(*send_buf, RT_NULL);
  148. send_buf++;
  149. }
  150. else
  151. {
  152. /* rx only */
  153. tx_rx_result |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, recv_buf);
  154. recv_buf++;
  155. }
  156. }
  157. if (ERR_SPI_OK != tx_rx_result)
  158. {
  159. LOG_E("spi transfer error : 0x%x", tx_rx_result);
  160. message->length = 0;
  161. }
  162. else
  163. {
  164. }
  165. if (message->cs_release && cs_handler)
  166. {
  167. cs_handler(FALSE);
  168. }
  169. return message->length;
  170. }
  171. static rt_err_t spi_configure(struct rt_spi_device *device,
  172. struct rt_spi_configuration *configuration)
  173. {
  174. RT_ASSERT(device != RT_NULL);
  175. RT_ASSERT(configuration != RT_NULL);
  176. return ft2004_spi_init(configuration);
  177. }
  178. static const struct rt_spi_ops ft2004_spi_ops =
  179. {
  180. .configure = spi_configure,
  181. .xfer = spi_xfer,
  182. };
  183. /**
  184. * Attach the spi device to SPI bus, this function must be used after initialization.
  185. */
  186. rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint16_t cs_gpio_pin)
  187. {
  188. rt_err_t result;
  189. struct rt_spi_device *spi_device;
  190. ft2004_spi_class *spi_class = ft2004_spi_get_class();
  191. RT_ASSERT(spi_class != RT_NULL);
  192. spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
  193. RT_ASSERT(spi_device != RT_NULL);
  194. result = rt_spi_bus_attach_device(spi_device, device_name, bus_name, RT_NULL);
  195. LOG_I("attach result 0x%x", result);
  196. if (result != RT_EOK)
  197. {
  198. if (spi_device)
  199. {
  200. rt_free(spi_device);
  201. }
  202. }
  203. return result;
  204. }
  205. static int rt_hw_spi_bus_init(void)
  206. {
  207. rt_err_t result;
  208. ft2004_spi_class *spi_class = ft2004_spi_get_class();
  209. LOG_I("init spi ctrl");
  210. spi_class->spi_bus.parent.user_data = &spi_class->spi_bus;
  211. result = rt_spi_bus_register(&spi_class->spi_bus, SPI_BUS_NAME, &ft2004_spi_ops);
  212. return result;
  213. }
  214. int rt_hw_spi_init(void)
  215. {
  216. return rt_hw_spi_bus_init();
  217. }
  218. INIT_BOARD_EXPORT(rt_hw_spi_init);
  219. static void rthw_spi_delay(u32 delayCnt)
  220. {
  221. Ft_GenericTimer_UsDelay(delayCnt);
  222. }
  223. /************spi flash operatiosn implemented for sample test****************/
  224. /* definition of s25fs maunfactor id */
  225. typedef struct
  226. {
  227. u8 Mid;
  228. u8 MemoryType;
  229. u8 Density;
  230. u8 RemainBytes;
  231. u8 PhySectArch;
  232. u8 FamilyID;
  233. } ft2004_manuid_t;
  234. /* definition of cmd for s25fs */
  235. #define S25FS_ENABLE_WR 0x06
  236. #define S25FS_DISABLE_WR 0x04
  237. #define S25FS_READ_ID 0x9F
  238. #define S25FS_READ_4BYTE_ADD 0x13
  239. #define S25FS_ERASE_4BYTE_ADD 0x21
  240. #define S25FS_READ_STATUS_1 0x05
  241. #define S25FS_READ_FLASH_PARAM 0x5A
  242. static void ft2004_dump_manuid(const ft2004_manuid_t *pId)
  243. {
  244. rt_kprintf("0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\r\n",
  245. pId->Mid, pId->MemoryType, pId->Density, pId->RemainBytes,
  246. pId->PhySectArch, pId->FamilyID);
  247. }
  248. static u32 ft2004_read_in_4byte_addr(const u32 ReadAddr, const u32 BytesToRead, u8 *pBuf)
  249. {
  250. u32 ret = ERR_SPI_OK;
  251. u32 loop;
  252. RT_ASSERT(RT_NULL != pBuf);
  253. ft2004_spi_cs(TRUE);
  254. ret |= ft2004_spi_transcation(S25FS_READ_4BYTE_ADD, RT_NULL);
  255. /* only 4-bytes address, MSB first */
  256. ret |= ft2004_spi_transcation((u8)(ReadAddr >> 24), RT_NULL);
  257. ret |= ft2004_spi_transcation((u8)(ReadAddr >> 16), RT_NULL);
  258. ret |= ft2004_spi_transcation((u8)(ReadAddr >> 8), RT_NULL);
  259. ret |= ft2004_spi_transcation((u8)ReadAddr, RT_NULL);
  260. /* read out data */
  261. for (loop = 0; loop < BytesToRead; loop++)
  262. {
  263. ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, pBuf + loop);
  264. if (ERR_SPI_OK != ret)
  265. {
  266. break;
  267. }
  268. }
  269. ft2004_spi_cs(FALSE);
  270. return ret;
  271. }
  272. u32 ft2004_spi_enable_wr(const bool_t enable)
  273. {
  274. u32 ret = ERR_SPI_OK;
  275. ft2004_spi_cs(TRUE);
  276. if (enable)
  277. {
  278. ret |= ft2004_spi_transcation(S25FS_ENABLE_WR, RT_NULL);
  279. }
  280. else
  281. {
  282. ret |= ft2004_spi_transcation(S25FS_DISABLE_WR, RT_NULL);
  283. }
  284. ft2004_spi_cs(FALSE);
  285. return ret;
  286. }
  287. u32 ft2004_erase_sector_in_4byte_addr(const u32 sector_addr)
  288. {
  289. u32 Ret = ERR_SPI_OK;
  290. ft2004_spi_enable_wr(TRUE);
  291. LOG_I("erase sector 0x%x", Ret);
  292. if (ERR_SPI_OK != Ret)
  293. {
  294. return Ret;
  295. }
  296. ft2004_spi_cs(TRUE);
  297. Ret |= ft2004_spi_transcation(S25FS_ERASE_4BYTE_ADD, RT_NULL);
  298. Ret |= ft2004_spi_transcation((u8)(sector_addr >> 24), RT_NULL);
  299. Ret |= ft2004_spi_transcation((u8)(sector_addr >> 16), RT_NULL);
  300. Ret |= ft2004_spi_transcation((u8)(sector_addr >> 8), RT_NULL);
  301. Ret |= ft2004_spi_transcation((u8)(sector_addr), RT_NULL);
  302. ft2004_spi_cs(FALSE);
  303. return Ret;
  304. }
  305. u32 ft2004_spi_read_params(const u32 Addr)
  306. {
  307. u32 Ret = ERR_SPI_OK;
  308. u8 dat[8] = {0};
  309. u32 loop;
  310. ft2004_spi_cs(TRUE);
  311. Ret |= ft2004_spi_transcation(S25FS_READ_FLASH_PARAM, RT_NULL);
  312. Ret |= ft2004_spi_transcation((u8)(Addr >> 16), RT_NULL);
  313. Ret |= ft2004_spi_transcation((u8)(Addr >> 8), RT_NULL);
  314. Ret |= ft2004_spi_transcation((u8)(Addr), RT_NULL);
  315. for (loop = 0; loop < 8; loop++)
  316. {
  317. Ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, dat + loop);
  318. rt_kprintf("%d: 0x%x", loop, *(dat + loop));
  319. }
  320. ft2004_spi_cs(FALSE);
  321. return Ret;
  322. }
  323. static u32 ft2004_spi_readid_for_test(ft2004_manuid_t *pId)
  324. {
  325. FSpi_Ctrl_t *ctrl_p = ft2004_spi_get_ctrl();
  326. u32 ret = ERR_SPI_OK;
  327. if (!ctrl_p->IsReady)
  328. {
  329. return ERR_SPI_NOT_READY;
  330. }
  331. RT_ASSERT(RT_NULL != pId);
  332. ft2004_spi_cs(TRUE);
  333. /* shifting the command code “90H” followed by a 24-bit address */
  334. ret |= ft2004_spi_transcation(S25FS_READ_ID, RT_NULL);
  335. /* Manufacturer ID and the Device ID are shifted out */
  336. ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->Mid);
  337. ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->MemoryType);
  338. ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->Density);
  339. ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->RemainBytes);
  340. ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->PhySectArch);
  341. ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->FamilyID);
  342. ft2004_spi_cs(FALSE);
  343. if (ERR_SPI_OK == ret)
  344. {
  345. ft2004_dump_manuid(pId);
  346. }
  347. return ret;
  348. }
  349. static void spi_9f_s25fs_sample(int argc, char *argv[])
  350. {
  351. ft2004_manuid_t dev_id;
  352. u32 ret = ERR_SPI_OK;
  353. u32 delay = SPI_TIMEOUT * 10;
  354. rt_kprintf("test s25fs spi flash\r\n");
  355. ret |= ft2004_spi_init(RT_NULL);
  356. ret |= ft2004_spi_readid_for_test(&dev_id);
  357. rt_kprintf("result is: 0x%x \r\n", ret);
  358. while (--delay)
  359. {
  360. rthw_spi_delay(10);
  361. }
  362. }
  363. MSH_CMD_EXPORT(spi_9f_s25fs_sample, "spi s25fs cmd 9fH sample");
  364. static u8 read_buf[256];
  365. static void spi_5a_s25fs_sample(int argc, char *argv[])
  366. {
  367. u32 ret = ERR_SPI_OK;
  368. u32 delay = SPI_TIMEOUT * 10;
  369. u32 read_addr = 0x0000;
  370. rt_kprintf("test s25fs spi flash\r\n");
  371. ret |= ft2004_spi_init(RT_NULL);
  372. ret |= ft2004_spi_read_params(read_addr);
  373. ret |= ft2004_read_in_4byte_addr(read_addr, 256, read_buf);
  374. rt_kprintf("result is: 0x%x \r\n", ret);
  375. while (--delay)
  376. {
  377. rthw_spi_delay(10);
  378. }
  379. }
  380. MSH_CMD_EXPORT(spi_5a_s25fs_sample, "spi s25fs cmd 5aH sample");
  381. #endif