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
37 /* **** Includes **** */
38 #include <string.h>
39 #include "mxc_config.h"
40 #include "mxc_assert.h"
41 #include "mxc_sys.h"
42 #include "tmr_utils.h"
43 #include "mxc_lock.h"
44 #include "spi17y.h"
45
46 /* **** Definitions **** */
47
48 /* **** Globals **** */
49
50
51 typedef struct {
52 spi17y_req_t *req;
53 int started;
54 unsigned last_size;
55 unsigned deass;
56 } spi17y_req_state_t;
57
58 static spi17y_req_state_t states[MXC_SPI17Y_INSTANCES];
59
60 /* **** Functions **** */
61 static int SPI17Y_TransSetup(mxc_spi17y_regs_t *spi, spi17y_req_t *req, int master);
62 static int SPI17Y_MasterTransHandler(mxc_spi17y_regs_t *spi, spi17y_req_t *req, uint8_t async);
63 static int SPI17Y_TransHandler(mxc_spi17y_regs_t *spi, spi17y_req_t *req, uint8_t async);
64 static int SPI17Y_SlaveTransHandler(mxc_spi17y_regs_t *spi, spi17y_req_t *req, uint8_t async);
65
66 /* ************************************************************************** */
SPI17Y_Init(mxc_spi17y_regs_t * spi,unsigned int mode,unsigned int freq,const sys_cfg_spi17y_t * sys_cfg)67 int SPI17Y_Init(mxc_spi17y_regs_t *spi, unsigned int mode, unsigned int freq,
68 const sys_cfg_spi17y_t* sys_cfg)
69 {
70 uint32_t freq_div;
71 int spi_num, error, hi_clk, lo_clk, scale;
72
73 spi_num = MXC_SPI17Y_GET_IDX(spi);
74 MXC_ASSERT(spi_num >= 0);
75
76 if (mode > 3) {
77 return E_BAD_PARAM;
78 }
79
80 if ((error = SYS_SPI17Y_Init(spi, sys_cfg)) != E_NO_ERROR) {
81 return error;
82 }
83
84 states[spi_num].req = NULL;
85 states[spi_num].last_size = 0;
86 states[spi_num].deass = 1;
87
88 // Enable SPI17Y
89 spi->ctrl0 = (MXC_F_SPI17Y_CTRL0_EN);
90 spi->ss_time = ((0x1 << MXC_F_SPI17Y_SS_TIME_PRE_POS) |
91 (0x1 << MXC_F_SPI17Y_SS_TIME_POST_POS) |
92 (0x1 << MXC_F_SPI17Y_SS_TIME_INACT_POS));
93
94 // Check if frequency is too high
95 if (freq > PeripheralClock) {
96 return E_BAD_PARAM;
97 }
98
99 // Set the clock high and low
100 freq_div = PeripheralClock/ (freq);
101 hi_clk = freq_div/2;
102 lo_clk = freq_div/2;
103 scale = 0;
104
105 if (freq_div %2) {
106 hi_clk +=1;
107 }
108
109 while (hi_clk > 16 && scale < 9) {
110 hi_clk /= 2;
111 lo_clk /=2;
112 scale ++;
113 }
114
115 spi->clk_cfg = ((lo_clk << MXC_F_SPI17Y_CLK_CFG_LO_POS) |
116 (hi_clk << MXC_F_SPI17Y_CLK_CFG_HI_POS));
117
118 MXC_SETFIELD(spi->clk_cfg, MXC_F_SPI17Y_CLK_CFG_SCALE, (scale << MXC_F_SPI17Y_CLK_CFG_SCALE_POS));
119
120 // Set the mode
121 spi->ctrl2 = (mode << MXC_F_SPI17Y_CTRL2_CPHA_POS);
122
123 // Clear the interrupts
124 spi->int_fl = spi->int_fl;
125
126 return E_NO_ERROR;
127 }
128
129 /* ************************************************************************* */
SPI17Y_Shutdown(mxc_spi17y_regs_t * spi)130 int SPI17Y_Shutdown(mxc_spi17y_regs_t *spi)
131 {
132 int spi_num, err;
133 spi17y_req_t *temp_req;
134
135 // Disable and clear interrupts
136 spi->int_en = 0;
137 spi->int_fl = spi->int_fl;
138
139 // Disable SPI17Y and FIFOS
140 spi->ctrl0 &= ~(MXC_F_SPI17Y_CTRL0_EN);
141 spi->dma &= ~(MXC_F_SPI17Y_DMA_TX_FIFO_EN | MXC_F_SPI17Y_DMA_RX_FIFO_EN);
142
143 // Call all of the pending callbacks for this SPI17Y
144 spi_num = MXC_SPI17Y_GET_IDX(spi);
145 if (states[spi_num].req != NULL) {
146
147 // Save the request
148 temp_req = states[spi_num].req;
149
150 // Unlock this SPI17Y
151 mxc_free_lock((uint32_t*)&states[spi_num].req);
152
153 // Callback if not NULL
154 if (temp_req->callback != NULL) {
155 temp_req->callback(temp_req, E_SHUTDOWN);
156 }
157 }
158
159 // Clear registers
160 spi->ctrl0 = 0;
161 spi->ctrl1 = 0;
162 spi->ctrl2 = 0;
163 spi->ss_time = 0;
164
165 // Clear system level configurations
166 if ((err = SYS_SPI17Y_Shutdown(spi)) != E_NO_ERROR) {
167 return err;
168 }
169
170 return E_NO_ERROR;
171 }
172
173 /* ************************************************************************** */
SPI17Y_TransSetup(mxc_spi17y_regs_t * spi,spi17y_req_t * req,int master)174 int SPI17Y_TransSetup(mxc_spi17y_regs_t *spi, spi17y_req_t *req, int master)
175 {
176 int spi_num;
177 if ((req->tx_data == NULL) && (req->rx_data == NULL)) {
178 return E_BAD_PARAM;
179 }
180
181 if ((req->width > SPI17Y_WIDTH_1) && (req->tx_data != NULL) && (req->rx_data != NULL)) {
182 return E_BAD_PARAM;
183 }
184
185 // HW has problem with these two character sizes
186 if (req->bits == 1 || req->bits == 9) {
187 return E_BAD_PARAM;
188 }
189 spi_num = MXC_SPI17Y_GET_IDX(spi);
190 MXC_ASSERT(spi_num >= 0);
191 MXC_ASSERT(req->ssel < MXC_SPI17Y_SS_INSTANCES);
192
193 req->tx_num = 0;
194 req->rx_num = 0;
195
196 if (req->len == 0) {
197 return E_NO_ERROR;
198 }
199
200 states[spi_num].req = req;
201 states[spi_num].started = 0;
202
203 // HW requires disabling/renabling SPI block at end of each transaction (when SS is inactive).
204 if (states[spi_num].deass == 1) {
205 spi->ctrl0 &= ~(MXC_F_SPI17Y_CTRL0_EN);
206 }
207
208 if (master) {
209 // Enable master mode
210
211 spi->ctrl0 |= MXC_F_SPI17Y_CTRL0_MASTER;
212
213 // Setup the slave select
214 MXC_SETFIELD(spi->ctrl0, MXC_F_SPI17Y_CTRL0_SS, ((0x1 << req->ssel) << MXC_F_SPI17Y_CTRL0_SS_POS));
215 spi->ctrl2 |= ((req->ssel_pol << req->ssel)<<MXC_F_SPI17Y_CTRL2_SS_POL_POS);
216 } else {
217 // Enable slave mode
218 spi->ctrl0 &= ~MXC_F_SPI17Y_CTRL0_MASTER;
219 // Setup the slave select
220 spi->ctrl2 |= ((req->ssel_pol << 0)<<MXC_F_SPI17Y_CTRL2_SS_POL_POS);
221 }
222
223 if ((req->bits != states[spi_num].last_size)) {
224 // Setup the character size
225 // Master should only change character size at the end of a transaction. No restrictions on when slave can change.
226 if (!master || (!(spi->stat & MXC_F_SPI17Y_STAT_BUSY) && (states[spi_num].deass == 1)) || !(spi->ctrl0 & MXC_F_SPI17Y_CTRL0_EN)) {
227 //disable spi to change transfer size
228 spi->ctrl0 &= ~(MXC_F_SPI17Y_CTRL0_EN);
229 // set bit size
230 states[spi_num].last_size = req->bits;
231 if (req->bits <16) {
232 MXC_SETFIELD(spi->ctrl2, MXC_F_SPI17Y_CTRL2_NUMBITS, req->bits << MXC_F_SPI17Y_CTRL2_NUMBITS_POS);
233 } else {
234 MXC_SETFIELD(spi->ctrl2, MXC_F_SPI17Y_CTRL2_NUMBITS, 0 << MXC_F_SPI17Y_CTRL2_NUMBITS_POS);
235 }
236 } else {
237 // cant change transfer size while spi is busy
238 return E_BAD_STATE;
239 }
240 }
241
242 // Setup the data width
243 if (req->width == SPI17Y_WIDTH_4) {
244 MXC_SETFIELD(spi->ctrl2, MXC_F_SPI17Y_CTRL2_DATA_WIDTH, MXC_S_SPI17Y_CTRL2_DATA_WIDTH_QUAD);
245 } else if (req->width == SPI17Y_WIDTH_2) {
246 MXC_SETFIELD(spi->ctrl2, MXC_F_SPI17Y_CTRL2_DATA_WIDTH, MXC_S_SPI17Y_CTRL2_DATA_WIDTH_DUAL);
247 } else {
248 MXC_SETFIELD(spi->ctrl2, MXC_F_SPI17Y_CTRL2_DATA_WIDTH, MXC_S_SPI17Y_CTRL2_DATA_WIDTH_MONO);
249 }
250
251 // Setup the number of characters to transact
252 if (req->len > (MXC_F_SPI17Y_CTRL1_TX_NUM_CHAR >> MXC_F_SPI17Y_CTRL1_TX_NUM_CHAR_POS)) {
253 return E_BAD_PARAM;
254 }
255
256 if (req->rx_data != NULL) {
257 // The TX_NUM field is used for both RX and TX length when in 4-wire mode.
258 if(req->width == SPI17Y_WIDTH_1) {
259 MXC_SETFIELD(spi->ctrl1, MXC_F_SPI17Y_CTRL1_TX_NUM_CHAR,
260 req->len << MXC_F_SPI17Y_CTRL1_TX_NUM_CHAR_POS);
261 } else {
262 MXC_SETFIELD(spi->ctrl1, MXC_F_SPI17Y_CTRL1_RX_NUM_CHAR,
263 req->len << MXC_F_SPI17Y_CTRL1_RX_NUM_CHAR_POS);
264 }
265 spi->dma |= MXC_F_SPI17Y_DMA_RX_FIFO_EN;
266 } else {
267 spi->ctrl1 &= ~(MXC_F_SPI17Y_CTRL1_RX_NUM_CHAR);
268 spi->dma &= ~(MXC_F_SPI17Y_DMA_RX_FIFO_EN);
269 }
270
271 // Must use TXFIFO and NUM in full duplex
272 if (req->width == SPI17Y_WIDTH_1
273 && !((spi->ctrl2 & MXC_F_SPI17Y_CTRL2_THREE_WIRE)>> MXC_F_SPI17Y_CTRL2_THREE_WIRE_POS)) {
274
275 if (req->tx_data == NULL) {
276 // Must have something to send, so we'll use the rx_data buffer initialized to 0.
277 memset(req->rx_data, 0, (req->bits > 8 ? req->len << 1 : req->len));
278 req->tx_data = req->rx_data;
279 req->tx_num = 0;
280 }
281 }
282
283 if(req->tx_data != NULL) {
284 MXC_SETFIELD(spi->ctrl1, MXC_F_SPI17Y_CTRL1_TX_NUM_CHAR,
285 req->len << MXC_F_SPI17Y_CTRL1_TX_NUM_CHAR_POS);
286 spi->dma |= MXC_F_SPI17Y_DMA_TX_FIFO_EN;
287 } else {
288 spi->dma &= ~(MXC_F_SPI17Y_DMA_TX_FIFO_EN);
289 }
290
291 spi->dma |= MXC_F_SPI17Y_DMA_TX_FIFO_CLEAR | MXC_F_SPI17Y_DMA_RX_FIFO_CLEAR;
292 spi->ctrl0 |= (MXC_F_SPI17Y_CTRL0_EN);
293
294 states[spi_num].deass = req->deass;
295 // Clear master done flag
296 spi->int_fl = MXC_F_SPI17Y_INT_FL_M_DONE;
297 return E_NO_ERROR;
298 }
299
300 /* ************************************************************************** */
SPI17Y_Handler(mxc_spi17y_regs_t * spi)301 void SPI17Y_Handler(mxc_spi17y_regs_t *spi)
302 {
303 int spi_num, rx_avail;
304 uint32_t flags;
305
306 // Clear the interrupt flags
307 spi->int_en = 0;
308 flags = spi->int_fl;
309 spi->int_fl = flags;
310
311 spi_num = MXC_SPI17Y_GET_IDX(spi);
312 // Figure out if this SPI17Y has an active request
313 if ((states[spi_num].req != NULL) && (flags)) {
314 if ((spi->ctrl0 & MXC_F_SPI17Y_CTRL0_MASTER)>> MXC_F_SPI17Y_CTRL0_MASTER_POS) {
315 do {
316 SPI17Y_MasterTransHandler(spi, states[spi_num].req, 1);
317 rx_avail = (spi->dma & MXC_F_SPI17Y_DMA_RX_FIFO_CNT) >> MXC_F_SPI17Y_DMA_RX_FIFO_CNT_POS;
318 } while ((states[spi_num].req->rx_data != NULL) && (rx_avail > (spi->dma & MXC_F_SPI17Y_DMA_RX_FIFO_LEVEL)
319 >>MXC_F_SPI17Y_DMA_RX_FIFO_LEVEL_POS));
320
321 } else {
322 do {
323 SPI17Y_SlaveTransHandler(spi, states[spi_num].req, 1);
324 rx_avail = (spi->dma & MXC_F_SPI17Y_DMA_RX_FIFO_CNT) >> MXC_F_SPI17Y_DMA_RX_FIFO_CNT_POS;
325 } while ((states[spi_num].req->rx_data != NULL) && (rx_avail > (spi->dma & MXC_F_SPI17Y_DMA_RX_FIFO_LEVEL)
326 >>MXC_F_SPI17Y_DMA_RX_FIFO_LEVEL_POS));
327
328 }
329 }
330
331 }
332
333 /* ************************************************************************** */
SPI17Y_MasterTrans(mxc_spi17y_regs_t * spi,spi17y_req_t * req)334 int SPI17Y_MasterTrans(mxc_spi17y_regs_t *spi,spi17y_req_t *req)
335 {
336 int error;
337 if ((error =SPI17Y_TransSetup(spi, req, 1)) != E_NO_ERROR) {
338 return error;
339 }
340 req->callback = NULL;
341
342 while (SPI17Y_MasterTransHandler(spi,req,0)==0) {
343 }
344
345 while (!(spi->int_fl & MXC_F_SPI17Y_INT_FL_M_DONE)) {
346
347 }
348
349 return E_NO_ERROR;
350 }
351
352
353 /* ************************************************************************** */
SPI17Y_SlaveTrans(mxc_spi17y_regs_t * spi,spi17y_req_t * req)354 int SPI17Y_SlaveTrans(mxc_spi17y_regs_t *spi, spi17y_req_t *req)
355 {
356 int error;
357 if ((error =SPI17Y_TransSetup(spi, req,0)) != E_NO_ERROR) {
358 return error;
359 }
360 req->callback = NULL;
361
362 while (SPI17Y_SlaveTransHandler(spi,req,0)==0) {
363
364 }
365
366 return E_NO_ERROR;
367 }
368
369 /* ************************************************************************** */
SPI17Y_MasterTransAsync(mxc_spi17y_regs_t * spi,spi17y_req_t * req)370 int SPI17Y_MasterTransAsync(mxc_spi17y_regs_t *spi, spi17y_req_t *req)
371 {
372 int error;
373 if ((error =SPI17Y_TransSetup(spi, req, 1))!= E_NO_ERROR) {
374 return error;
375 }
376
377 SPI17Y_MasterTransHandler(spi,req, 1);
378
379 return E_NO_ERROR;
380 }
381
382 /* ************************************************************************** */
SPI17Y_SlaveTransAsync(mxc_spi17y_regs_t * spi,spi17y_req_t * req)383 int SPI17Y_SlaveTransAsync(mxc_spi17y_regs_t *spi, spi17y_req_t *req)
384 {
385 int error;
386 if ((error =SPI17Y_TransSetup(spi, req, 0)) != E_NO_ERROR) {
387 return error;
388 }
389
390 SPI17Y_SlaveTransHandler(spi,req, 1);
391
392
393 return E_NO_ERROR;
394 }
395
396 /* ************************************************************************** */
SPI17Y_MasterTransHandler(mxc_spi17y_regs_t * spi,spi17y_req_t * req,uint8_t async)397 int SPI17Y_MasterTransHandler(mxc_spi17y_regs_t *spi, spi17y_req_t *req,uint8_t async)
398 {
399 int retval;
400 int spi_num;
401
402 spi_num = MXC_SPI17Y_GET_IDX(spi);
403
404 // Leave slave select asserted at the end of the transaction
405 if (!req->deass) {
406 spi->ctrl0 |= MXC_F_SPI17Y_CTRL0_SS_CTRL;
407 }
408
409 retval = SPI17Y_TransHandler(spi,req, async);
410
411 if (!states[spi_num].started) {
412 spi->ctrl0 |= MXC_F_SPI17Y_CTRL0_START;
413 states[spi_num].started = 1;
414 }
415
416 // Deassert slave select at the end of the transaction
417 if (req->deass) {
418 spi->ctrl0 &= ~MXC_F_SPI17Y_CTRL0_SS_CTRL;
419 }
420
421 return retval;
422 }
423
424 /* ************************************************************************** */
SPI17Y_SlaveTransHandler(mxc_spi17y_regs_t * spi,spi17y_req_t * req,uint8_t async)425 int SPI17Y_SlaveTransHandler(mxc_spi17y_regs_t *spi, spi17y_req_t *req, uint8_t async)
426 {
427 return SPI17Y_TransHandler(spi,req, async);
428 }
429
430 /* ************************************************************************** */
431 // Returns non-zero if transactions is complete, or 0 if not.
SPI17Y_TransHandler(mxc_spi17y_regs_t * spi,spi17y_req_t * req,uint8_t async)432 int SPI17Y_TransHandler(mxc_spi17y_regs_t *spi, spi17y_req_t *req, uint8_t async)
433 {
434
435 unsigned tx_avail, rx_avail;
436 int remain, spi_num;
437 uint32_t int_en =0;
438 uint32_t length =0;
439 spi_num = MXC_SPI17Y_GET_IDX(spi);
440
441 // Read/write 2x number of bytes if larger character size
442 if (req->bits > 8) {
443 length = req->len*2;
444 } else {
445 length = req->len;
446 }
447
448 if (req->tx_data != NULL) {
449 // Need to know when all bytes are transmitted, so the callback can be triggered.
450 int_en |= MXC_F_SPI17Y_INT_EN_TX_EMPTY;
451
452 // Calculate how many bytes we can write to the FIFO
453 tx_avail = MXC_SPI17Y_FIFO_DEPTH - ((spi->dma & MXC_F_SPI17Y_DMA_TX_FIFO_CNT) >>
454 MXC_F_SPI17Y_DMA_TX_FIFO_CNT_POS);
455 if ((length - req->tx_num) < tx_avail) {
456 tx_avail = (length - req->tx_num);
457 }
458 if (req->bits > 8) {
459 tx_avail &= ~(unsigned)0x1;
460 }
461 // Write the FIFO
462 while (tx_avail) {
463 if (tx_avail > 3) {
464 memcpy((void*)&spi->data32,&((uint8_t*)req->tx_data)[req->tx_num], 4);
465
466 tx_avail -= 4;
467 req->tx_num += 4;
468
469 } else if (tx_avail > 1) {
470 memcpy((void*)&spi->data16[0],&((uint8_t*)req->tx_data)[req->tx_num], 2);
471
472 tx_avail -= 2;
473 req->tx_num += 2;
474
475 } else if (req->bits<=8) {
476 spi->data8[0] = ((uint8_t*)req->tx_data)[req->tx_num++];
477
478 tx_avail -= 1;
479 }
480 }
481 }
482
483 remain = length - req->tx_num;
484
485 // Set the TX interrupts
486 if (remain) {
487 if (remain > MXC_SPI17Y_FIFO_DEPTH) {
488 // Set the TX FIFO almost empty interrupt if we have to refill
489 spi->dma = ((spi->dma & ~MXC_F_SPI17Y_DMA_TX_FIFO_LEVEL) |
490 ((MXC_SPI17Y_FIFO_DEPTH) << MXC_F_SPI17Y_DMA_TX_FIFO_LEVEL_POS));
491 } else {
492
493 spi->dma = ((spi->dma & ~MXC_F_SPI17Y_DMA_TX_FIFO_LEVEL) |
494 ((remain) << MXC_F_SPI17Y_DMA_TX_FIFO_LEVEL_POS));
495 }
496 int_en |= MXC_F_SPI17Y_INT_EN_TX_THRESH;
497
498 }
499 // Break out if we've transmitted all the bytes and not receiving
500 if ((req->rx_data == NULL) && (req->tx_num == length) && ((spi->dma & MXC_F_SPI17Y_DMA_TX_FIFO_CNT) == 0)) {
501 spi->int_en = 0;
502 int_en = 0;
503 mxc_free_lock((uint32_t*)&states[spi_num].req);
504 // Callback if not NULL
505 if (req->callback != NULL) {
506 req->callback(req, E_NO_ERROR);
507 }
508 return 1;
509 }
510
511
512 // Read the RX FIFO
513 if (req->rx_data != NULL) {
514
515 // Wait for there to be data in the RX FIFO
516 rx_avail = (spi->dma & MXC_F_SPI17Y_DMA_RX_FIFO_CNT) >> MXC_F_SPI17Y_DMA_RX_FIFO_CNT_POS;
517 if ((length - req->rx_num) < rx_avail) {
518 rx_avail = (length - req->rx_num);
519 }
520 if (req->bits <= 8 || rx_avail >= 2) {
521 // Read from the FIFO
522 while (rx_avail) {
523 if (rx_avail > 3) {
524 memcpy(&((uint8_t*)req->rx_data)[req->rx_num], (void*)&spi->data32, 4);
525 rx_avail -= 4;
526 req->rx_num += 4;
527
528 } else if (rx_avail > 1) {
529 memcpy(&((uint8_t*)req->rx_data)[req->rx_num], (void*)&spi->data16[0], 2);
530 rx_avail -= 2;
531 req->rx_num += 2;
532
533 } else {
534 ((uint8_t*)req->rx_data)[req->rx_num++] = spi->data8[0];
535 rx_avail -= 1;
536 }
537 // Don't read less than 2 bytes if we are using greater than 8 bit characters
538 if (rx_avail == 1 && req->bits > 8) {
539 break;
540 }
541 }
542 }
543 remain = length - req->rx_num;
544 if (remain) {
545 if (remain > MXC_SPI17Y_FIFO_DEPTH) {
546 spi->dma = ((spi->dma & ~MXC_F_SPI17Y_DMA_RX_FIFO_LEVEL) |
547 ((2) << MXC_F_SPI17Y_DMA_RX_FIFO_LEVEL_POS));
548 } else {
549 spi->dma = ((spi->dma & ~MXC_F_SPI17Y_DMA_RX_FIFO_LEVEL) |
550 ((remain-1) << MXC_F_SPI17Y_DMA_RX_FIFO_LEVEL_POS));
551 }
552 int_en |= MXC_F_SPI17Y_INT_EN_RX_THRESH;
553 }
554
555 // Break out if we've received all the bytes and we're not transmitting
556 if ((req->tx_data == NULL) && (req->rx_num == length)) {
557 spi->int_en = 0;
558 int_en = 0;
559 mxc_free_lock((uint32_t*)&states[spi_num].req);
560 // Callback if not NULL
561 if (req->callback != NULL) {
562 req->callback(req, E_NO_ERROR);
563 }
564 return 1;
565 }
566 }
567
568 // Break out once we've transmitted and received all of the data
569 if ((req->rx_num == length) && (req->tx_num == length) && ((spi->dma & MXC_F_SPI17Y_DMA_TX_FIFO_CNT) == 0)) {
570 spi->int_en = 0;
571 int_en = 0;
572 mxc_free_lock((uint32_t*)&states[spi_num].req);
573 // Callback if not NULL
574 if (req->callback != NULL) {
575 req->callback(req, E_NO_ERROR);
576 }
577 return 1;
578 }
579 if(async){
580 spi->int_en = int_en;
581 }
582 return 0;
583 }
584
585 /* ************************************************************************* */
SPI17Y_AbortAsync(spi17y_req_t * req)586 int SPI17Y_AbortAsync(spi17y_req_t *req)
587 {
588 int spi_num;
589 mxc_spi17y_regs_t *spi;
590
591 // Check the input parameters
592 if (req == NULL) {
593 return E_BAD_PARAM;
594 }
595
596 // Find the request, set to NULL
597 for (spi_num = 0; spi_num < MXC_SPI17Y_INSTANCES; spi_num++) {
598 if (req == states[spi_num].req) {
599
600 spi = MXC_SPI17Y_GET_SPI17Y(spi_num);
601
602 // Disable interrupts, clear the flags
603 spi->int_en = 0;
604 spi->int_fl = spi->int_fl;
605
606 // Reset the SPI17Y to cancel the on ongoing transaction
607 spi->ctrl0 &= ~(MXC_F_SPI17Y_CTRL0_EN);
608 spi->ctrl0 |= (MXC_F_SPI17Y_CTRL0_EN);
609
610 // Unlock this SPI17Y
611 mxc_free_lock((uint32_t*)&states[spi_num].req);
612
613 // Callback if not NULL
614 if (req->callback != NULL) {
615 req->callback(req, E_ABORT);
616 }
617
618 return E_NO_ERROR;
619 }
620 }
621
622 return E_BAD_PARAM;
623 }
624
625 // *****************************************************************************
SPI17Y_Enable(mxc_spi17y_regs_t * spi)626 void SPI17Y_Enable(mxc_spi17y_regs_t* spi)
627 {
628 spi->ctrl0 |= (MXC_F_SPI17Y_CTRL0_EN);
629 }
630
631 // *****************************************************************************
SPI17Y_Disable(mxc_spi17y_regs_t * spi)632 void SPI17Y_Disable(mxc_spi17y_regs_t* spi)
633 {
634 spi->ctrl0 &= ~(MXC_F_SPI17Y_CTRL0_EN);
635 }
636
637 // *****************************************************************************
SPI17Y_Clear_fifo(mxc_spi17y_regs_t * spi)638 void SPI17Y_Clear_fifo(mxc_spi17y_regs_t* spi)
639 {
640 spi->dma |= MXC_F_SPI17Y_DMA_TX_FIFO_CLEAR | MXC_F_SPI17Y_DMA_RX_FIFO_CLEAR;
641 }
642