spi.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. #undef LOG_TAG_CONST
  2. #define LOG_TAG "[SPI]"
  3. #define LOG_ERROR_ENABLE
  4. //#define LOG_DEBUG_ENABLE
  5. #include "system/debug.h"
  6. #include "generic/gpio.h"
  7. #include "asm/clock.h"
  8. #include "asm/spi.h"
  9. #define spi_enable(reg) ((reg)->CON |= BIT(0))
  10. #define spi_disable(reg) ((reg)->CON &= ~BIT(0))
  11. #define spi_role_slave(reg) ((reg)->CON |= BIT(1))
  12. #define spi_role_master(reg) ((reg)->CON &= ~BIT(1))
  13. #define spi_cs_en(reg) ((reg)->CON |= BIT(2))
  14. #define spi_cs_dis(reg) ((reg)->CON &= ~BIT(2))
  15. #define spi_bidir(reg) ((reg)->CON |= BIT(3))
  16. #define spi_unidir(reg) ((reg)->CON &= ~BIT(3))
  17. #define spi_smp_edge_rise(reg) ((reg)->CON &= ~BIT(4))
  18. #define spi_smp_edge_fall(reg) ((reg)->CON |= BIT(4))
  19. #define spi_ud_edge_rise(reg) ((reg)->CON &= ~BIT(5))
  20. #define spi_ud_edge_fall(reg) ((reg)->CON |= BIT(5))
  21. #define spi_clk_idle_h(reg) ((reg)->CON |= BIT(6))
  22. #define spi_clk_idle_l(reg) ((reg)->CON &= ~BIT(6))
  23. #define spi_cs_idle_h(reg) ((reg)->CON |= BIT(7))
  24. #define spi_cs_idle_l(reg) ((reg)->CON &= ~BIT(7))
  25. #define spi_data_width(reg, x) ((reg)->CON = (reg->CON&~(3<<10))|((x)<<10))
  26. #define spi_dir_in(reg) ((reg)->CON |= BIT(12))
  27. #define spi_dir_out(reg) ((reg)->CON &= ~BIT(12))
  28. #define spi_ie_en(reg) ((reg)->CON |= BIT(13))
  29. #define spi_ie_dis(reg) ((reg)->CON &= ~BIT(13))
  30. #define spi_clr_pnd(reg) ((reg)->CON |= BIT(14))
  31. #define spi_pnd(reg) ((reg)->CON & BIT(15))
  32. #define spi_w_reg_con(reg, val) ((reg)->CON = (val))
  33. #define spi_r_reg_con(reg) ((reg)->CON)
  34. #define spi_w_reg_buf(reg, val) ((reg)->BUF = (val))
  35. #define spi_r_reg_buf(reg) ((reg)->BUF)
  36. #define spi_w_reg_baud(reg, baud) ((reg)->BAUD = (baud))
  37. #define spi_r_reg_baud(reg) ((reg)->BAUD)
  38. #define spi_w_reg_dma_addr(reg, addr) ((reg)->ADR = (addr))
  39. #define spi_w_reg_dma_cnt(reg, cnt) ((reg)->CNT = (cnt))
  40. #define SPI1_ENABLE 1 //是否使能SPI1,使能后需定义spi1_p_data
  41. #define SPI2_ENABLE 1 //是否使能SPI2,使能后需定义spi2_p_data
  42. static JL_SPI_TypeDef *const spi_regs[SPI_MAX_HW_NUM] = {
  43. NULL,
  44. JL_SPI1,
  45. JL_SPI2,
  46. };
  47. static u8 spi_get_info_id(spi_dev spi)
  48. {
  49. ASSERT(spi < SPI_MAX_HW_NUM);
  50. return spi;
  51. }
  52. static u8 *spi_get_info_port(spi_dev spi)
  53. {
  54. u8 *port = NULL;
  55. u8 id = spi_get_info_id(spi);
  56. switch (id) {
  57. #if SPI1_ENABLE
  58. case SPI1:
  59. port = (u8 *)spi1_p_data.port;
  60. break;
  61. #endif
  62. #if SPI2_ENABLE
  63. case SPI2:
  64. port = (u8 *)spi2_p_data.port;
  65. break;
  66. #endif
  67. default:
  68. break;
  69. }
  70. return port;
  71. }
  72. static u8 spi_get_info_mode(spi_dev spi)
  73. {
  74. u8 mode = (u8) - 1;
  75. u8 id = spi_get_info_id(spi);
  76. switch (id) {
  77. #if SPI1_ENABLE
  78. case SPI1:
  79. mode = spi1_p_data.mode;
  80. break;
  81. #endif
  82. #if SPI2_ENABLE
  83. case SPI2:
  84. mode = spi2_p_data.mode;
  85. break;
  86. #endif
  87. default:
  88. break;
  89. }
  90. return mode;
  91. }
  92. static u8 spi_get_info_role(spi_dev spi)
  93. {
  94. u8 role = (u8) - 1;
  95. u8 id = spi_get_info_id(spi);
  96. switch (id) {
  97. #if SPI1_ENABLE
  98. case SPI1:
  99. role = spi1_p_data.role;
  100. break;
  101. #endif
  102. #if SPI2_ENABLE
  103. case SPI2:
  104. role = spi2_p_data.role;
  105. break;
  106. #endif
  107. default:
  108. break;
  109. }
  110. return role;
  111. }
  112. static u32 spi_get_info_clock(spi_dev spi)
  113. {
  114. u32 clock = (u8) - 1;
  115. u8 id = spi_get_info_id(spi);
  116. switch (id) {
  117. #if SPI1_ENABLE
  118. case SPI1:
  119. clock = spi1_p_data.clk;
  120. break;
  121. #endif
  122. #if SPI2_ENABLE
  123. case SPI2:
  124. clock = spi2_p_data.clk;
  125. break;
  126. #endif
  127. default:
  128. break;
  129. }
  130. return clock;
  131. }
  132. static void spi1_iomc_config(spi_dev spi)
  133. {
  134. u8 *port = spi_get_info_port(spi);
  135. gpio_set_fun_output_port(port[0], FO_SPI1_CLK, 1, 1);
  136. gpio_set_fun_output_port(port[1], FO_SPI1_DA0, 1, 1);
  137. gpio_set_fun_output_port(port[2], FO_SPI1_DA1, 1, 1);
  138. gpio_set_fun_input_port(port[0], PFI_SPI1_CLK);
  139. gpio_set_fun_input_port(port[1], PFI_SPI1_DA0);
  140. gpio_set_fun_input_port(port[2], PFI_SPI1_DA1);
  141. gpio_set_fun_input_port(port[3], PFI_SPI1_DA2);
  142. gpio_set_fun_input_port(port[4], PFI_SPI1_DA3);
  143. }
  144. static void spi2_iomc_config(spi_dev spi)
  145. {
  146. u8 *port = spi_get_info_port(spi);
  147. gpio_set_fun_output_port(port[0], FO_SPI2_CLK, 1, 1);
  148. gpio_set_fun_output_port(port[1], FO_SPI2_DA0, 1, 1);
  149. gpio_set_fun_output_port(port[2], FO_SPI2_DA1, 1, 1);
  150. gpio_set_fun_input_port(port[0], PFI_SPI2_CLK);
  151. gpio_set_fun_input_port(port[1], PFI_SPI2_DA0);
  152. gpio_set_fun_input_port(port[2], PFI_SPI2_DA1);
  153. gpio_set_fun_input_port(port[3], PFI_SPI2_DA2);
  154. gpio_set_fun_input_port(port[4], PFI_SPI2_DA3);
  155. }
  156. static void (*pSPI_IOMC_CONFIG[])(spi_dev spi) = {
  157. NULL,
  158. spi1_iomc_config,
  159. spi2_iomc_config,
  160. };
  161. static void spi_io_port_init(u8 port, u8 dir)
  162. {
  163. if (port != (u8) - 1) {
  164. if (dir == 1) {
  165. gpio_set_direction(port, 1);
  166. } else {
  167. gpio_set_direction(port, 0);
  168. }
  169. gpio_set_die(port, 1);
  170. gpio_set_pull_up(port, 0);
  171. gpio_set_pull_down(port, 0);
  172. }
  173. }
  174. static void spi_io_port_uninit(u8 port)
  175. {
  176. if (port != (u8) - 1) {
  177. gpio_set_direction(port, 1);
  178. gpio_set_die(port, 0);
  179. gpio_set_pull_up(port, 0);
  180. gpio_set_pull_down(port, 0);
  181. }
  182. }
  183. /*
  184. * @brief 设置波特率
  185. * @parm spi spi句柄
  186. * @parm baud 波特率
  187. * @return 0 成功,< 0 失败
  188. */
  189. int spi_set_baud(spi_dev spi, u32 baud)
  190. {
  191. //SPICK = sysclk / (SPIx_BAUD + 1)
  192. //=> SPIx_BAUD = sysclk / SPICK - 1
  193. u8 id = spi_get_info_id(spi);
  194. u32 sysclk;
  195. sysclk = clk_get("spi");
  196. log_debug("spi clock source freq %lu", sysclk);
  197. if (sysclk < baud) {
  198. spi_w_reg_baud(spi_regs[id], 0);
  199. return -EINVAL;
  200. }
  201. spi_w_reg_baud(spi_regs[id], sysclk / baud - 1);
  202. return 0;
  203. }
  204. /*
  205. * @brief 获取波特率
  206. * @parm spi spi句柄
  207. * @return 波特率
  208. */
  209. u32 spi_get_baud(spi_dev spi)
  210. {
  211. u8 id = spi_get_info_id(spi);
  212. return spi_get_info_clock(spi);
  213. }
  214. static int __spi_wait_ok(spi_dev spi, u32 n)
  215. {
  216. u8 id = spi_get_info_id(spi);
  217. u32 baud = spi_get_info_clock(spi);
  218. baud = clk_get("spi") / baud - 1;
  219. u32 retry = baud * (clk_get("sys") / clk_get("spi")) * 8 * n * 5; //500% spi baudate
  220. while (!spi_pnd(spi_regs[id])) {
  221. __asm__ volatile("nop");
  222. if (--retry == 0) {
  223. log_error("spi wait pnd timeout");
  224. return -EFAULT;
  225. }
  226. }
  227. spi_clr_pnd(spi_regs[id]);
  228. return 0;
  229. }
  230. /*
  231. * @brief 发送1个字节
  232. * @parm spi spi句柄
  233. * @parm byte 发送的字节
  234. * @return 0 成功,< 0 失败
  235. */
  236. int spi_send_byte(spi_dev spi, u8 byte)
  237. {
  238. u8 id = spi_get_info_id(spi);
  239. spi_dir_out(spi_regs[id]);
  240. spi_w_reg_buf(spi_regs[id], byte);
  241. return __spi_wait_ok(spi, 1);
  242. }
  243. /*
  244. * @brief 发送1个字节,不等待pnd,用于中断
  245. * @parm spi spi句柄
  246. * @parm byte 发送的字节
  247. * @return null
  248. */
  249. void spi_send_byte_for_isr(spi_dev spi, u8 byte)
  250. {
  251. u8 id = spi_get_info_id(spi);
  252. spi_dir_out(spi_regs[id]);
  253. spi_w_reg_buf(spi_regs[id], byte);
  254. }
  255. /*
  256. * @brief 接收1个字节
  257. * @parm spi spi句柄
  258. * @parm err 返回错误信息,若err为非空指针,0 成功,< 0 失败,若为空指针,忽略
  259. * @return 接收的字节
  260. */
  261. u8 spi_recv_byte(spi_dev spi, int *err)
  262. {
  263. u8 id = spi_get_info_id(spi);
  264. int ret;
  265. spi_dir_in(spi_regs[id]);
  266. spi_w_reg_buf(spi_regs[id], 0xff);
  267. ret = __spi_wait_ok(spi, 1);
  268. if (ret) {
  269. err != NULL ? *err = ret : 0;
  270. return 0;
  271. }
  272. err != NULL ? *err = 0 : 0;
  273. return spi_r_reg_buf(spi_regs[id]);
  274. }
  275. /*
  276. * @brief 接收1个字节,不等待pnd,用于中断
  277. * @parm spi spi句柄
  278. * @return 接收的字节
  279. */
  280. u8 spi_recv_byte_for_isr(spi_dev spi)
  281. {
  282. u8 id = spi_get_info_id(spi);
  283. spi_dir_in(spi_regs[id]);
  284. return spi_r_reg_buf(spi_regs[id]);
  285. }
  286. /*
  287. * @brief 发送并接收1个字节,在8个时钟内完成,仅使用于SPI_MODE_BIDIR_1BIT
  288. * @parm spi spi句柄
  289. * @parm byte 发送的字节
  290. * @parm err 返回错误信息,若err为非空指针,0 成功,< 0 失败,若为空指针,忽略
  291. * @return 接收的字节
  292. */
  293. u8 spi_send_recv_byte(spi_dev spi, u8 byte, int *err)
  294. {
  295. u8 id = spi_get_info_id(spi);
  296. int ret;
  297. spi_w_reg_buf(spi_regs[id], byte);
  298. ret = __spi_wait_ok(spi, 1);
  299. if (ret) {
  300. err != NULL ? *err = ret : 0;
  301. return 0;
  302. }
  303. err != NULL ? *err = 0 : 0;
  304. return spi_r_reg_buf(spi_regs[id]);
  305. }
  306. /*
  307. * @brief 设置spi[单向/双向,位数]模式
  308. * @parm spi spi句柄
  309. * @parm mode 模式
  310. * @return null
  311. */
  312. void spi_set_bit_mode(spi_dev spi, int mode)
  313. {
  314. u8 id = spi_get_info_id(spi);
  315. u8 *port = spi_get_info_port(spi);
  316. u8 role = spi_get_info_role(spi);
  317. switch (mode) {
  318. case SPI_MODE_BIDIR_1BIT:
  319. spi_bidir(spi_regs[id]);
  320. spi_data_width(spi_regs[id], 0);
  321. break;
  322. case SPI_MODE_UNIDIR_1BIT:
  323. spi_unidir(spi_regs[id]);
  324. spi_data_width(spi_regs[id], 0);
  325. break;
  326. case SPI_MODE_UNIDIR_2BIT:
  327. spi_unidir(spi_regs[id]);
  328. spi_data_width(spi_regs[id], 1);
  329. break;
  330. case SPI_MODE_UNIDIR_4BIT:
  331. spi_unidir(spi_regs[id]);
  332. spi_data_width(spi_regs[id], 2);
  333. break;
  334. }
  335. spi_io_port_init(port[0], role == SPI_ROLE_MASTER ? 0 : 1);
  336. spi_io_port_init(port[1], 0);
  337. if (mode == SPI_MODE_BIDIR_1BIT) {
  338. spi_io_port_init(port[2], 1);
  339. } else if (mode == SPI_MODE_UNIDIR_2BIT) {
  340. spi_io_port_init(port[2], 0);
  341. } else if (mode == SPI_MODE_UNIDIR_4BIT) {
  342. spi_io_port_init(port[2], 0);
  343. }
  344. }
  345. /*
  346. * @brief 打开spi
  347. * @parm spi spi句柄
  348. * @return 0 成功,< 0 失败
  349. */
  350. int spi_open(spi_dev spi)
  351. {
  352. int err;
  353. u8 id = spi_get_info_id(spi);
  354. u8 mode = spi_get_info_mode(spi);
  355. u8 role = spi_get_info_role(spi);
  356. u32 clock = spi_get_info_clock(spi);
  357. pSPI_IOMC_CONFIG[id](spi);
  358. spi_set_bit_mode(spi, mode);
  359. spi_cs_dis(spi_regs[id]);
  360. if (role == SPI_ROLE_MASTER) {
  361. spi_role_master(spi_regs[id]);
  362. } else if (role == SPI_ROLE_SLAVE) {
  363. spi_role_slave(spi_regs[id]);
  364. }
  365. spi_smp_edge_rise(spi_regs[id]);
  366. spi_ud_edge_fall(spi_regs[id]);
  367. spi_cs_idle_h(spi_regs[id]);
  368. spi_clk_idle_l(spi_regs[id]);
  369. spi_clr_pnd(spi_regs[id]);
  370. if ((err = spi_set_baud(spi, clock))) {
  371. log_error("invalid spi baudrate");
  372. /* return 0; */
  373. }
  374. spi_w_reg_buf(spi_regs[id], 0);//设定spi初始化后DO口默认电平为低
  375. spi_enable(spi_regs[id]);
  376. #if 0
  377. printf("spi%d clk = %d\n", id, clock);
  378. printf("spi%d mode = %d\n", id, mode);
  379. printf("spi%d role = %d\n", id, role);
  380. printf("spi%d clk_pin = %d\n", id, port[0]);
  381. printf("spi%d do_pin = %d\n", id, port[1]);
  382. printf("spi%d di_pin = %d\n", id, port[2]);
  383. printf("spi%d CON = %04x\n", id, spi_r_reg_con(spi_regs[id]));
  384. printf("spi%d IOMC1 = %08x\n", id, JL_IOMAP->CON1);
  385. #endif
  386. return 0;
  387. }
  388. /*
  389. * @brief spi dma接收
  390. * @parm spi spi句柄
  391. * @parm buf 接收缓冲区基地址
  392. * @parm len 期望接收长度
  393. * @return 实际接收长度,< 0表示失败
  394. */
  395. int spi_dma_recv(spi_dev spi, void *buf, u32 len)
  396. {
  397. u8 id = spi_get_info_id(spi);
  398. /* ASSERT((u32)buf % 4 == 0, "spi dma addr need 4-aligned"); */
  399. spi_dir_in(spi_regs[id]);
  400. spi_w_reg_dma_addr(spi_regs[id], (u32)buf);
  401. spi_w_reg_dma_cnt(spi_regs[id], len);
  402. asm("csync");
  403. if (__spi_wait_ok(spi, len)) {
  404. return -EFAULT;
  405. }
  406. return len;
  407. }
  408. /*
  409. * @brief spi dma发送
  410. * @parm spi spi句柄
  411. * @parm buf 发送缓冲区基地址
  412. * @parm len 期望发送长度
  413. * @return 实际发送长度,< 0表示失败
  414. */
  415. int spi_dma_send(spi_dev spi, const void *buf, u32 len)
  416. {
  417. u8 id = spi_get_info_id(spi);
  418. /* ASSERT((u32)buf % 4 == 0, "spi dma addr need 4-aligned"); */
  419. spi_dir_out(spi_regs[id]);
  420. spi_w_reg_dma_addr(spi_regs[id], (u32)buf);
  421. spi_w_reg_dma_cnt(spi_regs[id], len);
  422. asm("csync");
  423. if (__spi_wait_ok(spi, len)) {
  424. return -EFAULT;
  425. }
  426. return len;
  427. }
  428. /*
  429. * @brief spi 配置dma,不等待pnd,用于中断
  430. * @parm spi spi句柄
  431. * @parm buf 缓冲区基地址
  432. * @parm len 期望长度
  433. * @parm rw 1 接收 / 0 发送
  434. * @return null
  435. */
  436. void spi_dma_set_addr_for_isr(spi_dev spi, void *buf, u32 len, u8 rw)
  437. {
  438. u8 id = spi_get_info_id(spi);
  439. /* ASSERT((u32)buf % 4 == 0, "spi dma addr need 4-aligned"); */
  440. rw ? spi_dir_in(spi_regs[id]) : spi_dir_out(spi_regs[id]);
  441. spi_w_reg_dma_addr(spi_regs[id], (u32)buf);
  442. spi_w_reg_dma_cnt(spi_regs[id], len);
  443. }
  444. /*
  445. * @brief 中断使能
  446. * @parm spi spi句柄
  447. * @parm en 1 使能,0 失能
  448. * @return null
  449. */
  450. void spi_set_ie(spi_dev spi, u8 en)
  451. {
  452. u8 id = spi_get_info_id(spi);
  453. en ? spi_ie_en(spi_regs[id]) : spi_ie_dis(spi_regs[id]);
  454. }
  455. /*
  456. * @brief 判断中断标志
  457. * @parm spi spi句柄
  458. * @return 0 / 1
  459. */
  460. u8 spi_get_pending(spi_dev spi)
  461. {
  462. u8 id = spi_get_info_id(spi);
  463. return spi_pnd(spi_regs[id]) ? 1 : 0;
  464. }
  465. /*
  466. * @brief 清除中断标志
  467. * @parm spi spi句柄
  468. * @return null
  469. */
  470. void spi_clear_pending(spi_dev spi)
  471. {
  472. u8 id = spi_get_info_id(spi);
  473. spi_clr_pnd(spi_regs[id]);
  474. }
  475. /*
  476. * @brief 关闭spi
  477. * @parm spi spi句柄
  478. * @return null
  479. */
  480. void spi_close(spi_dev spi)
  481. {
  482. u8 id = spi_get_info_id(spi);
  483. u8 *port = spi_get_info_port(spi);
  484. spi_io_port_uninit(port[0]);
  485. spi_io_port_uninit(port[1]);
  486. spi_io_port_uninit(port[2]);
  487. spi_disable(spi_regs[id]);
  488. }
  489. void spi_disable_for_ota()
  490. {
  491. for (int i = 0; i < 2; i++) {
  492. spi_disable(spi_regs[i]);
  493. }
  494. }