dw_spi.c 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237
  1. /*
  2. * Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /******************************************************************************
  17. * @file dw_spi.c
  18. * @brief CSI Source File for SPI Driver
  19. * @version V1.0
  20. * @date 02. June 2017
  21. ******************************************************************************/
  22. #include "csi_core.h"
  23. #include "drv_spi.h"
  24. #include "dw_spi.h"
  25. #include "drv_gpio.h"
  26. #ifdef CONFIG_SPI_DMA
  27. #include "ck_dmac.h"
  28. #include <string.h>
  29. #endif
  30. #include "soc.h" /*CONFIG_SPI_NUM*/
  31. #define ERR_SPI(errno) (CSI_DRV_ERRNO_SPI_BASE | errno)
  32. #define SPI_NULL_PARAM_CHK(para) \
  33. do { \
  34. if (para == NULL) { \
  35. return ERR_SPI(EDRV_PARAMETER); \
  36. } \
  37. } while (0)
  38. typedef struct {
  39. uint32_t base;
  40. uint32_t irq;
  41. pin_t ssel;
  42. spi_event_cb_t cb_event;
  43. void *cb_arg;
  44. uint32_t send_num;
  45. uint32_t recv_num;
  46. uint8_t *send_buf;
  47. uint8_t *recv_buf;
  48. uint8_t enable_slave;
  49. uint32_t transfer_num;
  50. uint32_t clk_num; //clock number with a process of communication
  51. uint8_t state; //Current SPI state
  52. uint32_t mode; //Current SPI mode
  53. uint8_t ss_mode;
  54. spi_status_t status;
  55. #ifdef CONFIG_SPI_DMA
  56. dmac_handle_t dma_handle;
  57. int32_t dma_tx_id;
  58. int32_t dma_rx_id;
  59. #endif
  60. } dw_spi_priv_t;
  61. static dw_spi_priv_t spi_instance[CONFIG_SPI_NUM];
  62. static gpio_pin_handle_t pgpio_pin_handle;
  63. static const spi_capabilities_t spi_capabilities = {
  64. .simplex = 1, /* Simplex Mode (Master and Slave) */
  65. .ti_ssi = 1, /* TI Synchronous Serial Interface */
  66. .microwire = 1, /* Microwire Interface */
  67. .event_mode_fault = 0 /* Signal Mode Fault event: \ref CSKY_SPI_EVENT_MODE_FAULT */
  68. };
  69. static int32_t dw_spi_set_datawidth(dw_spi_reg_t *addr, DWENUM_SPI_DATAWIDTH datawidth);
  70. static int32_t dw_spi_set_mode(spi_handle_t handle, DWENUM_SPI_MODE mode);
  71. /**
  72. \brief use phobos gpio pin to simulate ss line for hardware controlled Output mode.
  73. */
  74. static int32_t dw_spi_ss_init(dw_spi_priv_t *spi_priv)
  75. {
  76. csi_gpio_port_initialize(0, NULL);
  77. pgpio_pin_handle = csi_gpio_pin_initialize(spi_priv->ssel);
  78. csi_gpio_pin_config(pgpio_pin_handle, GPIO_MODE_PULLNONE, GPIO_DIRECTION_OUTPUT);
  79. csi_gpio_pin_write(pgpio_pin_handle, true);
  80. spi_priv->ss_mode = SPI_SS_MASTER_HW_OUTPUT;
  81. return 0;
  82. }
  83. /**
  84. \brief control ss line depend on controlled Output mode.
  85. */
  86. static int32_t dw_spi_ss_control(dw_spi_priv_t *spi_priv, spi_ss_stat_e stat)
  87. {
  88. if (spi_priv->ss_mode == SPI_SS_MASTER_HW_OUTPUT) {
  89. if (stat == SPI_SS_INACTIVE) {
  90. csi_gpio_pin_write(pgpio_pin_handle, true);
  91. } else if (stat == SPI_SS_ACTIVE) {
  92. csi_gpio_pin_write(pgpio_pin_handle, false);
  93. } else {
  94. return -1;
  95. }
  96. }
  97. return 0;
  98. }
  99. #ifdef CONFIG_SPI_DMA
  100. void dw_spi_dma_event_cb(dma_event_e event, int32_t ch)
  101. {
  102. dw_spi_priv_t *spi_priv = NULL;
  103. uint8_t i = 0u;
  104. for (i = 0; i < CONFIG_SPI_NUM; i++) { /* find the SPI id */
  105. spi_priv = &spi_instance[i];
  106. if ((spi_priv->dma_tx_id == ch) || (spi_priv->dma_rx_id == ch)) {
  107. break;
  108. }
  109. }
  110. if (spi_priv->dma_tx_id == ch) {
  111. spi_priv->dma_tx_id = -1;
  112. } else {
  113. spi_priv->dma_rx_id = -1;
  114. }
  115. if (event == DMA_EVENT_TRANSFER_ERROR) { /* DMA transfer ERROR */
  116. if (spi_priv->cb_event) {
  117. spi_priv->cb_event(SPI_EVENT_DATA_LOST, NULL);
  118. }
  119. } else if (event == DMA_EVENT_TRANSFER_DONE) { /* DMA transfer complete */
  120. if (spi_priv->mode == DWENUM_SPI_TXRX) {
  121. if (spi_priv->cb_event) {
  122. spi_priv->cb_event(SPI_EVENT_TRANSFER_COMPLETE, spi_priv->cb_arg);
  123. }
  124. } else if (spi_priv->mode == DWENUM_SPI_TX) {
  125. dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
  126. while (addr->SR & DW_SPI_DISABLE);
  127. if (spi_priv->cb_event) {
  128. spi_priv->cb_event(SPI_EVENT_TX_COMPLETE, spi_priv->cb_arg);
  129. }
  130. } else {
  131. if (spi_priv->cb_event) {
  132. spi_priv->cb_event(SPI_EVENT_RX_COMPLETE, spi_priv->cb_arg);
  133. }
  134. }
  135. }
  136. spi_priv->status.busy = 0U;
  137. }
  138. /**
  139. \brief sending data to SPI transmitter with DMA,(received data is ignored).
  140. */
  141. static int32_t dw_spi_dma_send(dw_spi_priv_t *spi_priv, const void *data, uint32_t num)
  142. {
  143. int32_t ch = csi_dma_alloc_channel(spi_priv->dma_handle, -1);
  144. spi_priv->dma_tx_id = ch;
  145. dma_config_t config;
  146. config.src_inc = DMA_ADDR_INC;
  147. config.dst_inc = DMA_ADDR_CONSTANT;
  148. config.src_tw = DMA_DATAWIDTH_SIZE8;
  149. config.dst_tw = DMA_DATAWIDTH_SIZE8;
  150. config.hs_if = CKENUM_DMA_SPI1_TX;
  151. config.type = DMA_MEM2PERH;
  152. dw_spi_ss_control(spi_priv, SPI_SS_ACTIVE);
  153. dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
  154. uint8_t *ptxbuffer = (uint8_t *)data;
  155. int32_t ret = csi_dma_config(spi_priv->dma_handle, ch, ptxbuffer, (uint8_t *) & (addr->DR), num, &config, dw_spi_dma_event_cb);
  156. if (ret < 0) {
  157. return ret;
  158. }
  159. addr->SPIENR = DW_SPI_DISABLE; /* enable SPI */
  160. dw_spi_set_mode(spi_priv, DWENUM_SPI_TX);
  161. addr->DMATDLR = 0;
  162. addr->DMACR = DW_SPI_TDMAE;
  163. addr->SER = spi_priv->enable_slave;
  164. addr->SPIENR = DW_SPI_ENABLE;
  165. csi_dma_start(spi_priv->dma_handle, ch);
  166. while (csi_dma_get_status(spi_priv->dma_handle, ch) != DMA_STATE_DONE);
  167. while (addr->SR & DW_SPI_BUSY);
  168. csi_dma_stop(spi_priv->dma_handle, ch);
  169. csi_dma_release_channel(spi_priv->dma_handle, ch);
  170. addr->SPIENR = DW_SPI_DISABLE;
  171. addr->SER = 0;
  172. dw_spi_ss_control(spi_priv, SPI_SS_INACTIVE);
  173. spi_priv->status.busy = 0U;
  174. return 0;
  175. }
  176. /**
  177. \brief receiving data from SPI receiver with DMA.
  178. */
  179. static int32_t dw_spi_dma_receive(dw_spi_priv_t *spi_priv, void *data, uint32_t num)
  180. {
  181. int32_t ch;
  182. ch = csi_dma_alloc_channel(spi_priv->dma_handle, -1);
  183. spi_priv->dma_tx_id = ch;
  184. dma_config_t config;
  185. config.src_inc = DMA_ADDR_CONSTANT;
  186. config.dst_inc = DMA_ADDR_INC;
  187. config.src_tw = DMA_DATAWIDTH_SIZE8;
  188. config.dst_tw = DMA_DATAWIDTH_SIZE8;
  189. config.hs_if = CKENUM_DMA_SPI1_RX;
  190. config.type = DMA_PERH2MEM;
  191. dw_spi_ss_control(spi_priv, SPI_SS_ACTIVE);
  192. uint8_t *prx_buffer = (uint8_t *)data;
  193. spi_priv->recv_buf = prx_buffer;
  194. spi_priv->clk_num = num;
  195. spi_priv->recv_num = num;
  196. dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
  197. int32_t ret;
  198. while (spi_priv->clk_num) {
  199. if (spi_priv->clk_num >= DW_SPI_FIFO_MAX_LV / 2) {
  200. spi_priv->recv_num = DW_SPI_FIFO_MAX_LV / 2;
  201. }
  202. ret = csi_dma_config(spi_priv->dma_handle, ch, (uint8_t *) & (addr->DR), spi_priv->recv_buf, spi_priv->recv_num, &config, dw_spi_dma_event_cb);
  203. if (ret < 0) {
  204. return ret;
  205. }
  206. addr->SPIENR = DW_SPI_DISABLE; /* enable SPI */
  207. dw_spi_set_mode(spi_priv, DWENUM_SPI_RX);
  208. addr->DMARDLR = spi_priv->recv_num - 1;
  209. addr->CTRLR1 = spi_priv->recv_num - 1;
  210. addr->DMACR = DW_SPI_RDMAE;
  211. addr->SER = spi_priv->enable_slave;
  212. csi_dma_start(spi_priv->dma_handle, ch);
  213. addr->SPIENR = DW_SPI_ENABLE;
  214. addr->DR = DW_SPI_START_RX;
  215. while (csi_dma_get_status(spi_priv->dma_handle, ch) != DMA_STATE_DONE);
  216. csi_dma_stop(spi_priv->dma_handle, ch);
  217. spi_priv->clk_num -= spi_priv->recv_num;
  218. spi_priv->recv_buf += spi_priv->recv_num;
  219. }
  220. addr->SPIENR = DW_SPI_DISABLE;
  221. addr->SER = 0;
  222. csi_dma_release_channel(spi_priv->dma_handle, ch);
  223. dw_spi_ss_control(spi_priv, SPI_SS_INACTIVE);
  224. spi_priv->status.busy = 0U;
  225. return 0;
  226. }
  227. /**
  228. \brief sending/receiving data to/from SPI transmitter/receiver with DMA.
  229. */
  230. static int32_t dw_spi_dma_transfer(dw_spi_priv_t *spi_priv, const void *data_out, void *data_in, uint32_t num_out, uint32_t num_in)
  231. {
  232. int32_t tx_ch = csi_dma_alloc_channel(spi_priv->dma_handle, -1);
  233. if (tx_ch < 0) {
  234. return tx_ch;
  235. }
  236. spi_priv->dma_tx_id = tx_ch;
  237. int32_t rx_ch = csi_dma_alloc_channel(spi_priv->dma_handle, -1);
  238. if (rx_ch < 0) {
  239. return rx_ch;
  240. }
  241. spi_priv->dma_rx_id = rx_ch;
  242. dma_config_t tx_config, rx_config;
  243. tx_config.src_inc = DMA_ADDR_INC;
  244. tx_config.dst_inc = DMA_ADDR_CONSTANT;
  245. tx_config.src_tw = DMA_DATAWIDTH_SIZE8;
  246. tx_config.dst_tw = DMA_DATAWIDTH_SIZE8;
  247. tx_config.hs_if = CKENUM_DMA_SPI1_TX;
  248. tx_config.type = DMA_MEM2PERH;
  249. rx_config.src_inc = DMA_ADDR_CONSTANT;
  250. rx_config.dst_inc = DMA_ADDR_INC;
  251. rx_config.src_tw = DMA_DATAWIDTH_SIZE8;
  252. rx_config.dst_tw = DMA_DATAWIDTH_SIZE8;
  253. rx_config.hs_if = CKENUM_DMA_SPI1_RX;
  254. rx_config.type = DMA_PERH2MEM;
  255. dw_spi_ss_control(spi_priv, SPI_SS_ACTIVE);
  256. uint8_t *ptx_buffer = (uint8_t *)data_out;
  257. uint8_t *prx_buffer = (uint8_t *)data_in;
  258. spi_priv->send_buf = ptx_buffer;
  259. spi_priv->recv_buf = prx_buffer;
  260. spi_priv->send_num = num_out;
  261. spi_priv->recv_num = num_in;
  262. spi_priv->clk_num = num_in;
  263. dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
  264. int32_t ret;
  265. uint8_t dma_send_buf[DW_SPI_FIFO_MAX_LV];
  266. while (spi_priv->clk_num) {
  267. if (spi_priv->clk_num >= DW_SPI_FIFO_MAX_LV) {
  268. spi_priv->transfer_num = DW_SPI_FIFO_MAX_LV;
  269. } else {
  270. spi_priv->transfer_num = spi_priv->clk_num;
  271. }
  272. if (spi_priv->send_num >= spi_priv->transfer_num) {
  273. memcpy(dma_send_buf, spi_priv->send_buf, spi_priv->transfer_num);
  274. spi_priv->send_num -= spi_priv->transfer_num;
  275. spi_priv->send_buf += spi_priv->transfer_num;
  276. } else {
  277. if (spi_priv->send_num > 0) {
  278. memcpy(dma_send_buf, spi_priv->send_buf, spi_priv->send_num);
  279. spi_priv->send_buf = NULL;
  280. }
  281. memset(&dma_send_buf[spi_priv->send_num], 0, spi_priv->transfer_num - spi_priv->send_num);
  282. spi_priv->send_num = 0;
  283. }
  284. ret = csi_dma_config(spi_priv->dma_handle, tx_ch, dma_send_buf, (uint8_t *) & (addr->DR), spi_priv->transfer_num, &tx_config, dw_spi_dma_event_cb);
  285. if (ret < 0) {
  286. return ret;
  287. }
  288. ret = csi_dma_config(spi_priv->dma_handle, rx_ch, (uint8_t *) & (addr->DR), spi_priv->recv_buf, spi_priv->transfer_num, &rx_config, dw_spi_dma_event_cb);
  289. if (ret < 0) {
  290. return ret;
  291. }
  292. addr->SPIENR = DW_SPI_DISABLE; /* disable SPI */
  293. addr->DMARDLR = (spi_priv->transfer_num - 1) % 16; /* set dma receive data level */
  294. addr->DMATDLR = (spi_priv->transfer_num - 1) % 16 + 1; /* set dma transmit data level */
  295. addr->DMACR = DW_SPI_RDMAE | DW_SPI_TDMAE;
  296. dw_spi_set_mode(spi_priv, DWENUM_SPI_TXRX);
  297. addr->SER = spi_priv->enable_slave;
  298. addr->SPIENR = DW_SPI_ENABLE; /* enable SPI */
  299. ret = csi_dma_start(spi_priv->dma_handle, tx_ch);
  300. if (ret < 0) {
  301. return ret;
  302. }
  303. while (csi_dma_get_status(spi_priv->dma_handle, tx_ch) != DMA_STATE_DONE);
  304. ret = csi_dma_start(spi_priv->dma_handle, rx_ch);
  305. if (ret < 0) {
  306. return ret;
  307. }
  308. while (csi_dma_get_status(spi_priv->dma_handle, rx_ch) != DMA_STATE_DONE);
  309. spi_priv->recv_buf += spi_priv->transfer_num;
  310. spi_priv->recv_num -= spi_priv->transfer_num;
  311. spi_priv->clk_num -= spi_priv->transfer_num;
  312. addr->SPIENR = DW_SPI_DISABLE;
  313. csi_dma_stop(spi_priv->dma_handle, tx_ch);
  314. csi_dma_stop(spi_priv->dma_handle, rx_ch);
  315. }
  316. dw_spi_ss_control(spi_priv, SPI_SS_INACTIVE);
  317. addr->SER = 0;
  318. csi_dma_release_channel(spi_priv->dma_handle, tx_ch);
  319. csi_dma_release_channel(spi_priv->dma_handle, rx_ch);
  320. spi_priv->status.busy = 0U;
  321. return 0;
  322. }
  323. #endif
  324. /**
  325. \brief Set the SPI datawidth.
  326. \param[in] addr pointer to register address
  327. \param[in] datawidth date frame size
  328. \return error code
  329. */
  330. static int32_t dw_spi_set_datawidth(dw_spi_reg_t *addr, DWENUM_SPI_DATAWIDTH datawidth)
  331. {
  332. if ((datawidth >= DWENUM_SPI_DATASIZE_4) && (datawidth <= DWENUM_SPI_DATASIZE_16)) {
  333. uint16_t temp = addr->CTRLR0;
  334. temp &= 0xfff0; /* temp has the value of CTRLR0 with DFS being cleared.*/
  335. temp |= (datawidth); /* get the final CTRLR0 after datawidth config. */
  336. addr->CTRLR0 = temp; /* write CTRLR0 */
  337. return 0;
  338. }
  339. return -1;
  340. }
  341. /**
  342. \brief Set the SPI clock divider.
  343. \param[in] addr pointer to register address
  344. \param[in] baud spi baud rate
  345. \param[in] apbfreq sysclk for spi module.
  346. \return error code
  347. */
  348. static int32_t dw_spi_set_baudrate(dw_spi_reg_t *addr, int32_t baud, int32_t apbfreq)
  349. {
  350. int32_t sckdv = apbfreq / baud;
  351. if (sckdv < 0x10000) {
  352. addr->BAUDR = sckdv;
  353. } else {
  354. return -1;
  355. }
  356. return 0;
  357. }
  358. /**
  359. \brief Set the SPI polarity.
  360. \param[in] addr pointer to register address
  361. \param[in] polarity spi polarity
  362. \return error code
  363. */
  364. static int32_t dw_spi_set_polarity(dw_spi_reg_t *addr, DWENUM_SPI_POLARITY polarity)
  365. {
  366. /* To config the polarity, we can set the SCPOL bit(CTRLR0[7]) as below:
  367. * 0 - inactive state of serial clock is low
  368. * 1 - inactive state of serial clock is high
  369. */
  370. switch (polarity) {
  371. case DWENUM_SPI_CLOCK_POLARITY_LOW:
  372. addr->CTRLR0 &= (~DW_SPI_POLARITY);
  373. break;
  374. case DWENUM_SPI_CLOCK_POLARITY_HIGH:
  375. addr->CTRLR0 |= DW_SPI_POLARITY;
  376. break;
  377. default:
  378. return -1;
  379. }
  380. return 0;
  381. }
  382. /**
  383. \brief Set the SPI Phase.
  384. \param[in] addr pointer to register address
  385. \param[in] phase Serial clock phase
  386. \return error code
  387. */
  388. static int32_t dw_spi_set_phase(dw_spi_reg_t *addr, DWENUM_SPI_PHASE phase)
  389. {
  390. switch (phase) {
  391. case DWENUM_SPI_CLOCK_PHASE_MIDDLE:
  392. addr->CTRLR0 &= (~DW_SPI_PHASE);
  393. break;
  394. case DWENUM_SPI_CLOCK_PHASE_START:
  395. addr->CTRLR0 |= DW_SPI_PHASE;
  396. break;
  397. default:
  398. return -1;
  399. }
  400. return 0;
  401. }
  402. /**
  403. \brief Set the SPI mode.
  404. \param[in] addr pointer to register address
  405. \param[in] mode SPI_Mode
  406. \return error code
  407. */
  408. static int32_t dw_spi_set_mode(spi_handle_t handle, DWENUM_SPI_MODE mode)
  409. {
  410. dw_spi_priv_t *spi_priv = handle;
  411. dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
  412. /* It is impossible to write to this register when the SSI is enabled.*/
  413. /* we can set the TMOD to config transfer mode as below:
  414. * TMOD_BIT9 TMOD_BIT8 transfer mode
  415. * 0 0 transmit & receive
  416. * 0 1 transmit only
  417. * 1 0 receive only
  418. * 1 1 reserved
  419. */
  420. switch (mode) {
  421. case DWENUM_SPI_TXRX:
  422. addr->CTRLR0 &= (~DW_SPI_TMOD_BIT8);
  423. addr->CTRLR0 &= (~DW_SPI_TMOD_BIT9);
  424. break;
  425. case DWENUM_SPI_TX:
  426. addr->CTRLR0 |= DW_SPI_TMOD_BIT8;
  427. addr->CTRLR0 &= (~DW_SPI_TMOD_BIT9);
  428. break;
  429. case DWENUM_SPI_RX:
  430. addr->CTRLR0 &= (~DW_SPI_TMOD_BIT8);
  431. addr->CTRLR0 |= DW_SPI_TMOD_BIT9;
  432. break;
  433. default:
  434. addr->CTRLR0 |= DW_SPI_TMOD_BIT8;
  435. addr->CTRLR0 |= DW_SPI_TMOD_BIT9;
  436. break;
  437. }
  438. spi_priv->mode = mode;
  439. return 0;
  440. }
  441. /**
  442. \brief interrupt service function for receive FIFO full interrupt .
  443. \param[in] spi_priv pointer to spi private.
  444. */
  445. static void dw_spi_intr_rx_full(dw_spi_priv_t *spi_priv)
  446. {
  447. dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
  448. uint8_t temp = addr->ICR;
  449. uint8_t *pbuffer = spi_priv->recv_buf;
  450. uint32_t length = spi_priv->recv_num;
  451. uint8_t rxnum;
  452. rxnum = addr->RXFLR;
  453. uint32_t i = 0u;
  454. for (i = 0; i < rxnum; i++) {
  455. *pbuffer = addr->DR;
  456. pbuffer++;
  457. }
  458. length -= rxnum;
  459. if (length < DW_SPI_FIFO_MAX_LV) {
  460. addr->RXFTLR = length - 1;
  461. }
  462. if (length <= 0) {
  463. temp = addr->IMR;
  464. temp &= 0x2f;
  465. addr->IMR = temp;
  466. addr->SER = 0;
  467. addr->SPIENR = DW_SPI_DISABLE;
  468. spi_priv->status.busy = 0U;
  469. dw_spi_ss_control(spi_priv, SPI_SS_INACTIVE);
  470. if (spi_priv->cb_event) {
  471. spi_priv->cb_event(SPI_EVENT_RX_COMPLETE, spi_priv->cb_arg);
  472. return;
  473. }
  474. } else {
  475. addr->SPIENR = DW_SPI_DISABLE; /* disable SPI */
  476. dw_spi_set_mode(spi_priv, DWENUM_SPI_RX);
  477. addr->SER = spi_priv->enable_slave; /* enable all cs */
  478. spi_priv->recv_buf = pbuffer;
  479. spi_priv->recv_num = length;
  480. if (spi_priv->recv_num > DW_SPI_FIFO_MAX_LV) {
  481. addr->RXFTLR = DW_SPI_FIFO_MAX_LV - 1;
  482. addr->CTRLR1 = DW_SPI_FIFO_MAX_LV - 1;
  483. } else {
  484. addr->RXFTLR = spi_priv->recv_num - 1;
  485. addr->CTRLR1 = spi_priv->recv_num - 1;
  486. }
  487. addr->SPIENR = DW_SPI_ENABLE; /* enable SPI */
  488. addr->DR = DW_SPI_START_RX ;
  489. }
  490. }
  491. /**
  492. \brief interrupt service function for transmit FIFO empty interrupt.
  493. \param[in] spi_priv pointer to spi private.
  494. */
  495. static void dw_spi_intr_tx_empty(dw_spi_priv_t *spi_priv)
  496. {
  497. dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
  498. uint8_t temp = addr->ICR;
  499. /* transfer mode:transmit & receive */
  500. uint32_t i = 0u;
  501. if (spi_priv->
  502. mode == DWENUM_SPI_TXRX) {
  503. /* read data out from rx FIFO */
  504. while (spi_priv->transfer_num) {
  505. *spi_priv->recv_buf = addr->DR;
  506. spi_priv->recv_buf++;
  507. spi_priv->transfer_num--;
  508. }
  509. if (spi_priv->clk_num >= DW_SPI_FIFO_MAX_LV) {
  510. spi_priv->transfer_num = DW_SPI_FIFO_MAX_LV;
  511. } else {
  512. spi_priv->transfer_num = spi_priv->clk_num;
  513. }
  514. for (i = 0; i < spi_priv->transfer_num; i++) {
  515. if (spi_priv->send_num == 0) {
  516. addr->DR = 0x0;
  517. } else {
  518. addr->DR = *spi_priv->send_buf;
  519. spi_priv->send_buf++;
  520. }
  521. spi_priv->send_num--;
  522. }
  523. } else { //transfer mode :transmit only
  524. if (spi_priv->clk_num >= DW_SPI_FIFO_MAX_LV) {
  525. spi_priv->transfer_num = DW_SPI_FIFO_MAX_LV;
  526. } else {
  527. spi_priv->transfer_num = spi_priv->clk_num;
  528. }
  529. for (i = 0; i < spi_priv->transfer_num; i++) {
  530. addr->DR = *spi_priv->send_buf;
  531. spi_priv->send_buf++;
  532. spi_priv->send_num--;
  533. }
  534. }
  535. if (spi_priv->clk_num == 0) {
  536. temp = addr->IMR;
  537. temp &= ~DW_SPI_IMR_TXEIM;
  538. addr->IMR = temp;
  539. addr->SER = 0;
  540. addr->SPIENR = DW_SPI_DISABLE;
  541. spi_priv->status.busy = 0U;
  542. dw_spi_ss_control(spi_priv, SPI_SS_INACTIVE);
  543. if (spi_priv->mode == DWENUM_SPI_TXRX) {
  544. if (spi_priv->cb_event) {
  545. spi_priv->cb_event(SPI_EVENT_TRANSFER_COMPLETE, spi_priv->cb_arg);
  546. return;
  547. }
  548. } else {
  549. if (spi_priv->cb_event) {
  550. spi_priv->cb_event(SPI_EVENT_TX_COMPLETE, spi_priv->cb_arg);
  551. return;
  552. }
  553. }
  554. }
  555. spi_priv->clk_num -= spi_priv->transfer_num;
  556. }
  557. /**
  558. \brief handler the interrupt.
  559. \param[in] spi Pointer to \ref SPI_RESOURCES
  560. */
  561. void dw_spi_irqhandler(int32_t idx)
  562. {
  563. dw_spi_priv_t *spi_priv = &spi_instance[idx];
  564. dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
  565. uint32_t intr = addr->ISR;
  566. /* deal with receive FIFO full interrupt */
  567. if (intr & DW_SPI_RXFIFO_FULL) {
  568. dw_spi_intr_rx_full(spi_priv);
  569. }
  570. /* deal with transmit FIFO empty interrupt */
  571. else if (intr & DW_SPI_TXFIFO_EMPTY) {
  572. dw_spi_intr_tx_empty(spi_priv);
  573. }
  574. }
  575. int32_t __attribute__((weak)) target_spi_init(pin_t mosi, pin_t miso, pin_t sclk, pin_t ssel, uint32_t *base, uint32_t *irq)
  576. {
  577. return -1;
  578. }
  579. /**
  580. \brief Initialize SPI Interface. 1. Initializes the resources needed for the SPI interface 2.registers event callback function
  581. \param[in] spi pin of mosi
  582. \param[in] spi pin of miso
  583. \param[in] spi pin of sclk
  584. \param[in] spi pin of ssel
  585. \param[in] cb_event event call back function \ref spi_event_cb_t
  586. \return return spi handle if success
  587. */
  588. spi_handle_t csi_spi_initialize(pin_t mosi, pin_t miso, pin_t sclk, pin_t ssel, spi_event_cb_t cb_event, void *cb_arg)
  589. {
  590. uint32_t base = 0u;
  591. uint32_t irq = 0u;
  592. int32_t idx = target_spi_init(mosi, miso, sclk, ssel, &base, &irq);
  593. if (idx < 0 || idx >= CONFIG_SPI_NUM) {
  594. return NULL;
  595. }
  596. dw_spi_priv_t *spi_priv = &spi_instance[idx];
  597. spi_priv->base = base;
  598. spi_priv->irq = irq;
  599. spi_priv->ssel = ssel;
  600. spi_priv->cb_event = cb_event;
  601. spi_priv->cb_arg = cb_arg;
  602. spi_priv->status.busy = 0U;
  603. spi_priv->status.data_lost = 0U;
  604. spi_priv->status.mode_fault = 0U;
  605. spi_priv->enable_slave = 1U;
  606. spi_priv->state = SPI_INITIALIZED;
  607. drv_nvic_enable_irq(spi_priv->irq);
  608. #ifdef CONFIG_SPI_DMA
  609. spi_priv->dma_handle = csi_dma_initialize(0);
  610. #endif
  611. return (spi_handle_t)spi_priv;
  612. }
  613. /**
  614. \brief De-initialize SPI Interface. stops operation and releases the software resources used by the interface
  615. \param[in] handle spi handle to operate.
  616. \return error code
  617. */
  618. int32_t csi_spi_uninitialize(spi_handle_t handle)
  619. {
  620. SPI_NULL_PARAM_CHK(handle);
  621. dw_spi_priv_t *spi_priv = handle;
  622. drv_nvic_disable_irq(spi_priv->irq);
  623. spi_priv->cb_event = NULL;
  624. spi_priv->state = 0U;
  625. spi_priv->status.busy = 0U;
  626. spi_priv->status.data_lost = 0U;
  627. spi_priv->status.mode_fault = 0U;
  628. #ifdef CONFIG_SPI_DMA
  629. csi_dma_uninitialize(spi_priv->dma_handle);
  630. #endif
  631. return 0;
  632. }
  633. /**
  634. \brief Get driver capabilities.
  635. \param[in] spi instance to operate.
  636. \return \ref spi_capabilities_t
  637. */
  638. spi_capabilities_t csi_spi_get_capabilities(spi_handle_t handle)
  639. {
  640. return spi_capabilities;
  641. }
  642. /**
  643. \brief config spi mode.
  644. \param[in] handle spi handle to operate.
  645. \param[in] sysclk sysclk for spi module.
  646. \param[in] baud spi baud rate. if negative, then this attribute not changed
  647. \param[in] mode \ref spi_mode_e . if negative, then this attribute not changed
  648. \param[in] format \ref spi_format_e . if negative, then this attribute not changed
  649. \param[in] order \ref spi_bit_order_e . if negative, then this attribute not changed
  650. \param[in] ss_mode \ref spi_ss_mode_e . if negative, then this attribute not changed
  651. \param[in] bit_width spi data bitwidth: (1 ~ SPI_DATAWIDTH_MAX) . if negative, then this attribute not changed
  652. \return error code
  653. */
  654. int32_t csi_spi_config(spi_handle_t handle,
  655. int32_t sysclk,
  656. int32_t baud,
  657. spi_mode_e mode,
  658. spi_format_e format,
  659. spi_bit_order_e order,
  660. spi_ss_mode_e ss_mode,
  661. int32_t bit_width)
  662. {
  663. SPI_NULL_PARAM_CHK(handle);
  664. dw_spi_priv_t *spi_priv = handle;
  665. dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
  666. if ((spi_priv->state & SPI_INITIALIZED) == 0U) {
  667. return ERR_SPI(EDRV_UNSUPPORTED);
  668. }
  669. if (spi_priv->status.busy) {
  670. return ERR_SPI(EDRV_BUSY);
  671. }
  672. spi_priv->status.busy = 0U;
  673. spi_priv->status.data_lost = 0U;
  674. spi_priv->status.mode_fault = 0U;
  675. addr->SPIENR = DW_SPI_DISABLE;
  676. addr->IMR = DW_SPI_INT_DISABLE;
  677. int32_t ret = 0;
  678. if (baud >= 0) {
  679. ret = dw_spi_set_baudrate(addr, baud, sysclk);
  680. if (ret < 0) {
  681. return ERR_SPI(EDRV_PARAMETER);
  682. }
  683. }
  684. if (mode >= 0) {
  685. switch (mode) {
  686. case SPI_MODE_MASTER:
  687. break;
  688. default:
  689. return ERR_SPI(EDRV_UNSUPPORTED);
  690. }
  691. }
  692. if (format >= 0) {
  693. switch (format) {
  694. case SPI_FORMAT_CPOL0_CPHA0:
  695. dw_spi_set_polarity(addr, DWENUM_SPI_CLOCK_POLARITY_LOW);
  696. dw_spi_set_phase(addr, DWENUM_SPI_CLOCK_PHASE_MIDDLE);
  697. break;
  698. case SPI_FORMAT_CPOL0_CPHA1:
  699. dw_spi_set_polarity(addr, DWENUM_SPI_CLOCK_POLARITY_LOW);
  700. dw_spi_set_phase(addr, DWENUM_SPI_CLOCK_PHASE_START);
  701. break;
  702. case SPI_FORMAT_CPOL1_CPHA0:
  703. dw_spi_set_polarity(addr, DWENUM_SPI_CLOCK_POLARITY_HIGH);
  704. dw_spi_set_phase(addr, DWENUM_SPI_CLOCK_PHASE_MIDDLE);
  705. break;
  706. case SPI_FORMAT_CPOL1_CPHA1:
  707. dw_spi_set_polarity(addr, DWENUM_SPI_CLOCK_POLARITY_HIGH);
  708. dw_spi_set_phase(addr, DWENUM_SPI_CLOCK_PHASE_START);
  709. break;
  710. default:
  711. return ERR_SPI(EDRV_PARAMETER);
  712. }
  713. }
  714. if (order >= 0) {
  715. //TD:
  716. }
  717. if (ss_mode >= 0) {
  718. switch (ss_mode) {
  719. case SPI_SS_MASTER_SW:
  720. spi_priv->ss_mode = SPI_SS_MASTER_SW;
  721. break;
  722. case SPI_SS_MASTER_HW_OUTPUT:
  723. dw_spi_ss_init(spi_priv);
  724. break;
  725. default:
  726. return ERR_SPI(EDRV_UNSUPPORTED);
  727. }
  728. }
  729. if (bit_width >= 0) {
  730. ret = dw_spi_set_datawidth(addr, bit_width);
  731. if (ret < 0) {
  732. return ERR_SPI(EDRV_PARAMETER);
  733. }
  734. }
  735. spi_priv->state |= SPI_CONFIGURED;
  736. return 0;
  737. }
  738. /**
  739. \brief config spi default tx value.
  740. \param[in] handle spi handle to operate.
  741. \param[in] value default tx value
  742. \return error code
  743. */
  744. int32_t csi_spi_set_default_tx_value(spi_handle_t handle, uint32_t value)
  745. {
  746. SPI_NULL_PARAM_CHK(handle);
  747. return ERR_SPI(EDRV_UNSUPPORTED);
  748. }
  749. /**
  750. \brief sending data to SPI transmitter,(received data is ignored).
  751. if non-blocking mode, this function only start the sending,
  752. \ref spi_event_e is signaled when operation completes or error happens.
  753. \ref csi_spi_get_status can indicates operation status.
  754. if blocking mode, this function return after operation completes or error happens.
  755. \param[in] handle spi handle to operate.
  756. \param[in] data Pointer to buffer with data to send to SPI transmitter. data_type is : uint8_t for 1..8 data bits, uint16_t for 9..16 data bits,uint32_t for 17..32 data bits,
  757. \param[in] num Number of data items to send.
  758. \param[in] block_mode blocking and non_blocking to selcect
  759. \return error code
  760. */
  761. int32_t csi_spi_send(spi_handle_t handle, const void *data, uint32_t num, uint8_t block_mode)
  762. {
  763. if (handle == NULL || data == NULL || num == 0) {
  764. return ERR_SPI(EDRV_PARAMETER);
  765. }
  766. dw_spi_priv_t *spi_priv = handle;
  767. if ((spi_priv->state & SPI_CONFIGURED) == 0U) {
  768. return ERR_SPI(EDRV_UNSUPPORTED);
  769. }
  770. if (spi_priv->status.busy) {
  771. return ERR_SPI(EDRV_BUSY);
  772. }
  773. spi_priv->status.busy = 1U;
  774. spi_priv->status.data_lost = 0U;
  775. spi_priv->status.mode_fault = 0U;
  776. #ifdef CONFIG_SPI_DMA
  777. return dw_spi_dma_send(spi_priv, data, num);
  778. #endif
  779. dw_spi_ss_control(spi_priv, SPI_SS_ACTIVE);
  780. dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
  781. addr->SPIENR = DW_SPI_DISABLE; /* disable SPI */
  782. dw_spi_set_mode(spi_priv, DWENUM_SPI_TX);
  783. addr->SPIENR = DW_SPI_ENABLE; /* enable SPI */
  784. uint8_t *ptxbuffer = (uint8_t *)data;
  785. if (block_mode) {
  786. addr->SER = spi_priv->enable_slave;
  787. addr->TXFTLR = DW_SPI_TXFIFO_LV;
  788. dw_spi_ss_control(spi_priv, SPI_SS_ACTIVE);
  789. spi_priv->send_num = num;
  790. uint32_t once_len , i;
  791. while (spi_priv->send_num) {
  792. once_len = (spi_priv->send_num >= DW_SPI_FIFO_MAX_LV) ?
  793. DW_SPI_FIFO_MAX_LV : spi_priv->send_num;
  794. for (i = 0; i < once_len; i++) {
  795. addr->DR = *ptxbuffer++;
  796. }
  797. while (!(addr->SR & DW_SPI_TFE));
  798. while (addr->SR & DW_SPI_BUSY);
  799. spi_priv->send_num -= once_len;
  800. }
  801. dw_spi_ss_control(spi_priv, SPI_SS_INACTIVE);
  802. spi_priv->status.busy = 0U;
  803. } else {
  804. spi_priv->send_num = num;
  805. spi_priv->clk_num = num;
  806. spi_priv->send_buf = ptxbuffer;
  807. spi_priv->transfer_num = 0;
  808. addr->SPIENR = DW_SPI_ENABLE; /* enable SPI */
  809. addr->TXFTLR = DW_SPI_TXFIFO_LV;
  810. addr->SER = spi_priv->enable_slave;
  811. addr->IMR = DW_SPI_IMR_TXEIM;
  812. }
  813. return 0;
  814. }
  815. /**
  816. \brief receiving data from SPI receiver.transmits the default value as specified by csi_spi_set_default_tx_value
  817. if non-blocking mode, this function only start the receiving,
  818. \ref spi_event_e is signaled when operation completes or error happens.
  819. \ref csi_spi_get_status can indicates operation status.
  820. if blocking mode, this function return after operation completes or error happens.
  821. \param[in] handle spi handle to operate.
  822. \param[out] data Pointer to buffer for data to receive from SPI receiver
  823. \param[in] num Number of data items to receive
  824. \param[in] block_mode blocking and non_blocking to selcect
  825. \return error code
  826. */
  827. int32_t csi_spi_receive(spi_handle_t handle, void *data, uint32_t num, uint8_t block_mode)
  828. {
  829. if (handle == NULL || data == NULL || num == 0) {
  830. return ERR_SPI(EDRV_PARAMETER);
  831. }
  832. dw_spi_priv_t *spi_priv = handle;
  833. if ((spi_priv->state & SPI_CONFIGURED) == 0U) {
  834. return ERR_SPI(EDRV_UNSUPPORTED);
  835. }
  836. if (spi_priv->status.busy) {
  837. return ERR_SPI(EDRV_BUSY);
  838. }
  839. spi_priv->status.busy = 1U;
  840. spi_priv->status.data_lost = 0U;
  841. spi_priv->status.mode_fault = 0U;
  842. #ifdef CONFIG_SPI_DMA
  843. return dw_spi_dma_receive(spi_priv, data, num);
  844. #endif
  845. dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
  846. uint8_t *prx_buffer = data;
  847. if (block_mode) {
  848. dw_spi_ss_control(spi_priv, SPI_SS_ACTIVE);
  849. spi_priv->recv_buf = prx_buffer;
  850. spi_priv->recv_num = num;
  851. while (spi_priv->recv_num) {
  852. addr->SPIENR = DW_SPI_DISABLE; /* disable SPI */
  853. dw_spi_set_mode(spi_priv, DWENUM_SPI_RX);
  854. addr->SER = spi_priv->enable_slave; /* enable all cs */
  855. uint32_t once_len = (spi_priv->recv_num >= DW_SPI_FIFO_MAX_LV) ?
  856. DW_SPI_FIFO_MAX_LV : spi_priv->recv_num;
  857. addr->CTRLR1 = once_len - 1;
  858. addr->RXFTLR = once_len - 1;
  859. addr->SPIENR = DW_SPI_ENABLE;
  860. addr->DR = 0;
  861. while (addr->RXFLR < once_len);
  862. int i = 0;
  863. for (i = 0; i < once_len; i++) {
  864. *spi_priv->recv_buf++ = addr->DR;
  865. }
  866. spi_priv->recv_num -= once_len;
  867. }
  868. dw_spi_ss_control(spi_priv, SPI_SS_INACTIVE);
  869. spi_priv->status.busy = 0U;
  870. } else {
  871. dw_spi_ss_control(spi_priv, SPI_SS_ACTIVE);
  872. addr->SPIENR = DW_SPI_DISABLE; /* disable SPI */
  873. spi_priv->recv_buf = prx_buffer;
  874. spi_priv->recv_num = num;
  875. dw_spi_set_mode(spi_priv, DWENUM_SPI_RX);
  876. addr->SER = spi_priv->enable_slave; /* enable all cs */
  877. if (num > DW_SPI_FIFO_MAX_LV) {
  878. addr->RXFTLR = DW_SPI_FIFO_MAX_LV - 1;
  879. addr->CTRLR1 = DW_SPI_FIFO_MAX_LV - 1;
  880. } else {
  881. addr->RXFTLR = num - 1;
  882. addr->CTRLR1 = num - 1;
  883. }
  884. addr->IMR = DW_SPI_IMR_RXFIM;
  885. addr->SPIENR = DW_SPI_ENABLE; /* enable SPI */
  886. addr->DR = DW_SPI_START_RX ;
  887. }
  888. return 0;
  889. }
  890. /**
  891. \brief sending/receiving data to/from SPI transmitter/receiver.
  892. if non-blocking mode, this function only start the transfer,
  893. \ref spi_event_e is signaled when operation completes or error happens.
  894. \ref csi_spi_get_status can indicates operation status.
  895. if blocking mode, this function return after operation completes or error happens.
  896. \param[in] handle spi handle to operate.
  897. \param[in] data_out Pointer to buffer with data to send to SPI transmitter
  898. \param[out] data_in Pointer to buffer for data to receive from SPI receiver
  899. \param[in] num_out Number of data items to send
  900. \param[in] num_in Number of data items to receive
  901. \param[in] block_mode blocking and non_blocking to selcect
  902. \return error code
  903. */
  904. int32_t csi_spi_transfer(spi_handle_t handle, const void *data_out, void *data_in, uint32_t num_out, uint32_t num_in, uint8_t block_mode)
  905. {
  906. if (handle == NULL || data_in == NULL || num_out == 0 || num_in == 0 || data_out == NULL) {
  907. return ERR_SPI(EDRV_PARAMETER);
  908. }
  909. dw_spi_priv_t *spi_priv = handle;
  910. if ((spi_priv->state & SPI_CONFIGURED) == 0U) {
  911. return ERR_SPI(EDRV_UNSUPPORTED);
  912. }
  913. if (spi_priv->status.busy) {
  914. return ERR_SPI(EDRV_BUSY);
  915. }
  916. spi_priv->status.busy = 1U;
  917. spi_priv->status.data_lost = 0U;
  918. spi_priv->status.mode_fault = 0U;
  919. #ifdef CONFIG_SPI_DMA
  920. return dw_spi_dma_transfer(spi_priv, data_out, data_in, num_out, num_in);
  921. #endif
  922. dw_spi_ss_control(spi_priv, SPI_SS_ACTIVE);
  923. dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
  924. addr->SPIENR = DW_SPI_DISABLE; /* disable SPI */
  925. dw_spi_set_mode(spi_priv, DWENUM_SPI_TXRX);
  926. addr->SER = spi_priv->enable_slave; /* enable all cs */
  927. uint8_t *ptx_buffer = (uint8_t *)data_out;
  928. uint8_t *prx_buffer = (uint8_t *)data_in;
  929. uint32_t i = 0u;
  930. if (block_mode) {
  931. for (i = 0; i < num_out; i++) { /* transmit datas in transmit-buffer */
  932. addr->DR = *ptx_buffer;
  933. ptx_buffer++;
  934. }
  935. while ((addr->SR & DW_SPI_BUSY));
  936. while ((addr->SR & DW_SPI_TFE) == 0);
  937. while ((addr->SR & DW_SPI_RFNE) == 0);
  938. addr->SPIENR = DW_SPI_DISABLE; /* disable SPI */
  939. dw_spi_set_mode(addr, DWENUM_SPI_RX);
  940. addr->SPIENR = DW_SPI_ENABLE;
  941. addr->DR = DW_SPI_START_RX;
  942. for (i = 0; i < num_in; i++) {
  943. *prx_buffer = addr->DR;
  944. prx_buffer++;
  945. }
  946. addr->SER = 0;
  947. dw_spi_ss_control(spi_priv, SPI_SS_INACTIVE);
  948. addr->SPIENR = DW_SPI_DISABLE;
  949. spi_priv->status.busy = 0U;
  950. } else {
  951. spi_priv->send_buf = ptx_buffer;
  952. spi_priv->recv_buf = prx_buffer;
  953. spi_priv->send_num = num_out;
  954. spi_priv->recv_num = num_in;
  955. spi_priv->clk_num = num_in;
  956. spi_priv->transfer_num = 0;
  957. addr->TXFTLR = DW_SPI_TXFIFO_LV;
  958. addr->SPIENR = DW_SPI_ENABLE;
  959. /* enable transmit FIFO empty interrupt */
  960. addr->IMR |= DW_SPI_IMR_TXEIM;
  961. }
  962. return 0;
  963. }
  964. /**
  965. \brief abort spi transfer.
  966. \param[in] handle spi handle to operate.
  967. \return error code
  968. */
  969. int32_t csi_spi_abort_transfer(spi_handle_t handle)
  970. {
  971. SPI_NULL_PARAM_CHK(handle);
  972. dw_spi_priv_t *spi_priv = handle;
  973. dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
  974. addr->SPIENR = DW_SPI_DISABLE;
  975. spi_priv->status.busy = 0U;
  976. spi_priv->recv_buf = NULL;
  977. spi_priv->recv_num = 0;
  978. return 0;
  979. }
  980. /**
  981. \brief Get SPI status.
  982. \param[in] handle spi handle to operate.
  983. \return SPI status \ref ARM_SPI_STATUS
  984. */
  985. spi_status_t csi_spi_get_status(spi_handle_t handle)
  986. {
  987. spi_status_t spi_status = {0};
  988. if (handle == NULL) {
  989. return spi_status;
  990. }
  991. dw_spi_priv_t *spi_priv = handle;
  992. return spi_priv->status;
  993. }