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