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