1 /******************************************************************************
2  *
3  * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by
4  * Analog Devices, Inc.),
5  * Copyright (C) 2023-2024 Analog Devices, Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************************/
20 
21 #include <stdio.h>
22 #include <stddef.h>
23 #include <stdint.h>
24 #include <string.h>
25 #include "mxc_device.h"
26 #include "mxc_assert.h"
27 #include "mxc_lock.h"
28 #include "mxc_sys.h"
29 #include "mxc_delay.h"
30 #include "spi.h"
31 #include "spi_reva1.h"
32 #include "dma_reva.h"
33 
34 /* **** Definitions **** */
35 typedef struct {
36     mxc_spi_reva_req_t *req;
37     int started;
38     unsigned last_size;
39     unsigned ssDeassert;
40     unsigned defaultTXData;
41     int channelTx;
42     int channelRx;
43     int mtMode;
44     int mtFirstTrans;
45     bool txrx_req;
46     uint8_t req_done;
47     uint8_t async;
48     bool hw_ss_control;
49 } spi_req_reva_state_t;
50 
51 static spi_req_reva_state_t states[MXC_SPI_INSTANCES];
52 
53 static uint32_t MXC_SPI_RevA1_MasterTransHandler(mxc_spi_reva_regs_t *spi, mxc_spi_reva_req_t *req);
54 static uint32_t MXC_SPI_RevA1_TransHandler(mxc_spi_reva_regs_t *spi, mxc_spi_reva_req_t *req);
55 static uint32_t MXC_SPI_RevA1_SlaveTransHandler(mxc_spi_reva_req_t *req);
56 static void MXC_SPI_RevA1_SwapByte(uint8_t *arr, size_t length);
57 static int MXC_SPI_RevA1_TransSetup(mxc_spi_reva_req_t *req);
58 
MXC_SPI_RevA1_Init(mxc_spi_reva_regs_t * spi,int masterMode,int quadModeUsed,int numSlaves,unsigned ssPolarity,unsigned int hz)59 int MXC_SPI_RevA1_Init(mxc_spi_reva_regs_t *spi, int masterMode, int quadModeUsed, int numSlaves,
60                        unsigned ssPolarity, unsigned int hz)
61 {
62     int spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
63     /*  Validate that the specified SPI instance exists.
64         Note:  The Init function is the only one that performs this check.
65         It catches the rare edge case where a user has casted
66         a custom SPI regs struct with an incorrect base address.
67      */
68     if (spi_num < 0)
69         return E_BAD_PARAM;
70 
71     states[spi_num].req = NULL;
72     states[spi_num].last_size = 0;
73     states[spi_num].ssDeassert = 1;
74     states[spi_num].defaultTXData = 0;
75     states[spi_num].mtMode = 0;
76     states[spi_num].mtFirstTrans = 0;
77     states[spi_num].channelTx = E_NO_DEVICE;
78     states[spi_num].channelRx = E_NO_DEVICE;
79     states[spi_num].hw_ss_control = true;
80 
81     spi->ctrl0 = (MXC_F_SPI_REVA_CTRL0_EN);
82     spi->sstime =
83         ((0x1 << MXC_F_SPI_REVA_SSTIME_PRE_POS) | (0x1 << MXC_F_SPI_REVA_SSTIME_POST_POS) |
84          (0x1 << MXC_F_SPI_REVA_SSTIME_INACT_POS));
85 
86     //set master
87     if (masterMode) {
88         spi->ctrl0 |= MXC_F_SPI_REVA_CTRL0_MST_MODE;
89     } else {
90         spi->ctrl0 &= ~(MXC_F_SPI_REVA_CTRL0_MST_MODE);
91     }
92 
93     MXC_SPI_SetFrequency((mxc_spi_regs_t *)spi, hz);
94 
95     if (ssPolarity > (MXC_F_SPI_REVA_CTRL2_SS_POL >> MXC_F_SPI_REVA_CTRL2_SS_POL_POS)) {
96         return E_BAD_PARAM;
97     }
98 
99     //set slave select polarity
100     spi->ctrl2 |= (ssPolarity << MXC_F_SPI_REVA_CTRL2_SS_POL_POS);
101 
102     // Clear the interrupts
103     spi->intfl = spi->intfl;
104 
105     if (states[spi_num].hw_ss_control) {
106         if (numSlaves == 1) {
107             spi->ctrl0 |= MXC_S_SPI_REVA_CTRL0_SS_ACTIVE_SS0;
108         }
109 
110         if (numSlaves == 2) {
111             spi->ctrl0 |= (MXC_S_SPI_REVA_CTRL0_SS_ACTIVE_SS0 | MXC_S_SPI_REVA_CTRL0_SS_ACTIVE_SS1);
112         }
113 
114         if (numSlaves == 3) {
115             spi->ctrl0 |= (MXC_S_SPI_REVA_CTRL0_SS_ACTIVE_SS0 | MXC_S_SPI_REVA_CTRL0_SS_ACTIVE_SS1 |
116                            MXC_S_SPI_REVA_CTRL0_SS_ACTIVE_SS2);
117         }
118 
119         if (numSlaves == 4) {
120             spi->ctrl0 |= (MXC_S_SPI_REVA_CTRL0_SS_ACTIVE_SS0 | MXC_S_SPI_REVA_CTRL0_SS_ACTIVE_SS1 |
121                            MXC_S_SPI_REVA_CTRL0_SS_ACTIVE_SS2 | MXC_S_SPI_REVA_CTRL0_SS_ACTIVE_SS3);
122         }
123     }
124 
125     //set quad mode
126     if (quadModeUsed) {
127         spi->ctrl2 |= MXC_S_SPI_REVA_CTRL2_DATA_WIDTH_QUAD;
128     }
129 
130     return E_NO_ERROR;
131 }
132 
MXC_SPI_RevA1_Shutdown(mxc_spi_reva_regs_t * spi)133 int MXC_SPI_RevA1_Shutdown(mxc_spi_reva_regs_t *spi)
134 {
135     mxc_spi_reva_req_t *temp_req;
136     int spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
137 
138     //disable and clear interrupts
139     spi->inten = 0;
140     spi->intfl = spi->intfl;
141 
142     // Disable SPI and FIFOS
143     spi->ctrl0 &= ~(MXC_F_SPI_REVA_CTRL0_EN);
144     spi->dma &= ~(MXC_F_SPI_REVA_DMA_TX_FIFO_EN | MXC_F_SPI_REVA_DMA_RX_FIFO_EN);
145 
146     if (states[spi_num].req != NULL) {
147         //save the request
148         temp_req = states[spi_num].req;
149         MXC_FreeLock((uint32_t *)(uint32_t *)&states[spi_num].req);
150 
151         // Callback if not NULL
152         if (states[spi_num].req->completeCB != NULL) {
153             states[spi_num].req->completeCB(temp_req, E_SHUTDOWN);
154         }
155     }
156 
157     // Clear registers
158     spi->ctrl0 = 0;
159     spi->ctrl1 = 0;
160     spi->ctrl2 = 0;
161     spi->sstime = 0;
162 
163     // release any acquired DMA channels
164     if (states[spi_num].channelTx >= 0) {
165         MXC_DMA_RevA_ReleaseChannel(states[spi_num].channelTx);
166         states[spi_num].channelTx = E_NO_DEVICE;
167     }
168     if (states[spi_num].channelRx >= 0) {
169         MXC_DMA_RevA_ReleaseChannel(states[spi_num].channelRx);
170         states[spi_num].channelRx = E_NO_DEVICE;
171     }
172 
173     return E_NO_ERROR;
174 }
175 
MXC_SPI_RevA1_ReadyForSleep(mxc_spi_reva_regs_t * spi)176 int MXC_SPI_RevA1_ReadyForSleep(mxc_spi_reva_regs_t *spi)
177 {
178     if (spi->stat & MXC_F_SPI_REVA_STAT_BUSY || (spi->dma & MXC_F_SPI_REVA_DMA_TX_LVL) ||
179         (spi->dma & MXC_F_SPI_REVA_DMA_RX_LVL)) {
180         return E_BUSY;
181     } else {
182         return E_NO_ERROR;
183     }
184 }
185 
MXC_SPI_RevA1_SetFrequency(mxc_spi_reva_regs_t * spi,unsigned int hz)186 int MXC_SPI_RevA1_SetFrequency(mxc_spi_reva_regs_t *spi, unsigned int hz)
187 {
188     int hi_clk, lo_clk, scale;
189     uint32_t freq_div;
190 
191     // Check if frequency is too high
192     if (hz > PeripheralClock) {
193         return E_BAD_PARAM;
194     }
195 
196     // Set the clock high and low
197     freq_div = MXC_SPI_GetPeripheralClock((mxc_spi_regs_t *)spi);
198     freq_div = (freq_div / hz);
199 
200     hi_clk = freq_div / 2;
201     lo_clk = freq_div / 2;
202     scale = 0;
203 
204     if (freq_div % 2) {
205         hi_clk += 1;
206     }
207 
208     while (hi_clk >= 16 && scale < 8) {
209         hi_clk /= 2;
210         lo_clk /= 2;
211         scale++;
212     }
213 
214     if (scale == 8) {
215         lo_clk = 15;
216         hi_clk = 15;
217     }
218 
219     MXC_SETFIELD(spi->clkctrl, MXC_F_SPI_REVA_CLKCTRL_LO,
220                  (lo_clk << MXC_F_SPI_REVA_CLKCTRL_LO_POS));
221     MXC_SETFIELD(spi->clkctrl, MXC_F_SPI_REVA_CLKCTRL_HI,
222                  (hi_clk << MXC_F_SPI_REVA_CLKCTRL_HI_POS));
223     MXC_SETFIELD(spi->clkctrl, MXC_F_SPI_REVA_CLKCTRL_CLKDIV,
224                  (scale << MXC_F_SPI_REVA_CLKCTRL_CLKDIV_POS));
225 
226     return E_NO_ERROR;
227 }
228 
MXC_SPI_RevA1_GetFrequency(mxc_spi_reva_regs_t * spi)229 unsigned int MXC_SPI_RevA1_GetFrequency(mxc_spi_reva_regs_t *spi)
230 {
231     if (MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi) < 0) {
232         // Can't return error code (negative values) due to return type.
233         //  Return 0Hz instead.
234         return 0;
235     }
236 
237     unsigned scale, lo_clk, hi_clk;
238 
239     scale = (spi->clkctrl & MXC_F_SPI_REVA_CLKCTRL_CLKDIV) >> MXC_F_SPI_REVA_CLKCTRL_CLKDIV_POS;
240     hi_clk = (spi->clkctrl & MXC_F_SPI_REVA_CLKCTRL_HI) >> MXC_F_SPI_REVA_CLKCTRL_HI_POS;
241     lo_clk = (spi->clkctrl & MXC_F_SPI_REVA_CLKCTRL_LO) >> MXC_F_SPI_REVA_CLKCTRL_LO_POS;
242 
243     return (PeripheralClock / (1 << scale)) / (lo_clk + hi_clk);
244 }
245 
MXC_SPI_RevA1_SetDataSize(mxc_spi_reva_regs_t * spi,int dataSize)246 int MXC_SPI_RevA1_SetDataSize(mxc_spi_reva_regs_t *spi, int dataSize)
247 {
248     // HW has problem with these two character sizes
249     if (dataSize == 1 || dataSize > 16) {
250         return E_BAD_PARAM;
251     }
252 
253     int spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
254 
255     // Setup the character size
256     if (!(spi->stat & MXC_F_SPI_REVA_STAT_BUSY) && states[spi_num].ssDeassert == 1) {
257         //disable spi to change transfer size
258         spi->ctrl0 &= ~(MXC_F_SPI_REVA_CTRL0_EN);
259         // set bit size
260         states[spi_num].last_size = dataSize;
261 
262         if (dataSize < 16) {
263             MXC_SETFIELD(spi->ctrl2, MXC_F_SPI_REVA_CTRL2_NUMBITS,
264                          dataSize << MXC_F_SPI_REVA_CTRL2_NUMBITS_POS);
265         } else {
266             MXC_SETFIELD(spi->ctrl2, MXC_F_SPI_REVA_CTRL2_NUMBITS,
267                          0 << MXC_F_SPI_REVA_CTRL2_NUMBITS_POS); //may not be neccessary
268         }
269 
270         //enable spi to change transfer size
271         spi->ctrl0 |= (MXC_F_SPI_REVA_CTRL0_EN);
272     } else {
273         return E_BAD_STATE;
274     }
275 
276     return E_NO_ERROR;
277 }
278 
MXC_SPI_RevA1_GetDataSize(mxc_spi_reva_regs_t * spi)279 int MXC_SPI_RevA1_GetDataSize(mxc_spi_reva_regs_t *spi)
280 {
281     if (!(spi->ctrl2 & MXC_F_SPI_REVA_CTRL2_NUMBITS)) {
282         return 16;
283     }
284 
285     return (spi->ctrl2 & MXC_F_SPI_REVA_CTRL2_NUMBITS) >> MXC_F_SPI_REVA_CTRL2_NUMBITS_POS;
286 }
287 
MXC_SPI_RevA1_SetMTMode(mxc_spi_reva_regs_t * spi,int mtMode)288 int MXC_SPI_RevA1_SetMTMode(mxc_spi_reva_regs_t *spi, int mtMode)
289 {
290     int spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
291 
292     if ((mtMode != 0) && (mtMode != 1)) {
293         return E_BAD_PARAM;
294     }
295 
296     if (states[spi_num].mtMode == 1) {
297         if (mtMode == 0) {
298             // exiting MT Mode: release any acquired DMA channels
299             if (states[spi_num].channelTx >= 0) {
300                 MXC_DMA_RevA_ReleaseChannel(states[spi_num].channelTx);
301                 states[spi_num].channelTx = E_NO_DEVICE;
302             }
303             if (states[spi_num].channelRx >= 0) {
304                 MXC_DMA_RevA_ReleaseChannel(states[spi_num].channelRx);
305                 states[spi_num].channelRx = E_NO_DEVICE;
306             }
307         }
308     } else if (mtMode == 1) {
309         // entering MT Mode: set first transaction
310         states[spi_num].mtFirstTrans = 1;
311     }
312 
313     states[spi_num].mtMode = mtMode;
314 
315     return E_NO_ERROR;
316 }
317 
MXC_SPI_RevA1_GetMTMode(mxc_spi_reva_regs_t * spi)318 int MXC_SPI_RevA1_GetMTMode(mxc_spi_reva_regs_t *spi)
319 {
320     int spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
321 
322     return states[spi_num].mtMode;
323 }
324 
MXC_SPI_RevA1_SetSlave(mxc_spi_reva_regs_t * spi,int ssIdx)325 int MXC_SPI_RevA1_SetSlave(mxc_spi_reva_regs_t *spi, int ssIdx)
326 {
327     // HW has problem with these two character sizes
328     if (ssIdx >= MXC_SPI_SS_INSTANCES) {
329         return E_BAD_PARAM;
330     }
331 
332     //check if in master mode
333     if (!(spi->ctrl0 & MXC_F_SPI_REVA_CTRL0_MST_MODE)) {
334         return E_BAD_STATE;
335     }
336 
337     int spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
338 
339     if (states[spi_num].hw_ss_control) {
340         // Setup the slave select
341         // Activate chosen SS pin
342         spi->ctrl0 |= (1 << ssIdx) << MXC_F_SPI_REVA_CTRL0_SS_ACTIVE_POS;
343         // Deactivate all unchosen pins
344         spi->ctrl0 &= ~MXC_F_SPI_REVA_CTRL0_SS_ACTIVE |
345                       ((1 << ssIdx) << MXC_F_SPI_REVA_CTRL0_SS_ACTIVE_POS);
346     }
347     return E_NO_ERROR;
348 }
349 
MXC_SPI_RevA1_GetSlave(mxc_spi_reva_regs_t * spi)350 int MXC_SPI_RevA1_GetSlave(mxc_spi_reva_regs_t *spi)
351 {
352     return ((spi->ctrl0 & MXC_F_SPI_REVA_CTRL0_SS_ACTIVE) >> MXC_F_SPI_REVA_CTRL0_SS_ACTIVE_POS) >>
353            1;
354 }
355 
MXC_SPI_RevA1_SetWidth(mxc_spi_reva_regs_t * spi,mxc_spi_reva_width_t spiWidth)356 int MXC_SPI_RevA1_SetWidth(mxc_spi_reva_regs_t *spi, mxc_spi_reva_width_t spiWidth)
357 {
358     spi->ctrl2 &= ~(MXC_F_SPI_REVA_CTRL2_THREE_WIRE | MXC_F_SPI_REVA_CTRL2_DATA_WIDTH);
359 
360     switch (spiWidth) {
361     case SPI_REVA_WIDTH_3WIRE:
362         spi->ctrl2 |= MXC_F_SPI_REVA_CTRL2_THREE_WIRE;
363         break;
364 
365     case SPI_REVA_WIDTH_STANDARD:
366         spi->ctrl2 |= MXC_S_SPI_REVA_CTRL2_DATA_WIDTH_MONO;
367         break;
368 
369     case SPI_REVA_WIDTH_DUAL:
370         spi->ctrl2 |= MXC_S_SPI_REVA_CTRL2_DATA_WIDTH_DUAL;
371         break;
372 
373     case SPI_REVA_WIDTH_QUAD:
374         spi->ctrl2 |= MXC_S_SPI_REVA_CTRL2_DATA_WIDTH_QUAD;
375         break;
376     }
377 
378     return E_NO_ERROR;
379 }
380 
MXC_SPI_RevA1_GetWidth(mxc_spi_reva_regs_t * spi)381 mxc_spi_reva_width_t MXC_SPI_RevA1_GetWidth(mxc_spi_reva_regs_t *spi)
382 {
383     if (spi->ctrl2 & MXC_F_SPI_REVA_CTRL2_THREE_WIRE) {
384         return SPI_REVA_WIDTH_3WIRE;
385     }
386 
387     if (spi->ctrl2 & MXC_S_SPI_REVA_CTRL2_DATA_WIDTH_DUAL) {
388         return SPI_REVA_WIDTH_DUAL;
389     }
390 
391     if (spi->ctrl2 & MXC_S_SPI_REVA_CTRL2_DATA_WIDTH_QUAD) {
392         return SPI_REVA_WIDTH_QUAD;
393     }
394 
395     return SPI_REVA_WIDTH_STANDARD;
396 }
397 
MXC_SPI_RevA1_SetMode(mxc_spi_reva_regs_t * spi,mxc_spi_reva_mode_t spiMode)398 int MXC_SPI_RevA1_SetMode(mxc_spi_reva_regs_t *spi, mxc_spi_reva_mode_t spiMode)
399 {
400     switch (spiMode) {
401     case SPI_REVA_MODE_0:
402         spi->ctrl2 &= ~MXC_F_SPI_REVA_CTRL2_CLKPHA;
403         spi->ctrl2 &= ~MXC_F_SPI_REVA_CTRL2_CLKPOL;
404         break;
405 
406     case SPI_REVA_MODE_1:
407         spi->ctrl2 |= MXC_F_SPI_REVA_CTRL2_CLKPHA;
408         spi->ctrl2 &= ~MXC_F_SPI_REVA_CTRL2_CLKPOL;
409         break;
410 
411     case SPI_REVA_MODE_2:
412         spi->ctrl2 &= ~MXC_F_SPI_REVA_CTRL2_CLKPHA;
413         spi->ctrl2 |= MXC_F_SPI_REVA_CTRL2_CLKPOL;
414         break;
415 
416     case SPI_REVA_MODE_3:
417         spi->ctrl2 |= MXC_F_SPI_REVA_CTRL2_CLKPHA;
418         spi->ctrl2 |= MXC_F_SPI_REVA_CTRL2_CLKPOL;
419         break;
420 
421     default:
422         break;
423     }
424 
425     return E_NO_ERROR;
426 }
427 
MXC_SPI_RevA1_GetMode(mxc_spi_reva_regs_t * spi)428 mxc_spi_reva_mode_t MXC_SPI_RevA1_GetMode(mxc_spi_reva_regs_t *spi)
429 {
430     if (spi->ctrl2 & MXC_F_SPI_REVA_CTRL2_CLKPHA) {
431         if (spi->ctrl2 & MXC_F_SPI_REVA_CTRL2_CLKPOL) {
432             return SPI_REVA_MODE_3;
433         } else {
434             return SPI_REVA_MODE_2;
435         }
436     } else {
437         if (spi->ctrl2 & MXC_F_SPI_REVA_CTRL2_CLKPOL) {
438             return SPI_REVA_MODE_1;
439         }
440     }
441 
442     return SPI_REVA_MODE_0;
443 }
444 
MXC_SPI_RevA1_StartTransmission(mxc_spi_reva_regs_t * spi)445 int MXC_SPI_RevA1_StartTransmission(mxc_spi_reva_regs_t *spi)
446 {
447     if (MXC_SPI_GetActive((mxc_spi_regs_t *)spi) == E_BUSY) {
448         return E_BUSY;
449     }
450 
451     spi->ctrl0 |= MXC_F_SPI_REVA_CTRL0_START;
452 
453     return E_NO_ERROR;
454 }
455 
MXC_SPI_RevA1_GetActive(mxc_spi_reva_regs_t * spi)456 int MXC_SPI_RevA1_GetActive(mxc_spi_reva_regs_t *spi)
457 {
458     if (spi->stat & MXC_F_SPI_REVA_STAT_BUSY) {
459         return E_BUSY;
460     }
461 
462     return E_NO_ERROR;
463 }
464 
MXC_SPI_RevA1_AbortTransmission(mxc_spi_reva_regs_t * spi)465 int MXC_SPI_RevA1_AbortTransmission(mxc_spi_reva_regs_t *spi)
466 {
467     int spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
468 
469     // Disable interrupts, clear the flags
470     spi->inten = 0;
471     spi->intfl = spi->intfl;
472 
473     // Reset the SPI17Y to cancel the on ongoing transaction
474     spi->ctrl0 &= ~(MXC_F_SPI_REVA_CTRL0_EN);
475     spi->ctrl0 |= (MXC_F_SPI_REVA_CTRL0_EN);
476 
477     // Unlock this SPI
478     mxc_spi_reva_req_t *temp = states[spi_num].req;
479     MXC_FreeLock((uint32_t *)&states[spi_num].req);
480 
481     // Callback if not NULL
482     if (temp->completeCB != NULL) {
483         temp->completeCB(states[spi_num].req, E_ABORT);
484     }
485 
486     // release any acquired DMA channels
487     if (states[spi_num].channelTx >= 0) {
488         MXC_DMA_RevA_ReleaseChannel(states[spi_num].channelTx);
489         states[spi_num].channelTx = E_NO_DEVICE;
490     }
491     if (states[spi_num].channelRx >= 0) {
492         MXC_DMA_RevA_ReleaseChannel(states[spi_num].channelRx);
493         states[spi_num].channelRx = E_NO_DEVICE;
494     }
495     if (states[spi_num].mtMode == 1) {
496         states[spi_num].mtFirstTrans = 1;
497     }
498 
499     return E_NO_ERROR;
500 }
501 
MXC_SPI_RevA1_ReadRXFIFO(mxc_spi_reva_regs_t * spi,unsigned char * bytes,unsigned int len)502 unsigned int MXC_SPI_RevA1_ReadRXFIFO(mxc_spi_reva_regs_t *spi, unsigned char *bytes,
503                                       unsigned int len)
504 {
505     unsigned rx_avail, bits;
506 
507     if (!bytes || !len) {
508         return 0;
509     }
510 
511     rx_avail = MXC_SPI_GetRXFIFOAvailable((mxc_spi_regs_t *)spi);
512     bits = MXC_SPI_GetDataSize((mxc_spi_regs_t *)spi);
513 
514     if (len > rx_avail) {
515         len = rx_avail;
516     }
517 
518     if (bits > 8) {
519         len &= ~(unsigned)0x1;
520     }
521 
522     unsigned count = 0;
523 
524     // Read from the FIFO
525     while (len) {
526         // Reading 2-8 bit wide messages from the FIFO16 or FIFO32 register
527         //  swaps the ordering of the message.
528         //  Example:
529         //      When the SPI FIFO receives the message '00, 01, 02, 03', reading the FIFO16
530         //      or FIFO32 register could result in '01, 00, 03, 02' - depending on the part.
531         if (bits > 8) {
532             if (len > 3) {
533                 memcpy((uint8_t *)(&bytes[count]), (void *)(&spi->fifo32), 4);
534                 len -= 4;
535                 count += 4;
536             } else if (len > 1) {
537                 memcpy((uint8_t *)(&bytes[count]), (void *)(&spi->fifo16[0]), 2);
538                 len -= 2;
539                 count += 2;
540             }
541 
542             // Don't read less than 2 bytes if we are using greater than 8 bit wide messages.
543             //  Due to the nature of how this function is called in the drivers, it should never
544             //  reach to this point.
545             if (len == 1) {
546                 break;
547             }
548 
549             // 9-16 bit wide messages should not be read from the FIFO8 register (cuts
550             //  off the upper byte).
551         } else {
552             ((uint8_t *)bytes)[count++] = spi->fifo8[0];
553             len -= 1;
554         }
555     }
556 
557     return count;
558 }
559 
MXC_SPI_RevA1_GetRXFIFOAvailable(mxc_spi_reva_regs_t * spi)560 unsigned int MXC_SPI_RevA1_GetRXFIFOAvailable(mxc_spi_reva_regs_t *spi)
561 {
562     return (spi->dma & MXC_F_SPI_REVA_DMA_RX_LVL) >> MXC_F_SPI_REVA_DMA_RX_LVL_POS;
563 }
564 
MXC_SPI_RevA1_WriteTXFIFO(mxc_spi_reva_regs_t * spi,unsigned char * bytes,unsigned int len)565 unsigned int MXC_SPI_RevA1_WriteTXFIFO(mxc_spi_reva_regs_t *spi, unsigned char *bytes,
566                                        unsigned int len)
567 {
568     unsigned tx_avail, bits;
569 
570     if (!bytes || !len) {
571         return 0;
572     }
573 
574     tx_avail = MXC_SPI_GetTXFIFOAvailable((mxc_spi_regs_t *)spi);
575     bits = MXC_SPI_GetDataSize((mxc_spi_regs_t *)spi);
576 
577     if (len > tx_avail) {
578         len = tx_avail;
579     }
580 
581     if (bits > 8) {
582         len &= ~(unsigned)0x1;
583     }
584 
585     unsigned count = 0;
586 
587     while (len) {
588         // Writing 2-8 bit wide messages to the FIFO16 or FIFO32 register
589         //  swaps the ordering of the message.
590         //  Example:
591         //      SPI FIFO is expected to transmit the message '00, 01, 02, 03'.
592         //      Writing the four byte-wide characters to the FIFO16 or FIFO32 register could
593         //      result in this message shifted out: '01, 00, 03, 02' - depending on the part.
594         if (bits > 8) {
595             if (len > 3) {
596                 memcpy((void *)(&spi->fifo32), (uint8_t *)(&bytes[count]), 4);
597                 len -= 4;
598                 count += 4;
599             } else if (len > 1) {
600                 memcpy((void *)(&spi->fifo16[0]), (uint8_t *)(&bytes[count]), 2);
601                 len -= 2;
602                 count += 2;
603             }
604 
605             // 9-16 bit wide messages should not be written to the FIFO8 register (cuts
606             //  off the upper byte).
607         } else {
608             spi->fifo8[0] = ((uint8_t *)bytes)[count++];
609             len -= 1;
610         }
611     }
612 
613     return count;
614 }
615 
MXC_SPI_RevA1_GetTXFIFOAvailable(mxc_spi_reva_regs_t * spi)616 unsigned int MXC_SPI_RevA1_GetTXFIFOAvailable(mxc_spi_reva_regs_t *spi)
617 {
618     return MXC_SPI_FIFO_DEPTH -
619            ((spi->dma & MXC_F_SPI_REVA_DMA_TX_LVL) >> MXC_F_SPI_REVA_DMA_TX_LVL_POS);
620 }
621 
MXC_SPI_RevA1_ClearRXFIFO(mxc_spi_reva_regs_t * spi)622 void MXC_SPI_RevA1_ClearRXFIFO(mxc_spi_reva_regs_t *spi)
623 {
624     spi->dma |= MXC_F_SPI_REVA_DMA_RX_FLUSH;
625 }
626 
MXC_SPI_RevA1_ClearTXFIFO(mxc_spi_reva_regs_t * spi)627 void MXC_SPI_RevA1_ClearTXFIFO(mxc_spi_reva_regs_t *spi)
628 {
629     spi->dma |= MXC_F_SPI_REVA_DMA_TX_FLUSH;
630 }
631 
MXC_SPI_RevA1_SetRXThreshold(mxc_spi_reva_regs_t * spi,unsigned int numBytes)632 int MXC_SPI_RevA1_SetRXThreshold(mxc_spi_reva_regs_t *spi, unsigned int numBytes)
633 {
634     if (numBytes > 30) {
635         return E_BAD_PARAM;
636     }
637 
638     MXC_SETFIELD(spi->dma, MXC_F_SPI_REVA_DMA_RX_THD_VAL,
639                  numBytes << MXC_F_SPI_REVA_DMA_RX_THD_VAL_POS);
640 
641     return E_NO_ERROR;
642 }
643 
MXC_SPI_RevA1_GetRXThreshold(mxc_spi_reva_regs_t * spi)644 unsigned int MXC_SPI_RevA1_GetRXThreshold(mxc_spi_reva_regs_t *spi)
645 {
646     return (spi->dma & MXC_F_SPI_REVA_DMA_RX_THD_VAL) >> MXC_F_SPI_REVA_DMA_RX_THD_VAL_POS;
647 }
648 
MXC_SPI_RevA1_SetTXThreshold(mxc_spi_reva_regs_t * spi,unsigned int numBytes)649 int MXC_SPI_RevA1_SetTXThreshold(mxc_spi_reva_regs_t *spi, unsigned int numBytes)
650 {
651     // Valid values for the threshold are 0x1 to 0x1F
652     if (numBytes > 31 || numBytes == 0) {
653         return E_BAD_PARAM;
654     }
655 
656     MXC_SETFIELD(spi->dma, MXC_F_SPI_REVA_DMA_TX_THD_VAL,
657                  numBytes << MXC_F_SPI_REVA_DMA_TX_THD_VAL_POS);
658 
659     return E_NO_ERROR;
660 }
661 
MXC_SPI_RevA1_GetTXThreshold(mxc_spi_reva_regs_t * spi)662 unsigned int MXC_SPI_RevA1_GetTXThreshold(mxc_spi_reva_regs_t *spi)
663 {
664     return (spi->dma & MXC_F_SPI_REVA_DMA_TX_THD_VAL) >> MXC_F_SPI_REVA_DMA_TX_THD_VAL_POS;
665 }
666 
MXC_SPI_RevA1_GetFlags(mxc_spi_reva_regs_t * spi)667 unsigned int MXC_SPI_RevA1_GetFlags(mxc_spi_reva_regs_t *spi)
668 {
669     return spi->intfl;
670 }
671 
MXC_SPI_RevA1_ClearFlags(mxc_spi_reva_regs_t * spi)672 void MXC_SPI_RevA1_ClearFlags(mxc_spi_reva_regs_t *spi)
673 {
674     spi->intfl = spi->intfl;
675 }
676 
MXC_SPI_RevA1_EnableInt(mxc_spi_reva_regs_t * spi,unsigned int intEn)677 void MXC_SPI_RevA1_EnableInt(mxc_spi_reva_regs_t *spi, unsigned int intEn)
678 {
679     spi->inten |= intEn;
680 }
681 
MXC_SPI_RevA1_DisableInt(mxc_spi_reva_regs_t * spi,unsigned int intDis)682 void MXC_SPI_RevA1_DisableInt(mxc_spi_reva_regs_t *spi, unsigned int intDis)
683 {
684     spi->inten &= ~(intDis);
685 }
686 
MXC_SPI_RevA1_TransSetup(mxc_spi_reva_req_t * req)687 int MXC_SPI_RevA1_TransSetup(mxc_spi_reva_req_t *req)
688 {
689     int spi_num;
690     uint8_t bits;
691 
692     spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)(req->spi));
693 
694     MXC_ASSERT(req->ssIdx < MXC_SPI_SS_INSTANCES);
695 
696     if ((!req) || ((req->txData == NULL) && (req->rxData == NULL))) {
697         return E_BAD_PARAM;
698     }
699 
700     // Setup the number of characters to transact
701     if (req->txLen > (MXC_F_SPI_REVA_CTRL1_TX_NUM_CHAR >> MXC_F_SPI_REVA_CTRL1_TX_NUM_CHAR_POS)) {
702         return E_BAD_PARAM;
703     }
704 
705     bits = MXC_SPI_GetDataSize((mxc_spi_regs_t *)req->spi);
706     req->txCnt = 0;
707     req->rxCnt = 0;
708 
709     states[spi_num].req = req;
710     states[spi_num].started = 0;
711     states[spi_num].req_done = 0;
712     // HW requires disabling/renabling SPI block at end of each transaction (when SS is inactive).
713     if (states[spi_num].ssDeassert == 1) {
714         (req->spi)->ctrl0 &= ~(MXC_F_SPI_REVA_CTRL0_EN);
715     }
716 
717     //if  master
718     if ((req->spi)->ctrl0 & MXC_F_SPI_REVA_CTRL0_MST_MODE) {
719         // Setup the slave select
720         MXC_SPI_SetSlave((mxc_spi_regs_t *)req->spi, req->ssIdx);
721     }
722 
723     if (req->rxData != NULL && req->rxLen > 0) {
724         MXC_SETFIELD((req->spi)->ctrl1, MXC_F_SPI_REVA_CTRL1_RX_NUM_CHAR,
725                      req->rxLen << MXC_F_SPI_REVA_CTRL1_RX_NUM_CHAR_POS);
726         (req->spi)->dma |= MXC_F_SPI_REVA_DMA_RX_FIFO_EN;
727     } else {
728         (req->spi)->ctrl1 &= ~(MXC_F_SPI_REVA_CTRL1_RX_NUM_CHAR);
729         (req->spi)->dma &= ~(MXC_F_SPI_REVA_DMA_RX_FIFO_EN);
730     }
731 
732     // Must use TXFIFO and NUM in full duplex//start  editing here
733     if ((mxc_spi_reva_width_t)MXC_SPI_GetWidth((mxc_spi_regs_t *)req->spi) ==
734             SPI_REVA_WIDTH_STANDARD &&
735         !(((req->spi)->ctrl2 & MXC_F_SPI_REVA_CTRL2_THREE_WIRE) >>
736           MXC_F_SPI_REVA_CTRL2_THREE_WIRE_POS)) {
737         if (req->txData == NULL) {
738             // Must have something to send, so we'll use the rx_data buffer initialized to 0.
739             //SPI_SetDefaultTXData(spi, 0);
740             memset(req->rxData, states[spi_num].defaultTXData,
741                    (bits > 8 ? req->rxLen << 1 : req->rxLen));
742             req->txData = req->rxData;
743             req->txLen = req->rxLen;
744         }
745     }
746 
747     if (req->txData != NULL && req->txLen > 0) {
748         MXC_SETFIELD((req->spi)->ctrl1, MXC_F_SPI_REVA_CTRL1_TX_NUM_CHAR,
749                      req->txLen << MXC_F_SPI_REVA_CTRL1_TX_NUM_CHAR_POS);
750         (req->spi)->dma |= MXC_F_SPI_REVA_DMA_TX_FIFO_EN;
751     } else {
752         (req->spi)->ctrl1 &= ~(MXC_F_SPI_REVA_CTRL1_TX_NUM_CHAR);
753         (req->spi)->dma &= ~(MXC_F_SPI_REVA_DMA_TX_FIFO_EN);
754     }
755 
756     if ((req->txData != NULL && req->txLen) && (req->rxData != NULL && req->rxLen)) {
757         states[spi_num].txrx_req = true;
758     } else {
759         states[spi_num].txrx_req = false;
760     }
761 
762     (req->spi)->dma |= (MXC_F_SPI_REVA_DMA_TX_FLUSH | MXC_F_SPI_REVA_DMA_RX_FLUSH);
763     (req->spi)->ctrl0 |= (MXC_F_SPI_REVA_CTRL0_EN);
764 
765     states[spi_num].ssDeassert = req->ssDeassert;
766     // Clear master done flag
767     (req->spi)->intfl = MXC_F_SPI_REVA_INTFL_MST_DONE;
768 
769     return E_NO_ERROR;
770 }
771 
MXC_SPI_RevA1_MasterTransHandler(mxc_spi_reva_regs_t * spi,mxc_spi_reva_req_t * req)772 uint32_t MXC_SPI_RevA1_MasterTransHandler(mxc_spi_reva_regs_t *spi, mxc_spi_reva_req_t *req)
773 {
774     uint32_t retval;
775     int spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
776 
777     // Leave slave select asserted at the end of the transaction
778     if (states[spi_num].hw_ss_control && !req->ssDeassert) {
779         spi->ctrl0 = (spi->ctrl0 & ~MXC_F_SPI_REVA_CTRL0_START) | MXC_F_SPI_REVA_CTRL0_SS_CTRL;
780         // Note: Setting 0 to START bit to avoid race condition and duplicated starts.
781         // See https://github.com/analogdevicesinc/msdk/issues/713
782     }
783 
784     retval = MXC_SPI_RevA1_TransHandler(spi, req);
785 
786     if (!states[spi_num].started) {
787         MXC_SPI_StartTransmission((mxc_spi_regs_t *)spi);
788         states[spi_num].started = 1;
789     }
790 
791     // Deassert slave select at the end of the transaction
792     if (states[spi_num].hw_ss_control && req->ssDeassert) {
793         spi->ctrl0 &= ~(MXC_F_SPI_REVA_CTRL0_START | MXC_F_SPI_REVA_CTRL0_SS_CTRL);
794     }
795 
796     return retval;
797 }
798 
MXC_SPI_RevA1_SlaveTransHandler(mxc_spi_reva_req_t * req)799 uint32_t MXC_SPI_RevA1_SlaveTransHandler(mxc_spi_reva_req_t *req)
800 {
801     return MXC_SPI_RevA1_TransHandler(req->spi, req);
802 }
803 
MXC_SPI_RevA1_TransHandler(mxc_spi_reva_regs_t * spi,mxc_spi_reva_req_t * req)804 uint32_t MXC_SPI_RevA1_TransHandler(mxc_spi_reva_regs_t *spi, mxc_spi_reva_req_t *req)
805 {
806     int remain, spi_num;
807     uint32_t int_en = 0;
808     uint32_t tx_length = 0, rx_length = 0;
809     uint8_t bits;
810     spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
811 
812     bits = MXC_SPI_GetDataSize((mxc_spi_regs_t *)req->spi);
813 
814     //MXC_F_SPI_REVA_CTRL2_NUMBITS data bits
815     // Read/write 2x number of bytes if larger character size
816     if (bits > 8) {
817         tx_length = req->txLen * 2;
818         rx_length = req->rxLen * 2;
819     } else {
820         tx_length = req->txLen;
821         rx_length = req->rxLen;
822     }
823 
824     if (req->txData != NULL) {
825         req->txCnt += MXC_SPI_WriteTXFIFO((mxc_spi_regs_t *)spi, &(req->txData[req->txCnt]),
826                                           tx_length - req->txCnt);
827     }
828 
829     remain = tx_length - req->txCnt;
830 
831     // Set the TX interrupts
832     // Write the FIFO //starting here
833     if (remain) {
834         if (remain >= MXC_SPI_FIFO_DEPTH) {
835             MXC_SPI_SetTXThreshold((mxc_spi_regs_t *)spi, MXC_SPI_FIFO_DEPTH - 1);
836         } else {
837             MXC_SPI_SetTXThreshold((mxc_spi_regs_t *)spi, remain);
838         }
839 
840         int_en |= MXC_F_SPI_REVA_INTEN_TX_THD;
841     }
842     // Break out if we've transmitted all the bytes and not receiving
843     if ((req->rxData == NULL) && (req->txCnt == tx_length)) {
844         spi->inten = 0;
845         int_en = 0;
846         MXC_FreeLock((uint32_t *)&states[spi_num].req);
847 
848         // Callback if not NULL
849         if (states[spi_num].async && req->completeCB != NULL) {
850             req->completeCB(req, E_NO_ERROR);
851         }
852     }
853 
854     // Read the RX FIFO
855     if (req->rxData != NULL) {
856         req->rxCnt += MXC_SPI_ReadRXFIFO((mxc_spi_regs_t *)spi, &(req->rxData[req->rxCnt]),
857                                          rx_length - req->rxCnt);
858 
859         remain = rx_length - req->rxCnt;
860 
861         if (remain) {
862             if (remain >= MXC_SPI_FIFO_DEPTH) {
863                 MXC_SPI_SetRXThreshold((mxc_spi_regs_t *)spi, 2);
864             } else {
865                 MXC_SPI_SetRXThreshold((mxc_spi_regs_t *)spi, remain - 1);
866             }
867 
868             int_en |= MXC_F_SPI_REVA_INTEN_RX_THD;
869         }
870 
871         // Break out if we've received all the bytes and we're not transmitting
872         if ((req->txData == NULL) && (req->rxCnt == rx_length)) {
873             spi->inten = 0;
874             int_en = 0;
875             MXC_FreeLock((uint32_t *)&states[spi_num].req);
876 
877             // Callback if not NULL
878             if (states[spi_num].async && req->completeCB != NULL) {
879                 req->completeCB(req, E_NO_ERROR);
880             }
881         }
882     }
883     // Break out once we've transmitted and received all of the data
884     if ((req->rxCnt == rx_length) && (req->txCnt == tx_length)) {
885         spi->inten = 0;
886         int_en = 0;
887         MXC_FreeLock((uint32_t *)&states[spi_num].req);
888 
889         // Callback if not NULL
890         if (states[spi_num].async && req->completeCB != NULL) {
891             req->completeCB(req, E_NO_ERROR);
892         }
893     }
894 
895     return int_en;
896 }
897 
MXC_SPI_RevA1_MasterTransaction(mxc_spi_reva_req_t * req)898 int MXC_SPI_RevA1_MasterTransaction(mxc_spi_reva_req_t *req)
899 {
900     int error;
901 
902     if ((error = MXC_SPI_RevA1_TransSetup(req)) != E_NO_ERROR) {
903         return error;
904     }
905 
906     states[MXC_SPI_GET_IDX((mxc_spi_regs_t *)req->spi)].async = 0;
907 
908     //call master transHandler
909     while (MXC_SPI_RevA1_MasterTransHandler(req->spi, req) != 0) {}
910 
911     while (!((req->spi)->intfl & MXC_F_SPI_REVA_INTFL_MST_DONE)) {}
912 
913     return E_NO_ERROR;
914 }
915 
MXC_SPI_RevA1_MasterTransactionAsync(mxc_spi_reva_req_t * req)916 int MXC_SPI_RevA1_MasterTransactionAsync(mxc_spi_reva_req_t *req)
917 {
918     int error;
919 
920     if ((error = MXC_SPI_RevA1_TransSetup(req)) != E_NO_ERROR) {
921         return error;
922     }
923 
924     states[MXC_SPI_GET_IDX((mxc_spi_regs_t *)req->spi)].async = 1;
925 
926     MXC_SPI_EnableInt((mxc_spi_regs_t *)req->spi, MXC_SPI_RevA1_MasterTransHandler(req->spi, req));
927 
928     return E_NO_ERROR;
929 }
930 
MXC_SPI_RevA1_MasterTransactionDMA(mxc_spi_reva_req_t * req,int reqselTx,int reqselRx,mxc_dma_regs_t * dma)931 int MXC_SPI_RevA1_MasterTransactionDMA(mxc_spi_reva_req_t *req, int reqselTx, int reqselRx,
932                                        mxc_dma_regs_t *dma)
933 {
934     int spi_num;
935     uint8_t error, bits;
936     mxc_dma_config_t config;
937     mxc_dma_srcdst_t srcdst;
938     mxc_dma_adv_config_t advConfig = {
939         0, MXC_DMA_PRIO_HIGH, 0, MXC_DMA_TIMEOUT_4_CLK, MXC_DMA_PRESCALE_DISABLE, 0
940     };
941 
942     spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)(req->spi));
943 
944     if (req->txData == NULL && req->rxData == NULL) {
945         return E_BAD_PARAM;
946     }
947 
948     if ((error = MXC_SPI_RevA1_TransSetup(req)) != E_NO_ERROR) {
949         return error;
950     }
951 
952     // for non-MT mode do this setup every time, for MT mode only first time
953     if ((states[spi_num].mtMode == 0) ||
954         ((states[spi_num].mtMode == 1) && (states[spi_num].mtFirstTrans == 1))) {
955 #if TARGET_NUM == 32665
956         MXC_DMA_Init(dma);
957         states[spi_num].channelTx = MXC_DMA_AcquireChannel(dma);
958         states[spi_num].channelRx = MXC_DMA_AcquireChannel(dma);
959 #else
960         MXC_DMA_Init();
961         states[spi_num].channelTx = MXC_DMA_AcquireChannel();
962         states[spi_num].channelRx = MXC_DMA_AcquireChannel();
963 #endif
964 
965         if ((states[spi_num].channelTx < 0) || (states[spi_num].channelRx < 0)) {
966             states[spi_num].channelTx = E_NO_DEVICE;
967             states[spi_num].channelRx = E_NO_DEVICE;
968             return E_NO_DEVICE;
969         }
970 
971         states[spi_num].mtFirstTrans = 0;
972 
973         // Configure SS for per-transaction or always on
974         if (req->ssDeassert) {
975             req->spi->ctrl0 &= ~MXC_F_SPI_REVA_CTRL0_SS_CTRL;
976         } else {
977             req->spi->ctrl0 |= MXC_F_SPI_REVA_CTRL0_SS_CTRL;
978         }
979     }
980 
981     bits = MXC_SPI_GetDataSize((mxc_spi_regs_t *)req->spi);
982 
983     /*
984     There is a known issue with the SPI hardware and DMA.  The SPI FIFO must be pre-loaded before DMA is initiated,
985     otherwise the it will not work properly.  To do that, we leverage the TransHandler function, which will load the
986     FIFOs as much as possible.
987 
988     If the TX or RX length is less than the FIFO size, there will be nothing for the DMA to transfer.  We need extra logic
989     to ensure that the callbacks are still run in this case.  The TransHandler function returns a mask indicating the enabled
990     interrupts.  Interrupts are only enabled if DMA is still needed.  We check this mask to see if DMA is still needed for RX/TX.
991     Otherwise, we start the transmission (FIFOs are loaded, but a start is still needed to empty them) and then manually run the callbacks.
992     */
993     uint32_t enabled_interrupts = MXC_SPI_RevA1_TransHandler(req->spi, req);
994     // TX FIFO is loaded completely.  DMA is not needed.
995     bool tx_is_complete = !(enabled_interrupts & MXC_F_SPI_REVA_INTEN_TX_THD) &&
996                           (req->txCnt == req->txLen);
997     // RX FIFO is loaded completely.  DMA is not needed.
998     bool rx_is_complete = !(enabled_interrupts & MXC_F_SPI_REVA_INTEN_RX_THD) &&
999                           (req->rxCnt == req->rxLen);
1000 
1001     if (bits <= 8) {
1002         MXC_SPI_SetTXThreshold((mxc_spi_regs_t *)req->spi, 1); //set threshold to 1 byte
1003         MXC_SPI_SetRXThreshold((mxc_spi_regs_t *)req->spi, 0); //set threshold to 0 bytes
1004     } else {
1005         MXC_SPI_SetTXThreshold((mxc_spi_regs_t *)req->spi, 2);
1006         MXC_SPI_SetRXThreshold((mxc_spi_regs_t *)req->spi, 0);
1007     }
1008 
1009     //tx
1010     if (req->txData != NULL && !tx_is_complete) {
1011         MXC_DMA_SetCallback(states[spi_num].channelTx, MXC_SPI_RevA1_DMACallback);
1012         MXC_DMA_EnableInt(states[spi_num].channelTx);
1013         config.reqsel = (mxc_dma_reqsel_t)reqselTx;
1014         config.ch = states[spi_num].channelTx;
1015         advConfig.ch = states[spi_num].channelTx;
1016         advConfig.burst_size = 2;
1017 
1018         if (bits <= 8) {
1019             config.srcwd = MXC_DMA_WIDTH_BYTE;
1020             config.dstwd = MXC_DMA_WIDTH_BYTE;
1021         } else {
1022             config.srcwd = MXC_DMA_WIDTH_HALFWORD;
1023             config.dstwd = MXC_DMA_WIDTH_HALFWORD;
1024         }
1025 
1026         config.srcinc_en = 1;
1027         config.dstinc_en = 0;
1028 
1029         srcdst.ch = states[spi_num].channelTx;
1030         srcdst.source = &(req->txData[req->txCnt]);
1031 
1032         if (bits > 8) {
1033             srcdst.len = (req->txLen * 2) - req->txCnt;
1034         } else {
1035             srcdst.len = (req->txLen) - req->txCnt;
1036         }
1037 
1038         MXC_DMA_ConfigChannel(config, srcdst);
1039         MXC_DMA_Start(states[spi_num].channelTx);
1040         MXC_DMA_SetChannelInterruptEn(states[spi_num].channelTx, false, true);
1041         //MXC_DMA->ch[channel].ctrl |= MXC_F_DMA_CTRL_CTZ_IE;
1042 
1043         if (bits > 8) {
1044             MXC_DMA_AdvConfigChannel(advConfig);
1045             //MXC_SETFIELD (MXC_DMA->ch[channel].ctrl, MXC_F_DMA_CTRL_BURST_SIZE, 1 << MXC_F_DMA_CTRL_BURST_SIZE_POS);
1046         }
1047     }
1048 
1049     // rx
1050     if (req->rxData != NULL && !rx_is_complete) {
1051         MXC_DMA_SetCallback(states[spi_num].channelRx, MXC_SPI_RevA1_DMACallback);
1052         MXC_DMA_EnableInt(states[spi_num].channelRx);
1053         config.reqsel = (mxc_dma_reqsel_t)reqselRx;
1054         config.ch = states[spi_num].channelRx;
1055         config.srcinc_en = 0;
1056         config.dstinc_en = 1;
1057         advConfig.ch = states[spi_num].channelRx;
1058         advConfig.burst_size = 1;
1059 
1060         if (bits <= 8) {
1061             config.srcwd = MXC_DMA_WIDTH_BYTE;
1062             config.dstwd = MXC_DMA_WIDTH_BYTE;
1063         } else {
1064             config.srcwd = MXC_DMA_WIDTH_HALFWORD;
1065             config.dstwd = MXC_DMA_WIDTH_HALFWORD;
1066         }
1067 
1068         srcdst.ch = states[spi_num].channelRx;
1069         srcdst.dest = req->rxData;
1070 
1071         if (bits <= 8) {
1072             srcdst.len = req->rxLen;
1073         } else {
1074             srcdst.len = req->rxLen * 2;
1075         }
1076 
1077         MXC_DMA_ConfigChannel(config, srcdst);
1078         MXC_DMA_Start(states[spi_num].channelRx);
1079         MXC_DMA_SetChannelInterruptEn(states[spi_num].channelRx, false, true);
1080         //MXC_DMA->ch[channel].ctrl |= MXC_F_DMA_CTRL_CTZ_IE;
1081 
1082         if (bits > 8) {
1083             MXC_DMA_AdvConfigChannel(advConfig);
1084             //MXC_SETFIELD (MXC_DMA->ch[channel].ctrl, MXC_F_DMA_CTRL_BURST_SIZE, 0 << MXC_F_DMA_CTRL_BURST_SIZE_POS);
1085         }
1086     }
1087 
1088     // Enable TX/RX DMA, but only if it's still needed.
1089     (req->spi)->dma |= ((!(tx_is_complete) << MXC_F_SPI_REVA_DMA_DMA_TX_EN_POS) |
1090                         (!(rx_is_complete) << MXC_F_SPI_REVA_DMA_DMA_RX_EN_POS));
1091 
1092     if (!states[spi_num].started) {
1093         MXC_SPI_StartTransmission((mxc_spi_regs_t *)req->spi);
1094         states[spi_num].started = 1;
1095     }
1096 
1097     // Manually run TX/RX callbacks if the FIFO pre-load already completed that portion of the transaction
1098     if (tx_is_complete) {
1099         MXC_SPI_RevA1_DMACallback(states[spi_num].channelTx, E_NO_ERROR);
1100     }
1101 
1102     if (rx_is_complete) {
1103         MXC_SPI_RevA1_DMACallback(states[spi_num].channelRx, E_NO_ERROR);
1104     }
1105 
1106     return E_NO_ERROR;
1107 }
1108 
MXC_SPI_RevA1_SlaveTransaction(mxc_spi_reva_req_t * req)1109 int MXC_SPI_RevA1_SlaveTransaction(mxc_spi_reva_req_t *req)
1110 {
1111     int error;
1112 
1113     if ((error = MXC_SPI_RevA1_TransSetup(req)) != E_NO_ERROR) {
1114         return error;
1115     }
1116 
1117     states[MXC_SPI_GET_IDX((mxc_spi_regs_t *)req->spi)].async = 0;
1118 
1119     while (MXC_SPI_RevA1_SlaveTransHandler(req) != 0) {}
1120 
1121     return E_NO_ERROR;
1122 }
1123 
MXC_SPI_RevA1_SlaveTransactionAsync(mxc_spi_reva_req_t * req)1124 int MXC_SPI_RevA1_SlaveTransactionAsync(mxc_spi_reva_req_t *req)
1125 {
1126     int error;
1127 
1128     if ((error = MXC_SPI_RevA1_TransSetup(req)) != E_NO_ERROR) {
1129         return error;
1130     }
1131 
1132     states[MXC_SPI_GET_IDX((mxc_spi_regs_t *)req->spi)].async = 1;
1133 
1134     MXC_SPI_EnableInt((mxc_spi_regs_t *)req->spi, MXC_SPI_RevA1_SlaveTransHandler(req));
1135 
1136     return E_NO_ERROR;
1137 }
1138 
MXC_SPI_RevA1_SlaveTransactionDMA(mxc_spi_reva_req_t * req,int reqselTx,int reqselRx,mxc_dma_regs_t * dma)1139 int MXC_SPI_RevA1_SlaveTransactionDMA(mxc_spi_reva_req_t *req, int reqselTx, int reqselRx,
1140                                       mxc_dma_regs_t *dma)
1141 {
1142     int spi_num;
1143     uint8_t error, bits;
1144     mxc_dma_config_t config;
1145     mxc_dma_srcdst_t srcdst;
1146     mxc_dma_adv_config_t advConfig = {
1147         0, MXC_DMA_PRIO_HIGH, 0, MXC_DMA_TIMEOUT_4_CLK, MXC_DMA_PRESCALE_DISABLE, 0
1148     };
1149 
1150     spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)(req->spi));
1151 
1152     if (req->txData == NULL && req->rxData == NULL) {
1153         return E_BAD_PARAM;
1154     }
1155 
1156     if ((error = MXC_SPI_RevA1_TransSetup(req)) != E_NO_ERROR) {
1157         return error;
1158     }
1159 
1160     // for non-MT mode do this setup every time, for MT mode only first time
1161     if ((states[spi_num].mtMode == 0) ||
1162         ((states[spi_num].mtMode == 1) && (states[spi_num].mtFirstTrans == 1))) {
1163 #if TARGET_NUM == 32665
1164         MXC_DMA_Init(dma);
1165         states[spi_num].channelTx = MXC_DMA_AcquireChannel(dma);
1166         states[spi_num].channelRx = MXC_DMA_AcquireChannel(dma);
1167 #else
1168         MXC_DMA_Init();
1169         states[spi_num].channelTx = MXC_DMA_AcquireChannel();
1170         states[spi_num].channelRx = MXC_DMA_AcquireChannel();
1171 #endif
1172 
1173         if ((states[spi_num].channelTx < 0) || (states[spi_num].channelRx < 0)) {
1174             states[spi_num].channelTx = E_NO_DEVICE;
1175             states[spi_num].channelRx = E_NO_DEVICE;
1176             return E_NO_DEVICE;
1177         }
1178 
1179         states[spi_num].mtFirstTrans = 0;
1180 
1181         MXC_DMA_SetCallback(states[spi_num].channelTx, MXC_SPI_RevA1_DMACallback);
1182         MXC_DMA_SetCallback(states[spi_num].channelRx, MXC_SPI_RevA1_DMACallback);
1183         MXC_DMA_EnableInt(states[spi_num].channelTx);
1184         MXC_DMA_EnableInt(states[spi_num].channelRx);
1185     }
1186 
1187     bits = MXC_SPI_GetDataSize((mxc_spi_regs_t *)req->spi);
1188 
1189     MXC_SPI_RevA1_TransHandler(req->spi, req);
1190 
1191     if (bits <= 8) {
1192         MXC_SPI_SetTXThreshold((mxc_spi_regs_t *)req->spi, 1);
1193         MXC_SPI_SetRXThreshold((mxc_spi_regs_t *)req->spi, 0);
1194     } else {
1195         MXC_SPI_SetTXThreshold((mxc_spi_regs_t *)req->spi, 2);
1196         MXC_SPI_SetRXThreshold((mxc_spi_regs_t *)req->spi, 0);
1197     }
1198 
1199     //tx
1200     if (req->txData != NULL) {
1201         config.reqsel = (mxc_dma_reqsel_t)reqselTx;
1202         config.ch = states[spi_num].channelTx;
1203         advConfig.ch = states[spi_num].channelTx;
1204         advConfig.burst_size = 2;
1205 
1206         if (bits <= 8) {
1207             config.srcwd = MXC_DMA_WIDTH_BYTE;
1208             config.dstwd = MXC_DMA_WIDTH_BYTE;
1209         } else {
1210             config.srcwd = MXC_DMA_WIDTH_HALFWORD;
1211             config.dstwd = MXC_DMA_WIDTH_HALFWORD;
1212         }
1213 
1214         config.srcinc_en = 1;
1215         config.dstinc_en = 0;
1216 
1217         srcdst.ch = states[spi_num].channelTx;
1218         srcdst.source = &(req->txData[req->txCnt]);
1219 
1220         if (bits > 8) {
1221             srcdst.len = (req->txLen * 2) - req->txCnt;
1222         } else {
1223             srcdst.len = (req->txLen) - req->txCnt;
1224         }
1225 
1226         MXC_DMA_ConfigChannel(config, srcdst);
1227         MXC_DMA_Start(states[spi_num].channelTx);
1228         MXC_DMA_SetChannelInterruptEn(states[spi_num].channelTx, false, true);
1229         //MXC_DMA->ch[channel].ctrl |= MXC_F_DMA_CTRL_CTZ_IE;
1230 
1231         if (bits > 8) {
1232             MXC_DMA_AdvConfigChannel(advConfig);
1233             //MXC_SETFIELD (MXC_DMA->ch[channel].ctrl, MXC_F_DMA_CTRL_BURST_SIZE, 1 << MXC_F_DMA_CTRL_BURST_SIZE_POS);
1234         }
1235     }
1236 
1237     if (req->rxData != NULL) {
1238         config.reqsel = (mxc_dma_reqsel_t)reqselRx;
1239         config.ch = states[spi_num].channelRx;
1240         config.srcinc_en = 0;
1241         config.dstinc_en = 1;
1242         advConfig.ch = states[spi_num].channelRx;
1243         advConfig.burst_size = 1;
1244 
1245         if (bits <= 8) {
1246             config.srcwd = MXC_DMA_WIDTH_BYTE;
1247             config.dstwd = MXC_DMA_WIDTH_BYTE;
1248         } else {
1249             config.srcwd = MXC_DMA_WIDTH_HALFWORD;
1250             config.dstwd = MXC_DMA_WIDTH_HALFWORD;
1251         }
1252 
1253         srcdst.ch = states[spi_num].channelRx;
1254         srcdst.dest = req->rxData;
1255 
1256         if (bits <= 8) {
1257             srcdst.len = req->rxLen;
1258         } else {
1259             srcdst.len = req->rxLen * 2;
1260         }
1261 
1262         MXC_DMA_ConfigChannel(config, srcdst);
1263         MXC_DMA_Start(states[spi_num].channelRx);
1264         MXC_DMA_SetChannelInterruptEn(states[spi_num].channelRx, false, true);
1265         //MXC_DMA->ch[channel].ctrl |= MXC_F_DMA_CTRL_CTZ_IE;
1266 
1267         if (bits > 8) {
1268             MXC_DMA_AdvConfigChannel(advConfig);
1269             //MXC_SETFIELD (MXC_DMA->ch[channel].ctrl, MXC_F_DMA_CTRL_BURST_SIZE, 0 << MXC_F_DMA_CTRL_BURST_SIZE_POS);
1270         }
1271     }
1272 
1273     (req->spi)->dma |= (MXC_F_SPI_REVA_DMA_DMA_TX_EN | MXC_F_SPI_REVA_DMA_DMA_RX_EN);
1274 
1275     return E_NO_ERROR;
1276 }
1277 
MXC_SPI_RevA1_DMACallback(int ch,int error)1278 void MXC_SPI_RevA1_DMACallback(int ch, int error)
1279 {
1280     mxc_spi_reva_req_t *temp_req;
1281 
1282     for (int i = 0; i < MXC_SPI_INSTANCES; i++) {
1283         if (states[i].req != NULL) {
1284             if (states[i].channelTx == ch) {
1285                 states[i].req_done++;
1286             } else if (states[i].channelRx == ch) {
1287                 states[i].req_done++;
1288                 //save the request
1289                 temp_req = states[i].req;
1290 
1291                 if (MXC_SPI_GetDataSize((mxc_spi_regs_t *)temp_req->spi) > 8) {
1292                     MXC_SPI_RevA1_SwapByte(temp_req->rxData, temp_req->rxLen);
1293                 }
1294             }
1295 
1296             if (!states[i].txrx_req || (states[i].txrx_req && states[i].req_done == 2)) {
1297                 //save the request
1298                 temp_req = states[i].req;
1299                 MXC_FreeLock((uint32_t *)&states[i].req);
1300                 // Callback if not NULL
1301                 if (temp_req->completeCB != NULL) {
1302                     temp_req->completeCB(temp_req, E_NO_ERROR);
1303                 }
1304                 if (states[i].mtMode == 0) {
1305                     // release any acquired DMA channels
1306                     if (states[i].channelTx >= 0) {
1307                         MXC_DMA_RevA_ReleaseChannel(states[i].channelTx);
1308                         states[i].channelTx = E_NO_DEVICE;
1309                     }
1310                     if (states[i].channelRx >= 0) {
1311                         MXC_DMA_RevA_ReleaseChannel(states[i].channelRx);
1312                         states[i].channelRx = E_NO_DEVICE;
1313                     }
1314                 }
1315                 break;
1316             }
1317         }
1318     }
1319 }
1320 
MXC_SPI_RevA1_SetDefaultTXData(mxc_spi_reva_regs_t * spi,unsigned int defaultTXData)1321 int MXC_SPI_RevA1_SetDefaultTXData(mxc_spi_reva_regs_t *spi, unsigned int defaultTXData)
1322 {
1323     int spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
1324 
1325     states[spi_num].defaultTXData = defaultTXData;
1326     return E_NO_ERROR;
1327 }
1328 
MXC_SPI_RevA1_AbortAsync(mxc_spi_reva_regs_t * spi)1329 void MXC_SPI_RevA1_AbortAsync(mxc_spi_reva_regs_t *spi)
1330 {
1331     MXC_SPI_AbortTransmission((mxc_spi_regs_t *)spi);
1332 }
1333 
MXC_SPI_RevA1_AsyncHandler(mxc_spi_reva_regs_t * spi)1334 void MXC_SPI_RevA1_AsyncHandler(mxc_spi_reva_regs_t *spi)
1335 {
1336     int spi_num;
1337     unsigned rx_avail;
1338     uint32_t flags;
1339 
1340     // Clear the interrupt flags
1341     spi->inten = 0;
1342     flags = spi->intfl;
1343     spi->intfl = flags;
1344 
1345     spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
1346 
1347     // Figure out if this SPI has an active request
1348     if ((states[spi_num].req != NULL) && (flags)) {
1349         if ((spi->ctrl0 & MXC_F_SPI_REVA_CTRL0_MST_MODE) >> MXC_F_SPI_REVA_CTRL0_MST_MODE_POS) {
1350             do {
1351                 spi->inten = MXC_SPI_RevA1_MasterTransHandler(spi, states[spi_num].req);
1352                 rx_avail = MXC_SPI_RevA1_GetRXFIFOAvailable(spi);
1353             } while (rx_avail > MXC_SPI_RevA1_GetRXThreshold(spi));
1354 
1355         } else {
1356             do {
1357                 spi->inten = MXC_SPI_RevA1_SlaveTransHandler(states[spi_num].req);
1358                 rx_avail = MXC_SPI_RevA1_GetRXFIFOAvailable(spi);
1359             } while (rx_avail > MXC_SPI_RevA1_GetRXThreshold(spi));
1360         }
1361     }
1362 }
1363 
1364 //call in DMA IRQHANDLER with rxData for transmissions with bits > 8
MXC_SPI_RevA1_SwapByte(uint8_t * arr,size_t length)1365 void MXC_SPI_RevA1_SwapByte(uint8_t *arr, size_t length)
1366 {
1367     MXC_ASSERT(arr != NULL);
1368 
1369     for (size_t i = 0; i < (length * 2); i += 2) {
1370         uint8_t tmp = arr[i];
1371         arr[i] = arr[i + 1];
1372         arr[i + 1] = tmp;
1373     }
1374 }
1375 
MXC_SPI_RevA1_HWSSControl(mxc_spi_reva_regs_t * spi,int state)1376 void MXC_SPI_RevA1_HWSSControl(mxc_spi_reva_regs_t *spi, int state)
1377 {
1378     int spi_num;
1379 
1380     spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
1381 
1382     states[spi_num].hw_ss_control = state ? true : false;
1383 
1384     return;
1385 }
1386