spi17y.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. /* *****************************************************************************
  2. * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included
  12. * in all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  15. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  16. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  17. * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
  18. * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20. * OTHER DEALINGS IN THE SOFTWARE.
  21. *
  22. * Except as contained in this notice, the name of Maxim Integrated
  23. * Products, Inc. shall not be used except as stated in the Maxim Integrated
  24. * Products, Inc. Branding Policy.
  25. *
  26. * The mere transfer of this software does not imply any licenses
  27. * of trade secrets, proprietary technology, copyrights, patents,
  28. * trademarks, maskwork rights, or any other form of intellectual
  29. * property whatsoever. Maxim Integrated Products, Inc. retains all
  30. * ownership rights.
  31. *
  32. * $Date: 2019-06-25 10:15:10 -0500 (Tue, 25 Jun 2019) $
  33. * $Revision: 44277 $
  34. *
  35. **************************************************************************** */
  36. /* **** Includes **** */
  37. #include <string.h>
  38. #include "mxc_config.h"
  39. #include "mxc_assert.h"
  40. #include "mxc_sys.h"
  41. #include "tmr_utils.h"
  42. #include "mxc_lock.h"
  43. #include "spi17y.h"
  44. /* **** Definitions **** */
  45. /* **** Globals **** */
  46. typedef struct {
  47. spi17y_req_t *req;
  48. int started;
  49. unsigned last_size;
  50. unsigned deass;
  51. } spi17y_req_state_t;
  52. static spi17y_req_state_t states[MXC_SPI17Y_INSTANCES];
  53. /* **** Functions **** */
  54. static int SPI17Y_TransSetup(mxc_spi17y_regs_t *spi, spi17y_req_t *req, int master);
  55. static int SPI17Y_MasterTransHandler(mxc_spi17y_regs_t *spi, spi17y_req_t *req, uint8_t async);
  56. static int SPI17Y_TransHandler(mxc_spi17y_regs_t *spi, spi17y_req_t *req, uint8_t async);
  57. static int SPI17Y_SlaveTransHandler(mxc_spi17y_regs_t *spi, spi17y_req_t *req, uint8_t async);
  58. /* ************************************************************************** */
  59. int SPI17Y_Init(mxc_spi17y_regs_t *spi, unsigned int mode, unsigned int freq,
  60. const sys_cfg_spi17y_t* sys_cfg)
  61. {
  62. uint32_t freq_div;
  63. int spi_num, error, hi_clk, lo_clk, scale;
  64. spi_num = MXC_SPI17Y_GET_IDX(spi);
  65. MXC_ASSERT(spi_num >= 0);
  66. if (mode > 3) {
  67. return E_BAD_PARAM;
  68. }
  69. if ((error = SYS_SPI17Y_Init(spi, sys_cfg)) != E_NO_ERROR) {
  70. return error;
  71. }
  72. states[spi_num].req = NULL;
  73. states[spi_num].last_size = 0;
  74. states[spi_num].deass = 1;
  75. // Enable SPI17Y
  76. spi->ctrl0 = (MXC_F_SPI17Y_CTRL0_EN);
  77. spi->ss_time = ((0x1 << MXC_F_SPI17Y_SS_TIME_PRE_POS) |
  78. (0x1 << MXC_F_SPI17Y_SS_TIME_POST_POS) |
  79. (0x1 << MXC_F_SPI17Y_SS_TIME_INACT_POS));
  80. // Check if frequency is too high
  81. if (freq > PeripheralClock) {
  82. return E_BAD_PARAM;
  83. }
  84. // Set the clock high and low
  85. freq_div = PeripheralClock/ (freq);
  86. hi_clk = freq_div/2;
  87. lo_clk = freq_div/2;
  88. scale = 0;
  89. if (freq_div %2) {
  90. hi_clk +=1;
  91. }
  92. while (hi_clk > 16 && scale < 9) {
  93. hi_clk /= 2;
  94. lo_clk /=2;
  95. scale ++;
  96. }
  97. spi->clk_cfg = ((lo_clk << MXC_F_SPI17Y_CLK_CFG_LO_POS) |
  98. (hi_clk << MXC_F_SPI17Y_CLK_CFG_HI_POS));
  99. MXC_SETFIELD(spi->clk_cfg, MXC_F_SPI17Y_CLK_CFG_SCALE, (scale << MXC_F_SPI17Y_CLK_CFG_SCALE_POS));
  100. // Set the mode
  101. spi->ctrl2 = (mode << MXC_F_SPI17Y_CTRL2_CPHA_POS);
  102. // Clear the interrupts
  103. spi->int_fl = spi->int_fl;
  104. return E_NO_ERROR;
  105. }
  106. /* ************************************************************************* */
  107. int SPI17Y_Shutdown(mxc_spi17y_regs_t *spi)
  108. {
  109. int spi_num, err;
  110. spi17y_req_t *temp_req;
  111. // Disable and clear interrupts
  112. spi->int_en = 0;
  113. spi->int_fl = spi->int_fl;
  114. // Disable SPI17Y and FIFOS
  115. spi->ctrl0 &= ~(MXC_F_SPI17Y_CTRL0_EN);
  116. spi->dma &= ~(MXC_F_SPI17Y_DMA_TX_FIFO_EN | MXC_F_SPI17Y_DMA_RX_FIFO_EN);
  117. // Call all of the pending callbacks for this SPI17Y
  118. spi_num = MXC_SPI17Y_GET_IDX(spi);
  119. if (states[spi_num].req != NULL) {
  120. // Save the request
  121. temp_req = states[spi_num].req;
  122. // Unlock this SPI17Y
  123. mxc_free_lock((uint32_t*)&states[spi_num].req);
  124. // Callback if not NULL
  125. if (temp_req->callback != NULL) {
  126. temp_req->callback(temp_req, E_SHUTDOWN);
  127. }
  128. }
  129. // Clear registers
  130. spi->ctrl0 = 0;
  131. spi->ctrl1 = 0;
  132. spi->ctrl2 = 0;
  133. spi->ss_time = 0;
  134. // Clear system level configurations
  135. if ((err = SYS_SPI17Y_Shutdown(spi)) != E_NO_ERROR) {
  136. return err;
  137. }
  138. return E_NO_ERROR;
  139. }
  140. /* ************************************************************************** */
  141. int SPI17Y_TransSetup(mxc_spi17y_regs_t *spi, spi17y_req_t *req, int master)
  142. {
  143. int spi_num;
  144. if ((req->tx_data == NULL) && (req->rx_data == NULL)) {
  145. return E_BAD_PARAM;
  146. }
  147. if ((req->width > SPI17Y_WIDTH_1) && (req->tx_data != NULL) && (req->rx_data != NULL)) {
  148. return E_BAD_PARAM;
  149. }
  150. // HW has problem with these two character sizes
  151. if (req->bits == 1 || req->bits == 9) {
  152. return E_BAD_PARAM;
  153. }
  154. spi_num = MXC_SPI17Y_GET_IDX(spi);
  155. MXC_ASSERT(spi_num >= 0);
  156. MXC_ASSERT(req->ssel < MXC_SPI17Y_SS_INSTANCES);
  157. req->tx_num = 0;
  158. req->rx_num = 0;
  159. if (req->len == 0) {
  160. return E_NO_ERROR;
  161. }
  162. states[spi_num].req = req;
  163. states[spi_num].started = 0;
  164. // HW requires disabling/renabling SPI block at end of each transaction (when SS is inactive).
  165. if (states[spi_num].deass == 1) {
  166. spi->ctrl0 &= ~(MXC_F_SPI17Y_CTRL0_EN);
  167. }
  168. if (master) {
  169. // Enable master mode
  170. spi->ctrl0 |= MXC_F_SPI17Y_CTRL0_MASTER;
  171. // Setup the slave select
  172. MXC_SETFIELD(spi->ctrl0, MXC_F_SPI17Y_CTRL0_SS, ((0x1 << req->ssel) << MXC_F_SPI17Y_CTRL0_SS_POS));
  173. spi->ctrl2 |= ((req->ssel_pol << req->ssel)<<MXC_F_SPI17Y_CTRL2_SS_POL_POS);
  174. } else {
  175. // Enable slave mode
  176. spi->ctrl0 &= ~MXC_F_SPI17Y_CTRL0_MASTER;
  177. // Setup the slave select
  178. spi->ctrl2 |= ((req->ssel_pol << 0)<<MXC_F_SPI17Y_CTRL2_SS_POL_POS);
  179. }
  180. if ((req->bits != states[spi_num].last_size)) {
  181. // Setup the character size
  182. // Master should only change character size at the end of a transaction. No restrictions on when slave can change.
  183. if (!master || (!(spi->stat & MXC_F_SPI17Y_STAT_BUSY) && (states[spi_num].deass == 1)) || !(spi->ctrl0 & MXC_F_SPI17Y_CTRL0_EN)) {
  184. //disable spi to change transfer size
  185. spi->ctrl0 &= ~(MXC_F_SPI17Y_CTRL0_EN);
  186. // set bit size
  187. states[spi_num].last_size = req->bits;
  188. if (req->bits <16) {
  189. MXC_SETFIELD(spi->ctrl2, MXC_F_SPI17Y_CTRL2_NUMBITS, req->bits << MXC_F_SPI17Y_CTRL2_NUMBITS_POS);
  190. } else {
  191. MXC_SETFIELD(spi->ctrl2, MXC_F_SPI17Y_CTRL2_NUMBITS, 0 << MXC_F_SPI17Y_CTRL2_NUMBITS_POS);
  192. }
  193. } else {
  194. // cant change transfer size while spi is busy
  195. return E_BAD_STATE;
  196. }
  197. }
  198. // Setup the data width
  199. if (req->width == SPI17Y_WIDTH_4) {
  200. MXC_SETFIELD(spi->ctrl2, MXC_F_SPI17Y_CTRL2_DATA_WIDTH, MXC_S_SPI17Y_CTRL2_DATA_WIDTH_QUAD);
  201. } else if (req->width == SPI17Y_WIDTH_2) {
  202. MXC_SETFIELD(spi->ctrl2, MXC_F_SPI17Y_CTRL2_DATA_WIDTH, MXC_S_SPI17Y_CTRL2_DATA_WIDTH_DUAL);
  203. } else {
  204. MXC_SETFIELD(spi->ctrl2, MXC_F_SPI17Y_CTRL2_DATA_WIDTH, MXC_S_SPI17Y_CTRL2_DATA_WIDTH_MONO);
  205. }
  206. // Setup the number of characters to transact
  207. if (req->len > (MXC_F_SPI17Y_CTRL1_TX_NUM_CHAR >> MXC_F_SPI17Y_CTRL1_TX_NUM_CHAR_POS)) {
  208. return E_BAD_PARAM;
  209. }
  210. if (req->rx_data != NULL) {
  211. // The TX_NUM field is used for both RX and TX length when in 4-wire mode.
  212. if(req->width == SPI17Y_WIDTH_1) {
  213. MXC_SETFIELD(spi->ctrl1, MXC_F_SPI17Y_CTRL1_TX_NUM_CHAR,
  214. req->len << MXC_F_SPI17Y_CTRL1_TX_NUM_CHAR_POS);
  215. } else {
  216. MXC_SETFIELD(spi->ctrl1, MXC_F_SPI17Y_CTRL1_RX_NUM_CHAR,
  217. req->len << MXC_F_SPI17Y_CTRL1_RX_NUM_CHAR_POS);
  218. }
  219. spi->dma |= MXC_F_SPI17Y_DMA_RX_FIFO_EN;
  220. } else {
  221. spi->ctrl1 &= ~(MXC_F_SPI17Y_CTRL1_RX_NUM_CHAR);
  222. spi->dma &= ~(MXC_F_SPI17Y_DMA_RX_FIFO_EN);
  223. }
  224. // Must use TXFIFO and NUM in full duplex
  225. if (req->width == SPI17Y_WIDTH_1
  226. && !((spi->ctrl2 & MXC_F_SPI17Y_CTRL2_THREE_WIRE)>> MXC_F_SPI17Y_CTRL2_THREE_WIRE_POS)) {
  227. if (req->tx_data == NULL) {
  228. // Must have something to send, so we'll use the rx_data buffer initialized to 0.
  229. memset(req->rx_data, 0, (req->bits > 8 ? req->len << 1 : req->len));
  230. req->tx_data = req->rx_data;
  231. req->tx_num = 0;
  232. }
  233. }
  234. if(req->tx_data != NULL) {
  235. MXC_SETFIELD(spi->ctrl1, MXC_F_SPI17Y_CTRL1_TX_NUM_CHAR,
  236. req->len << MXC_F_SPI17Y_CTRL1_TX_NUM_CHAR_POS);
  237. spi->dma |= MXC_F_SPI17Y_DMA_TX_FIFO_EN;
  238. } else {
  239. spi->dma &= ~(MXC_F_SPI17Y_DMA_TX_FIFO_EN);
  240. }
  241. spi->dma |= MXC_F_SPI17Y_DMA_TX_FIFO_CLEAR | MXC_F_SPI17Y_DMA_RX_FIFO_CLEAR;
  242. spi->ctrl0 |= (MXC_F_SPI17Y_CTRL0_EN);
  243. states[spi_num].deass = req->deass;
  244. // Clear master done flag
  245. spi->int_fl = MXC_F_SPI17Y_INT_FL_M_DONE;
  246. return E_NO_ERROR;
  247. }
  248. /* ************************************************************************** */
  249. void SPI17Y_Handler(mxc_spi17y_regs_t *spi)
  250. {
  251. int spi_num, rx_avail;
  252. uint32_t flags;
  253. // Clear the interrupt flags
  254. spi->int_en = 0;
  255. flags = spi->int_fl;
  256. spi->int_fl = flags;
  257. spi_num = MXC_SPI17Y_GET_IDX(spi);
  258. // Figure out if this SPI17Y has an active request
  259. if ((states[spi_num].req != NULL) && (flags)) {
  260. if ((spi->ctrl0 & MXC_F_SPI17Y_CTRL0_MASTER)>> MXC_F_SPI17Y_CTRL0_MASTER_POS) {
  261. do {
  262. SPI17Y_MasterTransHandler(spi, states[spi_num].req, 1);
  263. rx_avail = (spi->dma & MXC_F_SPI17Y_DMA_RX_FIFO_CNT) >> MXC_F_SPI17Y_DMA_RX_FIFO_CNT_POS;
  264. } while ((states[spi_num].req->rx_data != NULL) && (rx_avail > (spi->dma & MXC_F_SPI17Y_DMA_RX_FIFO_LEVEL)
  265. >>MXC_F_SPI17Y_DMA_RX_FIFO_LEVEL_POS));
  266. } else {
  267. do {
  268. SPI17Y_SlaveTransHandler(spi, states[spi_num].req, 1);
  269. rx_avail = (spi->dma & MXC_F_SPI17Y_DMA_RX_FIFO_CNT) >> MXC_F_SPI17Y_DMA_RX_FIFO_CNT_POS;
  270. } while ((states[spi_num].req->rx_data != NULL) && (rx_avail > (spi->dma & MXC_F_SPI17Y_DMA_RX_FIFO_LEVEL)
  271. >>MXC_F_SPI17Y_DMA_RX_FIFO_LEVEL_POS));
  272. }
  273. }
  274. }
  275. /* ************************************************************************** */
  276. int SPI17Y_MasterTrans(mxc_spi17y_regs_t *spi,spi17y_req_t *req)
  277. {
  278. int error;
  279. if ((error =SPI17Y_TransSetup(spi, req, 1)) != E_NO_ERROR) {
  280. return error;
  281. }
  282. req->callback = NULL;
  283. while (SPI17Y_MasterTransHandler(spi,req,0)==0) {
  284. }
  285. while (!(spi->int_fl & MXC_F_SPI17Y_INT_FL_M_DONE)) {
  286. }
  287. return E_NO_ERROR;
  288. }
  289. /* ************************************************************************** */
  290. int SPI17Y_SlaveTrans(mxc_spi17y_regs_t *spi, spi17y_req_t *req)
  291. {
  292. int error;
  293. if ((error =SPI17Y_TransSetup(spi, req,0)) != E_NO_ERROR) {
  294. return error;
  295. }
  296. req->callback = NULL;
  297. while (SPI17Y_SlaveTransHandler(spi,req,0)==0) {
  298. }
  299. return E_NO_ERROR;
  300. }
  301. /* ************************************************************************** */
  302. int SPI17Y_MasterTransAsync(mxc_spi17y_regs_t *spi, spi17y_req_t *req)
  303. {
  304. int error;
  305. if ((error =SPI17Y_TransSetup(spi, req, 1))!= E_NO_ERROR) {
  306. return error;
  307. }
  308. SPI17Y_MasterTransHandler(spi,req, 1);
  309. return E_NO_ERROR;
  310. }
  311. /* ************************************************************************** */
  312. int SPI17Y_SlaveTransAsync(mxc_spi17y_regs_t *spi, spi17y_req_t *req)
  313. {
  314. int error;
  315. if ((error =SPI17Y_TransSetup(spi, req, 0)) != E_NO_ERROR) {
  316. return error;
  317. }
  318. SPI17Y_SlaveTransHandler(spi,req, 1);
  319. return E_NO_ERROR;
  320. }
  321. /* ************************************************************************** */
  322. int SPI17Y_MasterTransHandler(mxc_spi17y_regs_t *spi, spi17y_req_t *req,uint8_t async)
  323. {
  324. int retval;
  325. int spi_num;
  326. spi_num = MXC_SPI17Y_GET_IDX(spi);
  327. // Leave slave select asserted at the end of the transaction
  328. if (!req->deass) {
  329. spi->ctrl0 |= MXC_F_SPI17Y_CTRL0_SS_CTRL;
  330. }
  331. retval = SPI17Y_TransHandler(spi,req, async);
  332. if (!states[spi_num].started) {
  333. spi->ctrl0 |= MXC_F_SPI17Y_CTRL0_START;
  334. states[spi_num].started = 1;
  335. }
  336. // Deassert slave select at the end of the transaction
  337. if (req->deass) {
  338. spi->ctrl0 &= ~MXC_F_SPI17Y_CTRL0_SS_CTRL;
  339. }
  340. return retval;
  341. }
  342. /* ************************************************************************** */
  343. int SPI17Y_SlaveTransHandler(mxc_spi17y_regs_t *spi, spi17y_req_t *req, uint8_t async)
  344. {
  345. return SPI17Y_TransHandler(spi,req, async);
  346. }
  347. /* ************************************************************************** */
  348. // Returns non-zero if transactions is complete, or 0 if not.
  349. int SPI17Y_TransHandler(mxc_spi17y_regs_t *spi, spi17y_req_t *req, uint8_t async)
  350. {
  351. unsigned tx_avail, rx_avail;
  352. int remain, spi_num;
  353. uint32_t int_en =0;
  354. uint32_t length =0;
  355. spi_num = MXC_SPI17Y_GET_IDX(spi);
  356. // Read/write 2x number of bytes if larger character size
  357. if (req->bits > 8) {
  358. length = req->len*2;
  359. } else {
  360. length = req->len;
  361. }
  362. if (req->tx_data != NULL) {
  363. // Need to know when all bytes are transmitted, so the callback can be triggered.
  364. int_en |= MXC_F_SPI17Y_INT_EN_TX_EMPTY;
  365. // Calculate how many bytes we can write to the FIFO
  366. tx_avail = MXC_SPI17Y_FIFO_DEPTH - ((spi->dma & MXC_F_SPI17Y_DMA_TX_FIFO_CNT) >>
  367. MXC_F_SPI17Y_DMA_TX_FIFO_CNT_POS);
  368. if ((length - req->tx_num) < tx_avail) {
  369. tx_avail = (length - req->tx_num);
  370. }
  371. if (req->bits > 8) {
  372. tx_avail &= ~(unsigned)0x1;
  373. }
  374. // Write the FIFO
  375. while (tx_avail) {
  376. if (tx_avail > 3) {
  377. memcpy((void*)&spi->data32,&((uint8_t*)req->tx_data)[req->tx_num], 4);
  378. tx_avail -= 4;
  379. req->tx_num += 4;
  380. } else if (tx_avail > 1) {
  381. memcpy((void*)&spi->data16[0],&((uint8_t*)req->tx_data)[req->tx_num], 2);
  382. tx_avail -= 2;
  383. req->tx_num += 2;
  384. } else if (req->bits<=8) {
  385. spi->data8[0] = ((uint8_t*)req->tx_data)[req->tx_num++];
  386. tx_avail -= 1;
  387. }
  388. }
  389. }
  390. remain = length - req->tx_num;
  391. // Set the TX interrupts
  392. if (remain) {
  393. if (remain > MXC_SPI17Y_FIFO_DEPTH) {
  394. // Set the TX FIFO almost empty interrupt if we have to refill
  395. spi->dma = ((spi->dma & ~MXC_F_SPI17Y_DMA_TX_FIFO_LEVEL) |
  396. ((MXC_SPI17Y_FIFO_DEPTH) << MXC_F_SPI17Y_DMA_TX_FIFO_LEVEL_POS));
  397. } else {
  398. spi->dma = ((spi->dma & ~MXC_F_SPI17Y_DMA_TX_FIFO_LEVEL) |
  399. ((remain) << MXC_F_SPI17Y_DMA_TX_FIFO_LEVEL_POS));
  400. }
  401. int_en |= MXC_F_SPI17Y_INT_EN_TX_THRESH;
  402. }
  403. // Break out if we've transmitted all the bytes and not receiving
  404. if ((req->rx_data == NULL) && (req->tx_num == length) && ((spi->dma & MXC_F_SPI17Y_DMA_TX_FIFO_CNT) == 0)) {
  405. spi->int_en = 0;
  406. int_en = 0;
  407. mxc_free_lock((uint32_t*)&states[spi_num].req);
  408. // Callback if not NULL
  409. if (req->callback != NULL) {
  410. req->callback(req, E_NO_ERROR);
  411. }
  412. return 1;
  413. }
  414. // Read the RX FIFO
  415. if (req->rx_data != NULL) {
  416. // Wait for there to be data in the RX FIFO
  417. rx_avail = (spi->dma & MXC_F_SPI17Y_DMA_RX_FIFO_CNT) >> MXC_F_SPI17Y_DMA_RX_FIFO_CNT_POS;
  418. if ((length - req->rx_num) < rx_avail) {
  419. rx_avail = (length - req->rx_num);
  420. }
  421. if (req->bits <= 8 || rx_avail >= 2) {
  422. // Read from the FIFO
  423. while (rx_avail) {
  424. if (rx_avail > 3) {
  425. memcpy(&((uint8_t*)req->rx_data)[req->rx_num], (void*)&spi->data32, 4);
  426. rx_avail -= 4;
  427. req->rx_num += 4;
  428. } else if (rx_avail > 1) {
  429. memcpy(&((uint8_t*)req->rx_data)[req->rx_num], (void*)&spi->data16[0], 2);
  430. rx_avail -= 2;
  431. req->rx_num += 2;
  432. } else {
  433. ((uint8_t*)req->rx_data)[req->rx_num++] = spi->data8[0];
  434. rx_avail -= 1;
  435. }
  436. // Don't read less than 2 bytes if we are using greater than 8 bit characters
  437. if (rx_avail == 1 && req->bits > 8) {
  438. break;
  439. }
  440. }
  441. }
  442. remain = length - req->rx_num;
  443. if (remain) {
  444. if (remain > MXC_SPI17Y_FIFO_DEPTH) {
  445. spi->dma = ((spi->dma & ~MXC_F_SPI17Y_DMA_RX_FIFO_LEVEL) |
  446. ((2) << MXC_F_SPI17Y_DMA_RX_FIFO_LEVEL_POS));
  447. } else {
  448. spi->dma = ((spi->dma & ~MXC_F_SPI17Y_DMA_RX_FIFO_LEVEL) |
  449. ((remain-1) << MXC_F_SPI17Y_DMA_RX_FIFO_LEVEL_POS));
  450. }
  451. int_en |= MXC_F_SPI17Y_INT_EN_RX_THRESH;
  452. }
  453. // Break out if we've received all the bytes and we're not transmitting
  454. if ((req->tx_data == NULL) && (req->rx_num == length)) {
  455. spi->int_en = 0;
  456. int_en = 0;
  457. mxc_free_lock((uint32_t*)&states[spi_num].req);
  458. // Callback if not NULL
  459. if (req->callback != NULL) {
  460. req->callback(req, E_NO_ERROR);
  461. }
  462. return 1;
  463. }
  464. }
  465. // Break out once we've transmitted and received all of the data
  466. if ((req->rx_num == length) && (req->tx_num == length) && ((spi->dma & MXC_F_SPI17Y_DMA_TX_FIFO_CNT) == 0)) {
  467. spi->int_en = 0;
  468. int_en = 0;
  469. mxc_free_lock((uint32_t*)&states[spi_num].req);
  470. // Callback if not NULL
  471. if (req->callback != NULL) {
  472. req->callback(req, E_NO_ERROR);
  473. }
  474. return 1;
  475. }
  476. if(async){
  477. spi->int_en = int_en;
  478. }
  479. return 0;
  480. }
  481. /* ************************************************************************* */
  482. int SPI17Y_AbortAsync(spi17y_req_t *req)
  483. {
  484. int spi_num;
  485. mxc_spi17y_regs_t *spi;
  486. // Check the input parameters
  487. if (req == NULL) {
  488. return E_BAD_PARAM;
  489. }
  490. // Find the request, set to NULL
  491. for (spi_num = 0; spi_num < MXC_SPI17Y_INSTANCES; spi_num++) {
  492. if (req == states[spi_num].req) {
  493. spi = MXC_SPI17Y_GET_SPI17Y(spi_num);
  494. // Disable interrupts, clear the flags
  495. spi->int_en = 0;
  496. spi->int_fl = spi->int_fl;
  497. // Reset the SPI17Y to cancel the on ongoing transaction
  498. spi->ctrl0 &= ~(MXC_F_SPI17Y_CTRL0_EN);
  499. spi->ctrl0 |= (MXC_F_SPI17Y_CTRL0_EN);
  500. // Unlock this SPI17Y
  501. mxc_free_lock((uint32_t*)&states[spi_num].req);
  502. // Callback if not NULL
  503. if (req->callback != NULL) {
  504. req->callback(req, E_ABORT);
  505. }
  506. return E_NO_ERROR;
  507. }
  508. }
  509. return E_BAD_PARAM;
  510. }
  511. // *****************************************************************************
  512. void SPI17Y_Enable(mxc_spi17y_regs_t* spi)
  513. {
  514. spi->ctrl0 |= (MXC_F_SPI17Y_CTRL0_EN);
  515. }
  516. // *****************************************************************************
  517. void SPI17Y_Disable(mxc_spi17y_regs_t* spi)
  518. {
  519. spi->ctrl0 &= ~(MXC_F_SPI17Y_CTRL0_EN);
  520. }
  521. // *****************************************************************************
  522. void SPI17Y_Clear_fifo(mxc_spi17y_regs_t* spi)
  523. {
  524. spi->dma |= MXC_F_SPI17Y_DMA_TX_FIFO_CLEAR | MXC_F_SPI17Y_DMA_RX_FIFO_CLEAR;
  525. }