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_errors.h"
27 #include "mxc_assert.h"
28 #include "mxc_lock.h"
29 #include "mxc_sys.h"
30 #include "mxc_delay.h"
31 #include "nvic_table.h"
32 #include "spi.h"
33 #include "spi_reva2.h"
34 #include "dma_reva.h"
35
36 /* **** Definitions **** */
37
38 // clang-format off
39 typedef struct {
40 // Info from initialization.
41 bool dma_initialized;
42 mxc_spi_type_t controller_target; // Controller or Target Mode.
43 uint8_t frame_size; //
44 mxc_spi_interface_t if_mode;
45
46
47 // Transaction Data.
48 uint8_t *tx_buffer;
49 uint32_t tx_length_bytes; // Terms of bytes
50 uint32_t tx_count_bytes; // Terms of bytes
51 uint8_t *rx_buffer;
52 uint32_t rx_length_bytes; // Terms of bytes
53 uint32_t rx_count_bytes;
54 uint16_t tx_dummy_value;
55
56 mxc_spi_callback_t callback;
57 void *callback_data;
58
59 // Chip Select Info.
60 bool deassert; // Target Select (TS) Deasserted at the end of a transmission.
61 mxc_spi_tscontrol_t ts_control;
62
63 // DMA Settings.
64 mxc_dma_reva_regs_t *dma;
65 int tx_dma_ch;
66 int rx_dma_ch;
67
68 // Status Fields.
69 bool transaction_done;
70 bool tx_done;
71 bool rx_done;
72 } mxc_spi_reva2_handle_data_t;
73 // clang-format on
74
75 static volatile mxc_spi_reva2_handle_data_t STATES[MXC_SPI_INSTANCES];
76
77 /* **** Private Functions **** */
78
79 // The unique title for Private functions will not be capitalized.
80
81 /** Private Function: writeTXFIFO16
82 * Writes 2 bytes to the TX FIFO for 9-16 bit frame lengths.
83 * This function helps package the frame when the STATES[n] fields
84 * are all in terms of bytes.
85 *
86 * @param spi Pointer to SPI instance.
87 * @param buffer Pointer to buffer of messages to transmit.
88 * @param length_bytes Number of messages (in terms of bytes) in buffer to transmit.
89 *
90 * @return count The number of frames written to the TX FIFO.
91 */
MXC_SPI_RevA2_writeTXFIFO16(mxc_spi_reva_regs_t * spi,uint8_t * buffer,uint32_t length_bytes)92 static uint32_t MXC_SPI_RevA2_writeTXFIFO16(mxc_spi_reva_regs_t *spi, uint8_t *buffer,
93 uint32_t length_bytes)
94 {
95 uint32_t tx_avail;
96 uint32_t count = 0;
97
98 if (buffer == NULL || length_bytes == 0) {
99 return 0;
100 }
101
102 tx_avail = MXC_SPI_FIFO_DEPTH -
103 ((spi->dma & MXC_F_SPI_REVA_DMA_TX_LVL) >> MXC_F_SPI_REVA_DMA_TX_LVL_POS);
104
105 // Do not write more than the available FIFO size
106 if (length_bytes > tx_avail) {
107 length_bytes = tx_avail;
108 }
109
110 // Ensure even lengths for halfword frame lengths.
111 // Note: Len is in terms of bytes, so sending 9-16bit transactions means sending
112 // 2 bytes per frame.
113 length_bytes &= ~0x01;
114
115 while (length_bytes) {
116 if (length_bytes > 3) {
117 memcpy((void *)(&spi->fifo32), (uint8_t *)(&buffer[count]), 4);
118
119 length_bytes -= 4;
120 count += 4;
121
122 } else if (length_bytes > 1) {
123 memcpy((void *)(&spi->fifo16[0]), (uint8_t *)(&buffer[count]), 2);
124
125 length_bytes -= 2;
126 count += 2;
127 }
128 }
129
130 return count;
131 }
132
133 /** Private Function: readRXFIFO16
134 * Reads 2 bytes from the RX FIFO for 9-16 bit frame lengths.
135 * This function helps package the frame when the STATES[n] fields
136 * are all in terms of bytes.
137 *
138 * @param spi Pointer to SPI instance.
139 * @param buffer Pointer to buffer to store read messages.
140 * @param length_bytes Number of messages (in terms of bytes) to store in receive buffer.
141 *
142 * @return count The number of frames read from the RX FIFO.
143 */
MXC_SPI_RevA2_readRXFIFO16(mxc_spi_reva_regs_t * spi,uint8_t * buffer,uint32_t length_bytes)144 static uint32_t MXC_SPI_RevA2_readRXFIFO16(mxc_spi_reva_regs_t *spi, uint8_t *buffer,
145 uint32_t length_bytes)
146 {
147 uint32_t rx_avail;
148 uint32_t count = 0;
149
150 if (buffer == NULL || length_bytes == 0) {
151 return 0;
152 }
153
154 rx_avail = (spi->dma & MXC_F_SPI_REVA_DMA_RX_LVL) >> MXC_F_SPI_REVA_DMA_RX_LVL_POS;
155
156 // Do not read more than available frames in RX FIFO.
157 if (length_bytes > rx_avail) {
158 length_bytes = rx_avail;
159 }
160
161 // Ensure even lengths for halfword frame lengths.
162 // Note: Len is in terms of bytes, so reading 9-16bit wide messages means reading
163 // 2 bytes per frame.
164 length_bytes &= ~0x01;
165
166 if (length_bytes >= 2) {
167 // Read from the FIFO
168 while (length_bytes) {
169 if (length_bytes > 3) {
170 memcpy((uint8_t *)(&buffer[count]), (void *)(&spi->fifo32), 4);
171 length_bytes -= 4;
172 count += 4;
173
174 } else if (length_bytes > 1) {
175 memcpy((uint8_t *)(&buffer[count]), (void *)(&spi->fifo16[0]), 2);
176 length_bytes -= 2;
177 count += 2;
178 }
179
180 // Ensures read of less than 2 bytes aren't read.
181 // Code should never get to this point.
182 if (length_bytes == 1) {
183 break;
184 }
185 }
186 }
187
188 return count;
189 }
190
191 /** Private Function: process
192 * This function handles the reads and writes to the SPI RX/TX FIFO.
193 *
194 * @param spi Pointer to SPI instance.
195 */
MXC_SPI_RevA2_process(mxc_spi_reva_regs_t * spi)196 static void MXC_SPI_RevA2_process(mxc_spi_reva_regs_t *spi)
197 {
198 int8_t spi_num;
199 int remain;
200
201 spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
202
203 // Write any pending bytes out.
204 // Dependent on 1) Valid TX Buffer, 2) TX Length not 0, and 3) TX FIFO Not Empty.
205 if (STATES[spi_num].tx_buffer && STATES[spi_num].tx_length_bytes > 0) {
206 // Write to the FIFO for byte size transactions (message sizes for 8 bits or less)
207 if (STATES[spi_num].frame_size <= 8) {
208 while (((spi->dma & MXC_F_SPI_REVA_DMA_TX_LVL) >> MXC_F_SPI_REVA_DMA_TX_LVL_POS) <
209 (MXC_SPI_FIFO_DEPTH)) {
210 // Check for overflow.
211 if (STATES[spi_num].tx_count_bytes == STATES[spi_num].tx_length_bytes) {
212 break;
213 }
214
215 spi->fifo8[0] = STATES[spi_num].tx_buffer[STATES[spi_num].tx_count_bytes];
216 STATES[spi_num].tx_count_bytes += 1;
217 }
218
219 // Write to the FIFO for halfword size transactions (message sizes for 9 bits or greater)
220 } else {
221 STATES[spi_num].tx_count_bytes += MXC_SPI_RevA2_writeTXFIFO16(
222 spi, &(STATES[spi_num].tx_buffer[STATES[spi_num].tx_count_bytes]),
223 STATES[spi_num].tx_length_bytes - STATES[spi_num].tx_count_bytes);
224
225 remain = STATES[spi_num].tx_length_bytes - STATES[spi_num].tx_count_bytes;
226
227 if (remain) {
228 if (remain >= MXC_SPI_FIFO_DEPTH) {
229 MXC_SETFIELD(spi->dma, MXC_F_SPI_REVA_DMA_TX_THD_VAL,
230 ((MXC_SPI_FIFO_DEPTH - 1) << MXC_F_SPI_REVA_DMA_TX_THD_VAL_POS));
231 } else {
232 MXC_SETFIELD(spi->dma, MXC_F_SPI_REVA_DMA_TX_THD_VAL,
233 (remain << MXC_F_SPI_REVA_DMA_TX_THD_VAL_POS));
234 }
235 }
236 }
237 }
238
239 if (STATES[spi_num].tx_count_bytes == STATES[spi_num].tx_length_bytes) {
240 STATES[spi_num].tx_done = true;
241 }
242
243 // Unload any SPI data that has come in
244 // Dependent on 1) Valid RX Buffer, 2) RX Length not 0, and 3) RX FIFO Not Empty.
245 if (STATES[spi_num].rx_buffer && STATES[spi_num].rx_length_bytes > 0) {
246 // Read the FIFO for byte size transactions (message sizes for 8 bits or less)
247 if (STATES[spi_num].frame_size <= 8) {
248 while ((spi->dma & MXC_F_SPI_REVA_DMA_RX_LVL)) {
249 // Check for overflow.
250 if (STATES[spi_num].rx_count_bytes == STATES[spi_num].rx_length_bytes) {
251 break;
252 }
253
254 STATES[spi_num].rx_buffer[STATES[spi_num].rx_count_bytes] = spi->fifo8[0];
255 STATES[spi_num].rx_count_bytes += 1;
256 }
257
258 // Read the FIFO for halfword size transactions (message sizes for 9 bits or greater)
259 } else {
260 STATES[spi_num].rx_count_bytes += MXC_SPI_RevA2_readRXFIFO16(
261 spi, &(STATES[spi_num].rx_buffer[STATES[spi_num].rx_count_bytes]),
262 STATES[spi_num].rx_length_bytes - STATES[spi_num].rx_count_bytes);
263
264 remain = STATES[spi_num].rx_length_bytes - STATES[spi_num].rx_count_bytes;
265
266 if (remain) {
267 if (remain >= MXC_SPI_FIFO_DEPTH) {
268 MXC_SETFIELD(spi->dma, MXC_F_SPI_REVA_DMA_RX_THD_VAL,
269 (2 << MXC_F_SPI_REVA_DMA_RX_THD_VAL_POS));
270 } else {
271 MXC_SETFIELD(spi->dma, MXC_F_SPI_REVA_DMA_RX_THD_VAL,
272 ((remain - 1) << MXC_F_SPI_REVA_DMA_RX_THD_VAL_POS));
273 }
274 }
275 }
276 }
277
278 if (STATES[spi_num].rx_count_bytes == STATES[spi_num].rx_length_bytes) {
279 STATES[spi_num].rx_done = true;
280 }
281
282 // Handle Target Transaction Completion.
283 // Unlike the Controller, there is no Target Done interrupt to handle the callback and set the
284 // transaction_done flag.
285 if (STATES[spi_num].controller_target == MXC_SPI_TYPE_TARGET) {
286 // Check if the transaction is complete.
287 if (STATES[spi_num].tx_done == true && STATES[spi_num].rx_done == true) {
288 // Callback if valid.
289 // Note: If Target Select (TS) Control Scheme is set in SW_App mode, then the caller needs to ensure the
290 // Target Select (TS) pin is asserted or deasserted in their application.
291 if (STATES[spi_num].callback) {
292 STATES[spi_num].callback(STATES[spi_num].callback_data, E_NO_ERROR);
293 }
294
295 // Target is done after callback (if valid) is handled.
296 STATES[spi_num].transaction_done = true;
297
298 // Reset the SPI to complete the on-going transaction.
299 // SPIn may remain busy (SPI_STAT) even after the target select input
300 // is deasserted. This ensures the SPI block is not busy after a
301 // target transaction is completed.
302 spi->ctrl0 &= ~(MXC_F_SPI_REVA_CTRL0_EN);
303 spi->ctrl0 |= (MXC_F_SPI_REVA_CTRL0_EN);
304 }
305 }
306 }
307
308 /** Private Function: resetStateStruct
309 * This functions resets the STATE of an SPI instance.
310 *
311 * @param spi_num Index number of SPI instance.
312 */
MXC_SPI_RevA2_resetStateStruct(int8_t spi_num)313 static void MXC_SPI_RevA2_resetStateStruct(int8_t spi_num)
314 {
315 // Init Data
316 STATES[spi_num].dma_initialized = false;
317 STATES[spi_num].controller_target = MXC_SPI_TYPE_CONTROLLER;
318 STATES[spi_num].frame_size = 8; // 1 byte frame sizes.
319 STATES[spi_num].if_mode = MXC_SPI_INTERFACE_STANDARD;
320
321 // Transaction Members
322 STATES[spi_num].tx_buffer = NULL;
323 STATES[spi_num].tx_length_bytes = 0;
324 STATES[spi_num].tx_count_bytes = 0;
325 STATES[spi_num].rx_buffer = NULL;
326 STATES[spi_num].rx_length_bytes = 0;
327 STATES[spi_num].rx_count_bytes = 0;
328 STATES[spi_num].deassert =
329 true; // Default state is TS will be deasserted at the end of a transmission.
330 STATES[spi_num].ts_control = MXC_SPI_TSCONTROL_HW_AUTO; // Default (0) state.
331
332 // DMA
333 STATES[spi_num].dma = NULL;
334 STATES[spi_num].tx_dma_ch = -1;
335 STATES[spi_num].rx_dma_ch = -1;
336
337 // Status Members
338 STATES[spi_num].transaction_done = false;
339 STATES[spi_num].tx_done = false;
340 STATES[spi_num].rx_done = false;
341 }
342
343 /* **** Public Functions **** */
344
MXC_SPI_RevA2_Init(mxc_spi_reva_regs_t * spi,mxc_spi_type_t controller_target,mxc_spi_interface_t if_mode,uint32_t freq,uint8_t ts_active_pol_mask)345 int MXC_SPI_RevA2_Init(mxc_spi_reva_regs_t *spi, mxc_spi_type_t controller_target,
346 mxc_spi_interface_t if_mode, uint32_t freq, uint8_t ts_active_pol_mask)
347 {
348 int error;
349 int8_t spi_num;
350
351 spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
352 if (spi_num < 0 || spi_num >= MXC_SPI_INSTANCES) {
353 return E_BAD_PARAM;
354 }
355
356 // Reset STATE of current SPI instance.
357 MXC_SPI_RevA2_resetStateStruct(spi_num);
358
359 // Save init data states.
360 STATES[spi_num].controller_target = controller_target;
361 STATES[spi_num].frame_size = 8;
362 STATES[spi_num].if_mode = if_mode;
363
364 // Enable SPI port.
365 spi->ctrl0 &= ~(MXC_F_SPI_REVA_CTRL0_EN);
366 spi->ctrl0 |= (MXC_F_SPI_REVA_CTRL0_EN);
367
368 // Set Controller (L. Master) or Target (L. Slave) mode.
369 switch (controller_target) {
370 case MXC_SPI_TYPE_CONTROLLER:
371 spi->ctrl0 |= MXC_F_SPI_REVA_CTRL0_MST_MODE;
372 break;
373
374 case MXC_SPI_TYPE_TARGET:
375 spi->ctrl0 &= ~(MXC_F_SPI_REVA_CTRL0_MST_MODE);
376 break;
377
378 default:
379 return E_BAD_PARAM;
380 }
381
382 // Set default frame size to 8 bits wide.
383 MXC_SETFIELD(spi->ctrl2, MXC_F_SPI_REVA_CTRL2_NUMBITS, 8 << MXC_F_SPI_REVA_CTRL2_NUMBITS_POS);
384
385 // Remove any delay between TS (L. SS) and SCLK edges.
386 spi->sstime = (1 << MXC_F_SPI_REVA_SSTIME_PRE_POS) | (1 << MXC_F_SPI_REVA_SSTIME_POST_POS) |
387 (1 << MXC_F_SPI_REVA_SSTIME_INACT_POS);
388
389 // Enable TX/RX FIFOs
390 spi->dma |= MXC_F_SPI_REVA_DMA_TX_FIFO_EN | MXC_F_SPI_REVA_DMA_RX_FIFO_EN;
391
392 // Set TX and RX Threshold to (FIFO_DEPTH - 1) and (0), respectively.
393 MXC_SETFIELD(spi->dma, MXC_F_SPI_REVA_DMA_TX_THD_VAL,
394 ((MXC_SPI_FIFO_DEPTH - 1) << MXC_F_SPI_REVA_DMA_TX_THD_VAL_POS));
395 MXC_SETFIELD(spi->dma, MXC_F_SPI_REVA_DMA_RX_THD_VAL, (0 << MXC_F_SPI_REVA_DMA_RX_THD_VAL_POS));
396
397 // Set Default Clock Mode (CPOL: 0, and CPHA: 0).
398 error = MXC_SPI_SetClkMode((mxc_spi_regs_t *)spi, MXC_SPI_CLKMODE_0);
399 if (error != E_NO_ERROR) {
400 return error;
401 }
402
403 // Interface mode: 3-wire, standard (4-wire), dual, quad.
404 error = MXC_SPI_SetInterface((mxc_spi_regs_t *)spi, if_mode);
405 if (error != E_NO_ERROR) {
406 return error;
407 }
408
409 error = MXC_SPI_SetFrequency((mxc_spi_regs_t *)spi, freq);
410 if (error != E_NO_ERROR) {
411 return error;
412 }
413
414 // Clear any interrupt flags that may already be set.
415 spi->intfl = spi->intfl;
416 spi->inten = 0;
417
418 // Clear the HW TS settings (These are set in the transaction functions).
419 MXC_SETFIELD(spi->ctrl0, MXC_F_SPI_REVA_CTRL0_SS_ACTIVE, 0);
420
421 // Set the TS Active Polarity settings.
422 MXC_SETFIELD(spi->ctrl2, MXC_F_SPI_REVA_CTRL2_SS_POL,
423 ts_active_pol_mask << MXC_F_SPI_REVA_CTRL2_SS_POL_POS);
424
425 return E_NO_ERROR;
426 }
427
MXC_SPI_RevA2_Config(mxc_spi_cfg_t * cfg)428 int MXC_SPI_RevA2_Config(mxc_spi_cfg_t *cfg)
429 {
430 int error;
431 int8_t spi_num;
432
433 if (cfg == NULL) {
434 return E_NULL_PTR;
435 }
436
437 // Ensure valid SPI instance.
438 spi_num = MXC_SPI_GET_IDX(cfg->spi);
439 if (spi_num < 0 || spi_num >= MXC_SPI_INSTANCES) {
440 return E_BAD_PARAM;
441 }
442
443 // Set Single Frame Size.
444 error = MXC_SPI_SetFrameSize((cfg->spi), (cfg->frame_size));
445 if (error != E_NO_ERROR) {
446 return error;
447 }
448
449 // Set Clock Mode (CPOL and CPHA).
450 error = MXC_SPI_SetClkMode((cfg->spi), (cfg->clk_mode));
451 if (error != E_NO_ERROR) {
452 return error;
453 }
454
455 // Setup DMA features if used.
456 if (cfg->use_dma_tx || cfg->use_dma_rx) {
457 error = MXC_SPI_RevA2_DMA_Init((mxc_spi_reva_regs_t *)(cfg->spi),
458 (mxc_dma_reva_regs_t *)(cfg->dma), (cfg->use_dma_tx),
459 (cfg->use_dma_rx));
460 if (error != E_NO_ERROR) {
461 return error;
462 }
463 }
464
465 return E_NO_ERROR;
466 }
467
MXC_SPI_RevA2_Shutdown(mxc_spi_reva_regs_t * spi)468 int MXC_SPI_RevA2_Shutdown(mxc_spi_reva_regs_t *spi)
469 {
470 int8_t spi_num;
471
472 spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
473 if (spi_num < 0 || spi_num >= MXC_SPI_INSTANCES) {
474 return E_BAD_PARAM;
475 }
476
477 // Disable and clear interrupts.
478 spi->inten = 0;
479 spi->intfl = spi->intfl;
480
481 // Disable SPI and FIFOS
482 spi->ctrl0 &= ~(MXC_F_SPI_REVA_CTRL0_EN);
483 spi->dma &= ~(MXC_F_SPI_REVA_DMA_TX_FIFO_EN | MXC_F_SPI_REVA_DMA_RX_FIFO_EN);
484
485 // Clear registers.
486 spi->ctrl0 = 0;
487 spi->ctrl1 = 0;
488 spi->ctrl2 = 0;
489 spi->sstime = 0;
490
491 // Release any acquired DMA channels.
492 if (STATES[spi_num].tx_dma_ch >= 0) {
493 MXC_DMA_ReleaseChannel(STATES[spi_num].tx_dma_ch);
494 STATES[spi_num].tx_dma_ch = E_NO_DEVICE;
495 }
496 if (STATES[spi_num].rx_dma_ch >= 0) {
497 MXC_DMA_ReleaseChannel(STATES[spi_num].rx_dma_ch);
498 STATES[spi_num].rx_dma_ch = E_NO_DEVICE;
499 }
500
501 if (STATES[spi_num].dma_initialized) {
502 MXC_DMA_DeInit();
503 }
504
505 // Reset the SPI instance's STATE when shutting down.
506 MXC_SPI_RevA2_resetStateStruct(spi_num);
507
508 return E_NO_ERROR;
509 }
510
MXC_SPI_RevA2_GetFlags(mxc_spi_reva_regs_t * spi)511 uint32_t MXC_SPI_RevA2_GetFlags(mxc_spi_reva_regs_t *spi)
512 {
513 return spi->intfl;
514 }
515
MXC_SPI_RevA2_ClearFlags(mxc_spi_reva_regs_t * spi)516 void MXC_SPI_RevA2_ClearFlags(mxc_spi_reva_regs_t *spi)
517 {
518 spi->intfl = spi->intfl;
519 }
520
MXC_SPI_RevA2_EnableInt(mxc_spi_reva_regs_t * spi,uint32_t en)521 void MXC_SPI_RevA2_EnableInt(mxc_spi_reva_regs_t *spi, uint32_t en)
522 {
523 spi->inten |= en;
524 }
525
MXC_SPI_RevA2_DisableInt(mxc_spi_reva_regs_t * spi,uint32_t dis)526 void MXC_SPI_RevA2_DisableInt(mxc_spi_reva_regs_t *spi, uint32_t dis)
527 {
528 spi->inten &= ~(dis);
529 }
530
MXC_SPI_RevA2_SetTSControl(mxc_spi_reva_regs_t * spi,mxc_spi_tscontrol_t ts_control)531 int MXC_SPI_RevA2_SetTSControl(mxc_spi_reva_regs_t *spi, mxc_spi_tscontrol_t ts_control)
532 {
533 int8_t spi_num;
534
535 spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
536 if (spi_num < 0 || spi_num >= MXC_SPI_INSTANCES) {
537 return E_BAD_PARAM;
538 }
539
540 switch (ts_control) {
541 case MXC_SPI_TSCONTROL_HW_AUTO:
542 break;
543
544 case MXC_SPI_TSCONTROL_SW_APP:
545 spi->ctrl0 &= ~(MXC_F_SPI_REVA_CTRL0_SS_ACTIVE);
546 spi->ctrl0 &= ~(MXC_F_SPI_REVA_CTRL2_SS_POL);
547 break;
548
549 default:
550 return E_BAD_PARAM;
551 }
552
553 STATES[spi_num].ts_control = ts_control;
554
555 return E_NO_ERROR;
556 }
557
MXC_SPI_RevA2_GetTSControl(mxc_spi_reva_regs_t * spi)558 mxc_spi_tscontrol_t MXC_SPI_RevA2_GetTSControl(mxc_spi_reva_regs_t *spi)
559 {
560 int8_t spi_num;
561
562 spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
563 if (spi_num < 0 || spi_num >= MXC_SPI_INSTANCES) {
564 return E_BAD_PARAM;
565 }
566
567 return (STATES[spi_num].ts_control);
568 }
569
MXC_SPI_RevA2_SetFrequency(mxc_spi_reva_regs_t * spi,uint32_t freq)570 int MXC_SPI_RevA2_SetFrequency(mxc_spi_reva_regs_t *spi, uint32_t freq)
571 {
572 int hi_clk, lo_clk, scale;
573 uint32_t freq_div;
574
575 // Check if frequency is too high
576 if (freq > PeripheralClock) {
577 return E_BAD_PARAM;
578 }
579
580 // Set the clock high and low
581 freq_div = MXC_SPI_GetPeripheralClock((mxc_spi_regs_t *)spi);
582 freq_div = (freq_div / freq);
583
584 hi_clk = freq_div / 2;
585 lo_clk = freq_div / 2;
586 scale = 0;
587
588 if (freq_div % 2) {
589 hi_clk += 1;
590 }
591
592 while (hi_clk >= 16 && scale < 8) {
593 hi_clk /= 2;
594 lo_clk /= 2;
595 scale++;
596 }
597
598 if (scale == 8) {
599 lo_clk = 15;
600 hi_clk = 15;
601 }
602
603 MXC_SETFIELD(spi->clkctrl, MXC_F_SPI_REVA_CLKCTRL_LO,
604 (lo_clk << MXC_F_SPI_REVA_CLKCTRL_LO_POS));
605 MXC_SETFIELD(spi->clkctrl, MXC_F_SPI_REVA_CLKCTRL_HI,
606 (hi_clk << MXC_F_SPI_REVA_CLKCTRL_HI_POS));
607 MXC_SETFIELD(spi->clkctrl, MXC_F_SPI_REVA_CLKCTRL_CLKDIV,
608 (scale << MXC_F_SPI_REVA_CLKCTRL_CLKDIV_POS));
609
610 return E_NO_ERROR;
611 }
612
MXC_SPI_RevA2_GetFrequency(mxc_spi_reva_regs_t * spi)613 int MXC_SPI_RevA2_GetFrequency(mxc_spi_reva_regs_t *spi)
614 {
615 unsigned scale, lo_clk, hi_clk;
616
617 scale = (spi->clkctrl & MXC_F_SPI_REVA_CLKCTRL_CLKDIV) >> MXC_F_SPI_REVA_CLKCTRL_CLKDIV_POS;
618 hi_clk = (spi->clkctrl & MXC_F_SPI_REVA_CLKCTRL_HI) >> MXC_F_SPI_REVA_CLKCTRL_HI_POS;
619 lo_clk = (spi->clkctrl & MXC_F_SPI_REVA_CLKCTRL_LO) >> MXC_F_SPI_REVA_CLKCTRL_LO_POS;
620
621 return (PeripheralClock / (1 << scale)) / (lo_clk + hi_clk);
622 }
623
MXC_SPI_RevA2_SetFrameSize(mxc_spi_reva_regs_t * spi,int frame_size)624 int MXC_SPI_RevA2_SetFrameSize(mxc_spi_reva_regs_t *spi, int frame_size)
625 {
626 int8_t spi_num;
627 int saved_enable_state;
628
629 // HW has problem with these two character sizes
630 if (frame_size <= 1 || frame_size > 16) {
631 return E_BAD_PARAM;
632 }
633
634 spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
635
636 if ((spi->stat & MXC_F_SPI_REVA_STAT_BUSY) &&
637 (STATES[spi_num].controller_target == MXC_SPI_TYPE_CONTROLLER)) {
638 return E_BAD_STATE;
639 }
640
641 // Set up the character size.
642 saved_enable_state = spi->ctrl0 | MXC_F_SPI_REVA_CTRL0_EN;
643
644 // If enabled, disable SPI before changing character size.
645 if (saved_enable_state) {
646 spi->ctrl0 &= ~(MXC_F_SPI_REVA_CTRL0_EN);
647 }
648
649 // Update data size from save Init function.
650 STATES[spi_num].frame_size = frame_size;
651
652 if (frame_size < 16) {
653 MXC_SETFIELD(spi->ctrl2, MXC_F_SPI_REVA_CTRL2_NUMBITS,
654 frame_size << MXC_F_SPI_REVA_CTRL2_NUMBITS_POS);
655 } else {
656 // Set to 16 bits per character as default.
657 MXC_SETFIELD(spi->ctrl2, MXC_F_SPI_REVA_CTRL2_NUMBITS,
658 0 << MXC_F_SPI_REVA_CTRL2_NUMBITS_POS);
659 }
660
661 // Return back to original SPI enable state.
662 MXC_SETFIELD(spi->ctrl0, MXC_F_SPI_REVA_CTRL0_EN, saved_enable_state);
663
664 return E_NO_ERROR;
665 }
666
MXC_SPI_RevA2_GetFrameSize(mxc_spi_reva_regs_t * spi)667 int MXC_SPI_RevA2_GetFrameSize(mxc_spi_reva_regs_t *spi)
668 {
669 // NUMBITS = 0 means 16-bits per character
670 if (!(spi->ctrl2 & MXC_F_SPI_REVA_CTRL2_NUMBITS)) {
671 return 16;
672 } else {
673 return ((spi->ctrl2 & MXC_F_SPI_REVA_CTRL2_NUMBITS) >> MXC_F_SPI_REVA_CTRL2_NUMBITS_POS);
674 }
675 }
676
MXC_SPI_RevA2_SetInterface(mxc_spi_reva_regs_t * spi,mxc_spi_interface_t if_mode)677 int MXC_SPI_RevA2_SetInterface(mxc_spi_reva_regs_t *spi, mxc_spi_interface_t if_mode)
678 {
679 // Clear before setting
680 spi->ctrl2 &= ~(MXC_F_SPI_REVA_CTRL2_THREE_WIRE | MXC_F_SPI_REVA_CTRL2_DATA_WIDTH);
681
682 switch (if_mode) {
683 case MXC_SPI_INTERFACE_3WIRE:
684 spi->ctrl2 |= MXC_F_SPI_REVA_CTRL2_THREE_WIRE;
685 break;
686
687 case MXC_SPI_INTERFACE_STANDARD:
688 spi->ctrl2 |= MXC_S_SPI_REVA_CTRL2_DATA_WIDTH_MONO;
689 break;
690
691 case MXC_SPI_INTERFACE_DUAL:
692 spi->ctrl2 |= MXC_S_SPI_REVA_CTRL2_DATA_WIDTH_DUAL;
693 break;
694
695 case MXC_SPI_INTERFACE_QUAD:
696 spi->ctrl2 |= MXC_S_SPI_REVA_CTRL2_DATA_WIDTH_QUAD;
697 break;
698
699 // Default set to to 3-Wire
700 default:
701 spi->ctrl2 |= MXC_F_SPI_REVA_CTRL2_THREE_WIRE;
702 break;
703 }
704
705 // Save state of new mode
706 STATES[MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi)].if_mode = if_mode;
707
708 return E_NO_ERROR;
709 }
710
MXC_SPI_RevA2_GetInterface(mxc_spi_reva_regs_t * spi)711 mxc_spi_interface_t MXC_SPI_RevA2_GetInterface(mxc_spi_reva_regs_t *spi)
712 {
713 if (spi->ctrl2 & MXC_F_SPI_REVA_CTRL2_THREE_WIRE) {
714 return MXC_SPI_INTERFACE_3WIRE;
715 }
716
717 if (spi->ctrl2 & MXC_S_SPI_REVA_CTRL2_DATA_WIDTH_DUAL) {
718 return MXC_SPI_INTERFACE_DUAL;
719 }
720
721 if (spi->ctrl2 & MXC_S_SPI_REVA_CTRL2_DATA_WIDTH_QUAD) {
722 return MXC_SPI_INTERFACE_QUAD;
723 }
724
725 return MXC_SPI_INTERFACE_STANDARD;
726 }
727
MXC_SPI_RevA2_SetClkMode(mxc_spi_reva_regs_t * spi,mxc_spi_clkmode_t clk_mode)728 int MXC_SPI_RevA2_SetClkMode(mxc_spi_reva_regs_t *spi, mxc_spi_clkmode_t clk_mode)
729 {
730 switch (clk_mode) {
731 // CPOL: 0 CPHA: 0
732 case MXC_SPI_CLKMODE_0:
733 spi->ctrl2 &= ~MXC_F_SPI_REVA_CTRL2_CLKPHA;
734 spi->ctrl2 &= ~MXC_F_SPI_REVA_CTRL2_CLKPOL;
735 break;
736
737 // CPOL: 0 CPHA: 1
738 case MXC_SPI_CLKMODE_1:
739 spi->ctrl2 &= ~MXC_F_SPI_REVA_CTRL2_CLKPHA;
740 spi->ctrl2 |= MXC_F_SPI_REVA_CTRL2_CLKPOL;
741 break;
742
743 // CPOL: 1 CPHA: 0
744 case MXC_SPI_CLKMODE_2:
745 spi->ctrl2 |= MXC_F_SPI_REVA_CTRL2_CLKPHA;
746 spi->ctrl2 &= ~MXC_F_SPI_REVA_CTRL2_CLKPOL;
747 break;
748
749 // CPOL: 1 CPHA: 1
750 case MXC_SPI_CLKMODE_3:
751 spi->ctrl2 |= MXC_F_SPI_REVA_CTRL2_CLKPHA;
752 spi->ctrl2 |= MXC_F_SPI_REVA_CTRL2_CLKPOL;
753 break;
754
755 // Mode 0 by default.
756 default:
757 spi->ctrl2 &= ~MXC_F_SPI_REVA_CTRL2_CLKPHA;
758 spi->ctrl2 &= ~MXC_F_SPI_REVA_CTRL2_CLKPOL;
759 break;
760 }
761
762 return E_NO_ERROR;
763 }
764
MXC_SPI_RevA2_GetClkMode(mxc_spi_reva_regs_t * spi)765 mxc_spi_clkmode_t MXC_SPI_RevA2_GetClkMode(mxc_spi_reva_regs_t *spi)
766 {
767 if (spi->ctrl2 & MXC_F_SPI_REVA_CTRL2_CLKPHA) {
768 if (spi->ctrl2 & MXC_F_SPI_REVA_CTRL2_CLKPOL) {
769 return MXC_SPI_CLKMODE_3;
770 } else {
771 return MXC_SPI_CLKMODE_2;
772 }
773 } else {
774 if (spi->ctrl2 & MXC_F_SPI_REVA_CTRL2_CLKPOL) {
775 return MXC_SPI_CLKMODE_1;
776 }
777 }
778
779 return MXC_SPI_CLKMODE_0;
780 }
781
MXC_SPI_RevA2_SetCallback(mxc_spi_reva_regs_t * spi,mxc_spi_callback_t callback,void * data)782 int MXC_SPI_RevA2_SetCallback(mxc_spi_reva_regs_t *spi, mxc_spi_callback_t callback, void *data)
783 {
784 int8_t spi_num;
785
786 spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
787
788 STATES[spi_num].callback = callback;
789 STATES[spi_num].callback_data = data;
790
791 return E_NO_ERROR;
792 }
793
MXC_SPI_RevA2_GetActive(mxc_spi_reva_regs_t * spi)794 int MXC_SPI_RevA2_GetActive(mxc_spi_reva_regs_t *spi)
795 {
796 if (spi->stat & MXC_F_SPI_REVA_STAT_BUSY) {
797 return E_BUSY;
798 }
799
800 return E_NO_ERROR;
801 }
802
MXC_SPI_RevA2_ReadyForSleep(mxc_spi_reva_regs_t * spi)803 int MXC_SPI_RevA2_ReadyForSleep(mxc_spi_reva_regs_t *spi)
804 {
805 if (spi->stat & MXC_F_SPI_REVA_STAT_BUSY || (spi->dma & MXC_F_SPI_REVA_DMA_TX_LVL) ||
806 (spi->dma & MXC_F_SPI_REVA_DMA_RX_LVL)) {
807 return E_BUSY;
808 } else {
809 return E_NO_ERROR;
810 }
811 }
812
MXC_SPI_RevA2_SetDummyTX(mxc_spi_reva_regs_t * spi,uint16_t tx_value)813 int MXC_SPI_RevA2_SetDummyTX(mxc_spi_reva_regs_t *spi, uint16_t tx_value)
814 {
815 STATES[MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi)].tx_dummy_value = tx_value;
816
817 return E_NO_ERROR;
818 }
819
MXC_SPI_RevA2_StartTransmission(mxc_spi_reva_regs_t * spi)820 int MXC_SPI_RevA2_StartTransmission(mxc_spi_reva_regs_t *spi)
821 {
822 if (MXC_SPI_GetActive((mxc_spi_regs_t *)spi) == E_BUSY) {
823 return E_BUSY;
824 }
825
826 spi->ctrl0 |= MXC_F_SPI_REVA_CTRL0_START;
827
828 return E_NO_ERROR;
829 }
830
MXC_SPI_RevA2_AbortTransmission(mxc_spi_reva_regs_t * spi)831 int MXC_SPI_RevA2_AbortTransmission(mxc_spi_reva_regs_t *spi)
832 {
833 int8_t spi_num;
834
835 spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
836
837 // Disable interrupts, clear the flags.
838 spi->inten = 0;
839 spi->intfl = spi->intfl;
840
841 // Cancel on-going transaction before enabling.
842 spi->ctrl0 &= ~(MXC_F_SPI_REVA_CTRL0_EN);
843 spi->ctrl0 |= (MXC_F_SPI_REVA_CTRL0_EN);
844
845 // Callback if not NULL
846 if (STATES[spi_num].callback != NULL) {
847 STATES[spi_num].callback(STATES[spi_num].callback_data, E_ABORT);
848 }
849
850 return E_NO_ERROR;
851 }
852
MXC_SPI_RevA2_GetTXFIFOAvailable(mxc_spi_reva_regs_t * spi)853 uint8_t MXC_SPI_RevA2_GetTXFIFOAvailable(mxc_spi_reva_regs_t *spi)
854 {
855 return MXC_SPI_FIFO_DEPTH -
856 ((spi->dma & MXC_F_SPI_REVA_DMA_TX_LVL) >> MXC_F_SPI_REVA_DMA_TX_LVL_POS);
857 }
858
MXC_SPI_RevA2_GetRXFIFOAvailable(mxc_spi_reva_regs_t * spi)859 uint8_t MXC_SPI_RevA2_GetRXFIFOAvailable(mxc_spi_reva_regs_t *spi)
860 {
861 return (spi->dma & MXC_F_SPI_REVA_DMA_RX_LVL) >> MXC_F_SPI_REVA_DMA_RX_LVL_POS;
862 }
863
MXC_SPI_RevA2_ClearTXFIFO(mxc_spi_reva_regs_t * spi)864 int MXC_SPI_RevA2_ClearTXFIFO(mxc_spi_reva_regs_t *spi)
865 {
866 uint32_t save_state;
867
868 save_state = (spi->dma & (MXC_F_SPI_REVA_DMA_TX_FIFO_EN | MXC_F_SPI_REVA_DMA_DMA_TX_EN));
869
870 // Disable FIFOs before clearing as recommended by UG.
871 spi->dma &= ~(MXC_F_SPI_REVA_DMA_TX_FIFO_EN | MXC_F_SPI_REVA_DMA_DMA_TX_EN);
872 spi->dma |= (MXC_F_SPI_REVA_DMA_TX_FLUSH);
873
874 // Revert to previous state.
875 MXC_SETFIELD(spi->dma, (MXC_F_SPI_REVA_DMA_TX_FIFO_EN | MXC_F_SPI_REVA_DMA_DMA_TX_EN),
876 save_state);
877
878 return E_NO_ERROR;
879 }
880
MXC_SPI_RevA2_ClearRXFIFO(mxc_spi_reva_regs_t * spi)881 int MXC_SPI_RevA2_ClearRXFIFO(mxc_spi_reva_regs_t *spi)
882 {
883 uint32_t save_state;
884
885 save_state = (spi->dma & (MXC_F_SPI_REVA_DMA_RX_FIFO_EN | MXC_F_SPI_REVA_DMA_DMA_RX_EN));
886
887 // Disable FIFOs before clearing as recommended by UG.
888 spi->dma &= ~(MXC_F_SPI_REVA_DMA_RX_FIFO_EN | MXC_F_SPI_REVA_DMA_DMA_RX_EN);
889 spi->dma |= (MXC_F_SPI_REVA_DMA_RX_FLUSH);
890
891 // Revert to previous state.
892 MXC_SETFIELD(spi->dma, (MXC_F_SPI_REVA_DMA_RX_FIFO_EN | MXC_F_SPI_REVA_DMA_DMA_RX_EN),
893 save_state);
894
895 return E_NO_ERROR;
896 }
897
MXC_SPI_RevA2_SetTXThreshold(mxc_spi_reva_regs_t * spi,uint8_t thd_val)898 int MXC_SPI_RevA2_SetTXThreshold(mxc_spi_reva_regs_t *spi, uint8_t thd_val)
899 {
900 // Valid values for the threshold are 0x1 to 0x1F
901 if (thd_val > (MXC_SPI_FIFO_DEPTH - 1) || thd_val == 0) {
902 return E_BAD_PARAM;
903 }
904
905 MXC_SETFIELD(spi->dma, MXC_F_SPI_REVA_DMA_TX_THD_VAL,
906 thd_val << MXC_F_SPI_REVA_DMA_TX_THD_VAL_POS);
907
908 return E_NO_ERROR;
909 }
910
MXC_SPI_RevA2_SetRXThreshold(mxc_spi_reva_regs_t * spi,uint8_t thd_val)911 int MXC_SPI_RevA2_SetRXThreshold(mxc_spi_reva_regs_t *spi, uint8_t thd_val)
912 {
913 if (thd_val >= (MXC_SPI_FIFO_DEPTH - 1)) {
914 return E_BAD_PARAM;
915 }
916
917 MXC_SETFIELD(spi->dma, MXC_F_SPI_REVA_DMA_RX_THD_VAL,
918 thd_val << MXC_F_SPI_REVA_DMA_RX_THD_VAL_POS);
919
920 return E_NO_ERROR;
921 }
922
MXC_SPI_RevA2_GetTXThreshold(mxc_spi_reva_regs_t * spi)923 uint8_t MXC_SPI_RevA2_GetTXThreshold(mxc_spi_reva_regs_t *spi)
924 {
925 return (spi->dma & MXC_F_SPI_REVA_DMA_TX_THD_VAL) >> MXC_F_SPI_REVA_DMA_TX_THD_VAL_POS;
926 }
927
MXC_SPI_RevA2_GetRXThreshold(mxc_spi_reva_regs_t * spi)928 uint8_t MXC_SPI_RevA2_GetRXThreshold(mxc_spi_reva_regs_t *spi)
929 {
930 return (spi->dma & MXC_F_SPI_REVA_DMA_RX_THD_VAL) >> MXC_F_SPI_REVA_DMA_RX_THD_VAL_POS;
931 }
932
933 /* ** DMA-Specific Functions ** */
934
935 // Available for switching between DMA and non-DMA transactions
MXC_SPI_RevA2_DMA_Init(mxc_spi_reva_regs_t * spi,mxc_dma_reva_regs_t * dma,bool use_dma_tx,bool use_dma_rx)936 int MXC_SPI_RevA2_DMA_Init(mxc_spi_reva_regs_t *spi, mxc_dma_reva_regs_t *dma, bool use_dma_tx,
937 bool use_dma_rx)
938 {
939 int error;
940 int tx_ch, rx_ch; // For readability.
941 int8_t spi_num;
942
943 spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
944
945 if (dma == NULL) {
946 return E_NULL_PTR;
947 }
948
949 if (STATES[spi_num].dma_initialized) {
950 // Exit function if DMA is already initialized.
951 return E_NO_ERROR;
952 }
953
954 STATES[spi_num].dma = dma;
955
956 #if (MXC_DMA_INSTANCES == 1)
957 error = MXC_DMA_Init();
958 #else
959 error = MXC_DMA_Init(dma);
960 #endif
961 if (error != E_NO_ERROR) {
962 return error;
963 }
964
965 // Set up SPI DMA TX.
966 if (use_dma_tx) {
967 STATES[spi_num].tx_dma_ch = MXC_DMA_AcquireChannel();
968 tx_ch = STATES[spi_num].tx_dma_ch;
969
970 if (STATES[spi_num].tx_dma_ch < 0) {
971 return E_NONE_AVAIL;
972 }
973
974 // TX Channel
975 STATES[spi_num].dma->ch[tx_ch].ctrl |= (MXC_F_DMA_REVA_CTRL_CTZ_IE);
976 STATES[spi_num].dma->inten |= (1 << tx_ch);
977 }
978
979 // Set up SPI DMA RX.
980 if (use_dma_rx) {
981 STATES[spi_num].rx_dma_ch = MXC_DMA_AcquireChannel();
982 rx_ch = STATES[spi_num].rx_dma_ch;
983
984 if (STATES[spi_num].rx_dma_ch < 0) {
985 return E_NONE_AVAIL;
986 }
987
988 // RX Channel
989 STATES[spi_num].dma->ch[rx_ch].ctrl |= (MXC_F_DMA_REVA_CTRL_CTZ_IE);
990 STATES[spi_num].dma->inten |= (1 << rx_ch);
991 }
992
993 error = MXC_SPI_DMA_SetRequestSelect((mxc_spi_regs_t *)spi, use_dma_tx, use_dma_rx);
994 if (error != E_NO_ERROR) {
995 return error;
996 }
997
998 STATES[spi_num].dma_initialized = true;
999
1000 return E_NO_ERROR;
1001 }
1002
1003 // Available to chech whether DMA is already initialized for SPI instance.
1004 // Useful for switching from non-DMA to DMA transactions.
MXC_SPI_RevA2_DMA_GetInitialized(mxc_spi_reva_regs_t * spi)1005 bool MXC_SPI_RevA2_DMA_GetInitialized(mxc_spi_reva_regs_t *spi)
1006 {
1007 return (STATES[MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi)].dma_initialized);
1008 }
1009
MXC_SPI_RevA2_DMA_GetTXChannel(mxc_spi_reva_regs_t * spi)1010 int MXC_SPI_RevA2_DMA_GetTXChannel(mxc_spi_reva_regs_t *spi)
1011 {
1012 return (STATES[MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi)].tx_dma_ch);
1013 }
1014
MXC_SPI_RevA2_DMA_GetRXChannel(mxc_spi_reva_regs_t * spi)1015 int MXC_SPI_RevA2_DMA_GetRXChannel(mxc_spi_reva_regs_t *spi)
1016 {
1017 return (STATES[MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi)].rx_dma_ch);
1018 }
1019
MXC_SPI_RevA2_DMA_SetRequestSelect(mxc_spi_reva_regs_t * spi,uint32_t tx_reqsel,uint32_t rx_reqsel)1020 int MXC_SPI_RevA2_DMA_SetRequestSelect(mxc_spi_reva_regs_t *spi, uint32_t tx_reqsel,
1021 uint32_t rx_reqsel)
1022 {
1023 int8_t spi_num;
1024 uint32_t tx_ch;
1025 uint32_t rx_ch;
1026
1027 spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
1028
1029 // Ensure DMA was configured before setting DMA Request Selects.
1030 if (STATES[spi_num].dma == NULL) {
1031 return E_BAD_STATE;
1032 }
1033
1034 tx_ch = STATES[spi_num].tx_dma_ch;
1035 rx_ch = STATES[spi_num].rx_dma_ch;
1036
1037 // This function will overwrite the current DMA TX/RX Request Selects.
1038 if (tx_reqsel != -1) {
1039 STATES[spi_num].dma->ch[tx_ch].ctrl |= tx_reqsel;
1040 }
1041
1042 if (rx_reqsel != -1) {
1043 STATES[spi_num].dma->ch[rx_ch].ctrl |= rx_reqsel;
1044 }
1045
1046 return E_NO_ERROR;
1047 }
1048
1049 // Swaps the upper and lower byte of 2-byte wide frame transactions.
1050 // HW Bug: For 2-byte wide frame transactions, RX DMA swaps the
1051 // LSB and MSB.
1052 // Example: TX: 0x1234 => RX: 0x3412
1053 // Note: Use __REV assembly instruction for quicker Swap implementation.
MXC_SPI_RevA2_DMA_SwapByte(uint8_t * buffer,uint32_t length_bytes)1054 void MXC_SPI_RevA2_DMA_SwapByte(uint8_t *buffer, uint32_t length_bytes)
1055 {
1056 int i;
1057
1058 MXC_ASSERT(buffer != NULL);
1059
1060 for (i = 0; i < length_bytes; i += 2) {
1061 uint8_t temp = buffer[i];
1062 buffer[i] = buffer[i + 1];
1063 buffer[i + 1] = temp;
1064 }
1065 }
1066
1067 /* ** Transaction Helper Functions ** */
1068
1069 // SPI DMA/non-DMA Transaction Setup Helper Function.
MXC_SPI_RevA2_transactionSetup(mxc_spi_reva_regs_t * spi,uint8_t * tx_buffer,uint32_t tx_length_frames,uint8_t * rx_buffer,uint32_t rx_length_frames,bool use_dma)1070 static void MXC_SPI_RevA2_transactionSetup(mxc_spi_reva_regs_t *spi, uint8_t *tx_buffer,
1071 uint32_t tx_length_frames, uint8_t *rx_buffer,
1072 uint32_t rx_length_frames, bool use_dma)
1073 {
1074 int tx_dummy_length_frames;
1075 int8_t spi_num;
1076 // For readability purposes.
1077 int rx_ch, tx_ch;
1078
1079 // Ensure valid SPI Instance.
1080 spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
1081
1082 // Initialize SPIn state to handle data.
1083 STATES[spi_num].transaction_done = false;
1084
1085 STATES[spi_num].tx_buffer = tx_buffer;
1086 STATES[spi_num].tx_count_bytes = 0;
1087 STATES[spi_num].tx_done = false;
1088
1089 STATES[spi_num].rx_buffer = rx_buffer;
1090 STATES[spi_num].rx_count_bytes = 0;
1091 STATES[spi_num].rx_done = false;
1092
1093 // Max number of frames to transmit/receive.
1094 MXC_ASSERT(tx_length_frames <
1095 (MXC_F_SPI_REVA_CTRL1_TX_NUM_CHAR >> MXC_F_SPI_REVA_CTRL1_TX_NUM_CHAR_POS));
1096 MXC_ASSERT(rx_length_frames <
1097 (MXC_F_SPI_REVA_CTRL1_RX_NUM_CHAR >> MXC_F_SPI_REVA_CTRL1_RX_NUM_CHAR_POS));
1098
1099 // STATES[n] TX/RX Length Fields are in terms of number of bytes to send/receive.
1100 if (STATES[spi_num].frame_size <= 8) {
1101 STATES[spi_num].tx_length_bytes = tx_length_frames;
1102 STATES[spi_num].rx_length_bytes = rx_length_frames;
1103 } else {
1104 STATES[spi_num].tx_length_bytes = tx_length_frames * 2;
1105 STATES[spi_num].rx_length_bytes = rx_length_frames * 2;
1106 }
1107
1108 // Set the number of messages to transmit/receive for the SPI transaction.
1109 if (STATES[spi_num].if_mode == MXC_SPI_INTERFACE_STANDARD) {
1110 if (rx_length_frames > tx_length_frames) {
1111 // In standard 4-wire mode, the RX_NUM_CHAR field of ctrl1 is ignored.
1112 // The number of bytes to transmit AND receive is set by TX_NUM_CHAR,
1113 // because the hardware always assume full duplex. Therefore extra
1114 // dummy bytes must be transmitted to support half duplex.
1115 tx_dummy_length_frames = rx_length_frames - tx_length_frames;
1116
1117 // Check whether new frame length exceeds the possible number of frames to transmit.
1118 MXC_ASSERT((tx_length_frames + tx_dummy_length_frames) <
1119 (MXC_F_SPI_REVA_CTRL1_TX_NUM_CHAR >> MXC_F_SPI_REVA_CTRL1_TX_NUM_CHAR_POS));
1120
1121 spi->ctrl1 = ((tx_length_frames + tx_dummy_length_frames)
1122 << MXC_F_SPI_REVA_CTRL1_TX_NUM_CHAR_POS);
1123 } else {
1124 spi->ctrl1 = (tx_length_frames << MXC_F_SPI_REVA_CTRL1_TX_NUM_CHAR_POS);
1125 }
1126 } else { // mode != MXC_SPI_INTERFACE_STANDARD
1127 spi->ctrl1 = (tx_length_frames << MXC_F_SPI_REVA_CTRL1_TX_NUM_CHAR_POS) |
1128 (rx_length_frames << MXC_F_SPI_REVA_CTRL1_RX_NUM_CHAR_POS);
1129 }
1130
1131 // Disable FIFOs before clearing as recommended by UG.
1132 spi->dma &= ~(MXC_F_SPI_REVA_DMA_TX_FIFO_EN | MXC_F_SPI_REVA_DMA_DMA_TX_EN |
1133 MXC_F_SPI_REVA_DMA_RX_FIFO_EN | MXC_F_SPI_REVA_DMA_DMA_RX_EN);
1134 spi->dma |= (MXC_F_SPI_REVA_DMA_TX_FLUSH | MXC_F_SPI_REVA_DMA_RX_FLUSH);
1135
1136 //>>> Start of SPI DMA transaction setup.
1137 if (use_dma) {
1138 // Enable TX FIFO before configuring.
1139 spi->dma |= (MXC_F_SPI_REVA_DMA_TX_FIFO_EN);
1140
1141 // Set TX and RX Thresholds before loading FIFO.
1142 MXC_SETFIELD(spi->dma, MXC_F_SPI_REVA_DMA_TX_THD_VAL,
1143 ((MXC_SPI_FIFO_DEPTH - 1) << MXC_F_SPI_REVA_DMA_TX_THD_VAL_POS));
1144 MXC_SETFIELD(spi->dma, MXC_F_SPI_REVA_DMA_RX_THD_VAL,
1145 (0 << MXC_F_SPI_REVA_DMA_RX_THD_VAL_POS));
1146
1147 // Set up DMA TX Transactions.
1148 // Note: Number of transmitting frames greatly depends on the SPI DMA register settings for
1149 // the DMA burst size and TX Threshold values.
1150 // 1) For TX transmissions.
1151 if (tx_length_frames > 1) {
1152 // For readability purposes.
1153 tx_ch = STATES[spi_num].tx_dma_ch;
1154
1155 // Configure DMA TX depending on frame width.
1156 // 2-8 bit wide frames.
1157 if (STATES[spi_num].frame_size <= 8) {
1158 // Hardware requires writing the first byte into the FIFO manually.
1159 spi->fifo8[0] = tx_buffer[0];
1160
1161 // Threshold set to 2 frames (2 bytes) after pre-loading first byte for DMA.
1162 // This is the minimum threshold to handle any number of transmitting frames.
1163 // Note: This case is handling TX transactions of greater than 1 frame.
1164 // Threshold of 1 frame does not work.
1165 MXC_SETFIELD(spi->dma, MXC_F_SPI_REVA_DMA_TX_THD_VAL,
1166 (2 << MXC_F_SPI_REVA_DMA_TX_THD_VAL_POS));
1167
1168 STATES[spi_num].dma->ch[tx_ch].src = (uint32_t)(tx_buffer + 1); // 1 Byte offset
1169 STATES[spi_num].dma->ch[tx_ch].cnt = (tx_length_frames - 1);
1170
1171 // Set to 3 bytes (3 frames) burst size.
1172 // Due to design: burst_size = threshold + 1
1173 // Note: Assigning value of 2 to register-field equals 3 bytes transferred in/out of DMA.
1174 // Add 1 to the register-field setting to get the number of bytes for burst.
1175 MXC_SETFIELD(STATES[spi_num].dma->ch[tx_ch].ctrl, MXC_F_DMA_REVA_CTRL_BURST_SIZE,
1176 (2 << MXC_F_DMA_REVA_CTRL_BURST_SIZE_POS));
1177
1178 // Set source and destination width to one byte.
1179 MXC_SETFIELD(STATES[spi_num].dma->ch[tx_ch].ctrl, MXC_F_DMA_REVA_CTRL_SRCWD,
1180 MXC_S_DMA_REVA_CTRL_SRCWD_BYTE);
1181 MXC_SETFIELD(STATES[spi_num].dma->ch[tx_ch].ctrl, MXC_F_DMA_REVA_CTRL_DSTWD,
1182 MXC_S_DMA_REVA_CTRL_DSTWD_BYTE);
1183
1184 // 9-16 bit wide frames.
1185 } else {
1186 // Hardware requires writing the first bytes into the FIFO manually.
1187 STATES[spi_num].tx_count_bytes +=
1188 MXC_SPI_RevA2_writeTXFIFO16(spi, (uint8_t *)(STATES[spi_num].tx_buffer), 2);
1189
1190 // Threshold set to 3 frames (6 bytes) after pre-loading FIFO for DMA.
1191 // This is the minimum threshold to handle any number of transmitting frames.
1192 // Note: This case is handling TX transactions of greater than 1 frame.
1193 // Threshold of 1 or 2 frames does not work.
1194 MXC_SETFIELD(spi->dma, MXC_F_SPI_REVA_DMA_TX_THD_VAL,
1195 (3 << MXC_F_SPI_REVA_DMA_TX_THD_VAL_POS));
1196
1197 STATES[spi_num].dma->ch[tx_ch].src =
1198 (uint32_t)(tx_buffer + STATES[spi_num].tx_count_bytes);
1199 STATES[spi_num].dma->ch[tx_ch].cnt =
1200 (STATES[spi_num].tx_length_bytes - STATES[spi_num].tx_count_bytes);
1201
1202 // Set to 4 bytes (2 frames) burst size.
1203 // Due to design: burst_size = threshold + 1
1204 // Note: Assigning value of 3 to register-field equals 4 bytes.
1205 // Add 1 to the register-field setting to get the number of bytes for burst.
1206 MXC_SETFIELD(STATES[spi_num].dma->ch[tx_ch].ctrl, MXC_F_DMA_REVA_CTRL_BURST_SIZE,
1207 (3 << MXC_F_DMA_REVA_CTRL_BURST_SIZE_POS));
1208
1209 // Set source and destination width to two bytes.
1210 MXC_SETFIELD(STATES[spi_num].dma->ch[tx_ch].ctrl, MXC_F_DMA_REVA_CTRL_SRCWD,
1211 MXC_S_DMA_REVA_CTRL_SRCWD_HALFWORD);
1212 MXC_SETFIELD(STATES[spi_num].dma->ch[tx_ch].ctrl, MXC_F_DMA_REVA_CTRL_DSTWD,
1213 MXC_S_DMA_REVA_CTRL_DSTWD_HALFWORD);
1214 }
1215
1216 STATES[spi_num].dma->ch[tx_ch].ctrl |= MXC_F_DMA_REVA_CTRL_SRCINC;
1217 STATES[spi_num].dma->ch[tx_ch].ctrl |= MXC_F_DMA_REVA_CTRL_EN; // Start the DMA
1218
1219 // 2) For single character transmissions.
1220 // NOTE: Single-length transmissions does not trigger CTZ.
1221 } else if (tx_length_frames == 1) {
1222 // Write first frame into FIFO.
1223 if (STATES[spi_num].frame_size <= 8) {
1224 spi->fifo8[0] = tx_buffer[0];
1225 } else {
1226 MXC_SPI_RevA2_writeTXFIFO16(spi, (uint8_t *)(STATES[spi_num].tx_buffer), 2);
1227 }
1228
1229 // If there is no RX DMA and only one frame is transmitted, then
1230 // the transaction is done. Single-length transmissions
1231 // does not trigger a CTZ interrupt.
1232 if (rx_length_frames > 0 && rx_buffer != NULL) {
1233 STATES[spi_num].transaction_done = true;
1234 }
1235
1236 STATES[spi_num].tx_done = true;
1237
1238 // 3) Set up DMA TX for RX only transactions.
1239 // Note: Even if you are not transmitting anything in standard 4-wire mode,
1240 // the hardware always assume full duplex. Therefore dummy bytes
1241 // must be transmitted to support half duplex. The number of bytes to transmit
1242 // AND receive is set by TX_NUM_CHAR, and the RX_NUM_CHAR field of ctrl1 is ignored.
1243 } else if (tx_length_frames == 0 && STATES[spi_num].if_mode == MXC_SPI_INTERFACE_STANDARD) {
1244 // For readability purposes.
1245 tx_ch = STATES[spi_num].tx_dma_ch;
1246
1247 // Configure TX DMA channel to retransmit the dummy byte.
1248 STATES[spi_num].dma->ch[tx_ch].src = (uint32_t)(&(STATES[spi_num].tx_dummy_value));
1249 STATES[spi_num].dma->ch[tx_ch].cnt = STATES[spi_num].rx_length_bytes; // Only receiving
1250 STATES[spi_num].dma->ch[tx_ch].ctrl &= ~MXC_F_DMA_REVA_CTRL_SRCINC;
1251 STATES[spi_num].dma->ch[tx_ch].ctrl |= MXC_F_DMA_REVA_CTRL_EN; // Start the DMA
1252 }
1253
1254 // Enable SPI TX DMA after configuring.
1255 spi->dma |= (MXC_F_SPI_REVA_DMA_DMA_TX_EN);
1256
1257 // Set up DMA RX Transactions.
1258 if (rx_length_frames > 0 && rx_buffer != NULL) {
1259 // For readability purposes.
1260 rx_ch = STATES[spi_num].rx_dma_ch;
1261
1262 // Enable RX DMA channel before configuring.
1263 spi->dma |= (MXC_F_SPI_REVA_DMA_RX_FIFO_EN);
1264
1265 // Set RX threshold to minimum value to handle any number of received frames.
1266 MXC_SETFIELD(spi->dma, MXC_F_SPI_REVA_DMA_RX_THD_VAL,
1267 (0 << MXC_F_SPI_REVA_DMA_RX_THD_VAL_POS));
1268
1269 STATES[spi_num].dma->ch[rx_ch].dst = (uint32_t)rx_buffer;
1270 STATES[spi_num].dma->ch[rx_ch].cnt = STATES[spi_num].rx_length_bytes;
1271
1272 // Set to one byte burst size - minimum value to handle any number of recevied frames.
1273 MXC_SETFIELD(STATES[spi_num].dma->ch[rx_ch].ctrl, MXC_F_DMA_REVA_CTRL_BURST_SIZE,
1274 (0 << MXC_F_DMA_REVA_CTRL_BURST_SIZE_POS));
1275
1276 // Match frame size (in terms of bytes) in DMA ctrl settings.
1277 if (STATES[spi_num].frame_size <= 8) {
1278 // Set source and destination width to one byte
1279 MXC_SETFIELD(STATES[spi_num].dma->ch[rx_ch].ctrl, MXC_F_DMA_REVA_CTRL_SRCWD,
1280 MXC_S_DMA_REVA_CTRL_SRCWD_BYTE);
1281 MXC_SETFIELD(STATES[spi_num].dma->ch[rx_ch].ctrl, MXC_F_DMA_REVA_CTRL_DSTWD,
1282 MXC_S_DMA_REVA_CTRL_DSTWD_BYTE);
1283 } else {
1284 // Set source destination width to 2 bytes
1285 MXC_SETFIELD(STATES[spi_num].dma->ch[rx_ch].ctrl, MXC_F_DMA_REVA_CTRL_SRCWD,
1286 MXC_S_DMA_REVA_CTRL_SRCWD_HALFWORD);
1287 MXC_SETFIELD(STATES[spi_num].dma->ch[rx_ch].ctrl, MXC_F_DMA_REVA_CTRL_DSTWD,
1288 MXC_S_DMA_REVA_CTRL_DSTWD_HALFWORD);
1289 }
1290
1291 STATES[spi_num].dma->ch[rx_ch].ctrl |= MXC_F_DMA_REVA_CTRL_DSTINC;
1292 STATES[spi_num].dma->ch[rx_ch].ctrl |= MXC_F_DMA_REVA_CTRL_EN; // Start the DMA
1293
1294 // Enable SPI RX DMA after configuring.
1295 spi->dma |= (MXC_F_SPI_REVA_DMA_DMA_RX_EN);
1296 }
1297 //<<< End of SPI DMA transaction setup.
1298 //>>> Start of SPI non-DMA transaction setup.
1299 } else {
1300 // Finish setting up SPI for TX and RX.
1301 if (tx_length_frames > 0) {
1302 // Enable TX FIFO & TX Threshold crossed interrupt.
1303 spi->dma |= (MXC_F_SPI_REVA_DMA_TX_FIFO_EN);
1304 spi->inten |= MXC_F_SPI_REVA_INTEN_TX_THD;
1305
1306 // Set TX Threshold to minimum value after re-enabling TX FIFO.
1307 MXC_SETFIELD(spi->dma, MXC_F_SPI_REVA_DMA_TX_THD_VAL,
1308 (1 << MXC_F_SPI_REVA_DMA_TX_THD_VAL_POS));
1309 }
1310
1311 if (rx_length_frames > 0) {
1312 // Enable RX FIFO & RX Threshold crossed interrupt.
1313 spi->dma |= (MXC_F_SPI_REVA_DMA_RX_FIFO_EN);
1314 spi->inten |= MXC_F_SPI_REVA_INTEN_RX_THD;
1315
1316 // Set RX Threshold to minimum value after re-enabling RX FIFO.
1317 MXC_SETFIELD(spi->dma, MXC_F_SPI_REVA_DMA_RX_THD_VAL,
1318 (0 << MXC_F_SPI_REVA_DMA_RX_THD_VAL_POS));
1319 }
1320
1321 // This private function, MXC_SPI_RevA2_process, call fills the TX FIFO as much as possible
1322 // before launching the transaction. Subsequent FIFO management will be handled after
1323 // transaction has started.
1324 MXC_SPI_RevA2_process(spi);
1325 } //<<< End of SPI non-DMA transaction setup.
1326 }
1327
1328 // Helper function that handles the Target Select assertion/deassertion at start of transaction.
1329 // hw_ts_active_pol is either 1 or 0.
MXC_SPI_RevA2_handleTSControl(mxc_spi_reva_regs_t * spi,uint8_t deassert,uint8_t hw_ts_index)1330 static void MXC_SPI_RevA2_handleTSControl(mxc_spi_reva_regs_t *spi, uint8_t deassert,
1331 uint8_t hw_ts_index)
1332 {
1333 int8_t spi_num;
1334
1335 // Ensure valid SPI Instance.
1336 spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
1337
1338 // Handle target-select (L. SS) deassertion if HW is selected as Target Select (TS) Control Scheme. This must be done
1339 // AFTER launching the transaction to avoid a glitch on the TS line if:
1340 // - The TS line is asserted
1341 // - We want to deassert the line as part of this transaction
1342 //
1343 // As soon as the SPI hardware receives CTRL0->START it seems to reinitialize the Target Select (TS) pin based
1344 // on the value of CTRL->SS_CTRL, which causes the glitch.
1345 if (STATES[spi_num].ts_control == MXC_SPI_TSCONTROL_HW_AUTO) {
1346 // In HW Auto Scheme, only use the target index member.
1347 // Limitation: This implemention only support transactions with one target at a time.
1348 MXC_SETFIELD(spi->ctrl0, MXC_F_SPI_REVA_CTRL0_SS_ACTIVE,
1349 ((1 << hw_ts_index) << MXC_F_SPI_REVA_CTRL0_SS_ACTIVE_POS));
1350
1351 if (deassert) {
1352 spi->ctrl0 &= ~MXC_F_SPI_REVA_CTRL0_SS_CTRL;
1353 } else {
1354 spi->ctrl0 |= MXC_F_SPI_REVA_CTRL0_SS_CTRL;
1355 }
1356 }
1357
1358 // Add support for SW_DRV TS Control here in the future.
1359 }
1360
1361 /* ** Transaction Functions ** */
1362
MXC_SPI_RevA2_ControllerTransaction(mxc_spi_reva_regs_t * spi,uint8_t * tx_buffer,uint32_t tx_length_frames,uint8_t * rx_buffer,uint32_t rx_length_frames,uint8_t deassert,uint8_t hw_ts_index)1363 int MXC_SPI_RevA2_ControllerTransaction(mxc_spi_reva_regs_t *spi, uint8_t *tx_buffer,
1364 uint32_t tx_length_frames, uint8_t *rx_buffer,
1365 uint32_t rx_length_frames, uint8_t deassert,
1366 uint8_t hw_ts_index)
1367 {
1368 int8_t spi_num;
1369
1370 spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
1371
1372 // Make sure DMA is not initialized.
1373 if (STATES[spi_num].dma_initialized == true) {
1374 return E_BAD_STATE;
1375 }
1376
1377 // Make sure SPI Instance is in Controller mode (L. Master).
1378 if (STATES[spi_num].controller_target != MXC_SPI_TYPE_CONTROLLER) {
1379 return E_BAD_STATE;
1380 }
1381
1382 // Save target settings.
1383 STATES[spi_num].deassert = deassert;
1384
1385 // Setup SPI registers for non-DMA transaction.
1386 MXC_SPI_RevA2_transactionSetup(spi, tx_buffer, tx_length_frames, rx_buffer, rx_length_frames,
1387 false);
1388
1389 // Start the SPI transaction.
1390 spi->ctrl0 |= MXC_F_SPI_REVA_CTRL0_START;
1391
1392 // Handle Target Select Pin (Only applicable in HW_AUTO TS control scheme).
1393 MXC_SPI_RevA2_handleTSControl(spi, deassert, hw_ts_index);
1394
1395 // Complete transaction once it started.
1396 while (STATES[spi_num].transaction_done == false) {
1397 if (STATES[spi_num].tx_done == true && STATES[spi_num].rx_done == true) {
1398 if (!(spi->stat & MXC_F_SPI_REVA_STAT_BUSY)) {
1399 STATES[spi_num].transaction_done = true;
1400 }
1401 }
1402
1403 MXC_SPI_RevA2_process(spi);
1404 }
1405
1406 return E_SUCCESS;
1407 }
1408
MXC_SPI_RevA2_ControllerTransactionAsync(mxc_spi_reva_regs_t * spi,uint8_t * tx_buffer,uint32_t tx_length_frames,uint8_t * rx_buffer,uint32_t rx_length_frames,uint8_t deassert,uint8_t hw_ts_index)1409 int MXC_SPI_RevA2_ControllerTransactionAsync(mxc_spi_reva_regs_t *spi, uint8_t *tx_buffer,
1410 uint32_t tx_length_frames, uint8_t *rx_buffer,
1411 uint32_t rx_length_frames, uint8_t deassert,
1412 uint8_t hw_ts_index)
1413 {
1414 int8_t spi_num;
1415
1416 spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
1417
1418 // Make sure DMA is not initialized.
1419 if (STATES[spi_num].dma_initialized == true) {
1420 return E_BAD_STATE;
1421 }
1422
1423 // Make sure SPI Instance is in Controller mode (L. Master).
1424 if (STATES[spi_num].controller_target != MXC_SPI_TYPE_CONTROLLER) {
1425 return E_BAD_STATE;
1426 }
1427
1428 // Save target settings.
1429 STATES[spi_num].deassert = deassert;
1430
1431 // Setup SPI registers for non-DMA transaction.
1432 MXC_SPI_RevA2_transactionSetup(spi, tx_buffer, tx_length_frames, rx_buffer, rx_length_frames,
1433 false);
1434
1435 // Enable Controller Done Interrupt.
1436 spi->inten |= MXC_F_SPI_REVA_INTEN_MST_DONE;
1437
1438 // Start the SPI transaction.
1439 spi->ctrl0 |= MXC_F_SPI_REVA_CTRL0_START;
1440
1441 // Handle Target Select Pin (Only applicable in HW_AUTO TS control scheme).
1442 MXC_SPI_RevA2_handleTSControl(spi, deassert, hw_ts_index);
1443
1444 return E_SUCCESS;
1445 }
1446
MXC_SPI_RevA2_ControllerTransactionDMA(mxc_spi_reva_regs_t * spi,uint8_t * tx_buffer,uint32_t tx_length_frames,uint8_t * rx_buffer,uint32_t rx_length_frames,uint8_t deassert,uint8_t hw_ts_index,mxc_dma_reva_regs_t * dma)1447 int MXC_SPI_RevA2_ControllerTransactionDMA(mxc_spi_reva_regs_t *spi, uint8_t *tx_buffer,
1448 uint32_t tx_length_frames, uint8_t *rx_buffer,
1449 uint32_t rx_length_frames, uint8_t deassert,
1450 uint8_t hw_ts_index, mxc_dma_reva_regs_t *dma)
1451 {
1452 int8_t spi_num;
1453 int error;
1454
1455 spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
1456
1457 // More overhead, but this function will initialize DMA if it wasn't done earlier.
1458 if (STATES[spi_num].dma_initialized == false) {
1459 error = MXC_SPI_RevA2_DMA_Init(spi, dma, true, true);
1460 if (error != E_NO_ERROR) {
1461 return error;
1462 }
1463 }
1464
1465 // Make sure SPI Instance is in Controller mode (L. Master).
1466 if (STATES[spi_num].controller_target != MXC_SPI_TYPE_CONTROLLER) {
1467 return E_BAD_STATE;
1468 }
1469
1470 // Save target settings.
1471 STATES[spi_num].deassert = deassert;
1472
1473 // Setup SPI registers for non-DMA transaction.
1474 MXC_SPI_RevA2_transactionSetup(spi, tx_buffer, tx_length_frames, rx_buffer, rx_length_frames,
1475 true);
1476
1477 // Start the SPI transaction.
1478 spi->ctrl0 |= MXC_F_SPI_REVA_CTRL0_START;
1479
1480 // Handle Target Select Pin (Only applicable in HW_AUTO TS control scheme).
1481 MXC_SPI_RevA2_handleTSControl(spi, deassert, hw_ts_index);
1482
1483 return E_SUCCESS;
1484 }
1485
MXC_SPI_RevA2_TargetTransaction(mxc_spi_reva_regs_t * spi,uint8_t * tx_buffer,uint32_t tx_length_frames,uint8_t * rx_buffer,uint32_t rx_length_frames)1486 int MXC_SPI_RevA2_TargetTransaction(mxc_spi_reva_regs_t *spi, uint8_t *tx_buffer,
1487 uint32_t tx_length_frames, uint8_t *rx_buffer,
1488 uint32_t rx_length_frames)
1489 {
1490 int8_t spi_num;
1491
1492 // Ensure valid SPI Instance.
1493 spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
1494
1495 // Make sure DMA is not initialized.
1496 if (STATES[spi_num].dma_initialized == true) {
1497 return E_BAD_STATE;
1498 }
1499
1500 // Make sure SPI Instance is in Target mode (L. Slave).
1501 if (STATES[spi_num].controller_target != MXC_SPI_TYPE_TARGET) {
1502 return E_BAD_STATE;
1503 }
1504
1505 // Setup SPI registers for non-DMA transaction.
1506 MXC_SPI_RevA2_transactionSetup(spi, tx_buffer, tx_length_frames, rx_buffer, rx_length_frames,
1507 false);
1508
1509 // Wait for Target Select pin to be asserted before starting transaction.
1510 while ((spi->stat & MXC_F_SPI_REVA_STAT_BUSY) == 0) {}
1511
1512 // Complete transaction once started.
1513 while (STATES[spi_num].transaction_done == false) {
1514 if (STATES[spi_num].tx_count_bytes == STATES[spi_num].tx_length_bytes &&
1515 STATES[spi_num].rx_count_bytes == STATES[spi_num].rx_length_bytes) {
1516 STATES[spi_num].transaction_done = true;
1517 }
1518
1519 MXC_SPI_RevA2_process(spi);
1520 }
1521
1522 // Wait until transaction is complete.
1523 while (spi->stat & MXC_F_SPI_REVA_STAT_BUSY) {}
1524
1525 return E_SUCCESS;
1526 }
1527
MXC_SPI_RevA2_TargetTransactionAsync(mxc_spi_reva_regs_t * spi,uint8_t * tx_buffer,uint32_t tx_length_frames,uint8_t * rx_buffer,uint32_t rx_length_frames)1528 int MXC_SPI_RevA2_TargetTransactionAsync(mxc_spi_reva_regs_t *spi, uint8_t *tx_buffer,
1529 uint32_t tx_length_frames, uint8_t *rx_buffer,
1530 uint32_t rx_length_frames)
1531 {
1532 int8_t spi_num;
1533
1534 // Ensure valid SPI Instance.
1535 spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
1536
1537 // Make sure DMA is not initialized.
1538 if (STATES[spi_num].dma_initialized == true) {
1539 return E_BAD_STATE;
1540 }
1541
1542 // Make sure SPI Instance is in Target mode (L. Slave).
1543 if (STATES[spi_num].controller_target != MXC_SPI_TYPE_TARGET) {
1544 return E_BAD_STATE;
1545 }
1546
1547 // Setup SPI registers for non-DMA transaction.
1548 MXC_SPI_RevA2_transactionSetup(spi, tx_buffer, tx_length_frames, rx_buffer, rx_length_frames,
1549 false);
1550
1551 return E_SUCCESS;
1552 }
1553
MXC_SPI_RevA2_TargetTransactionDMA(mxc_spi_reva_regs_t * spi,uint8_t * tx_buffer,uint32_t tx_length_frames,uint8_t * rx_buffer,uint32_t rx_length_frames,mxc_dma_reva_regs_t * dma)1554 int MXC_SPI_RevA2_TargetTransactionDMA(mxc_spi_reva_regs_t *spi, uint8_t *tx_buffer,
1555 uint32_t tx_length_frames, uint8_t *rx_buffer,
1556 uint32_t rx_length_frames, mxc_dma_reva_regs_t *dma)
1557 {
1558 int8_t spi_num;
1559 int error;
1560
1561 spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
1562
1563 // More overhead, but this function will initialize DMA if it wasn't done earlier.
1564 if (STATES[spi_num].dma_initialized == false) {
1565 error = MXC_SPI_RevA2_DMA_Init(spi, dma, true, true);
1566 if (error != E_NO_ERROR) {
1567 return error;
1568 }
1569 }
1570
1571 // Make sure SPI Instance is in Target mode (L. Slave).
1572 if (STATES[spi_num].controller_target != MXC_SPI_TYPE_TARGET) {
1573 return E_BAD_STATE;
1574 }
1575
1576 // Setup SPI registers for DMA transaction.
1577 MXC_SPI_RevA2_transactionSetup(spi, tx_buffer, tx_length_frames, rx_buffer, rx_length_frames,
1578 true);
1579
1580 // Target transaction is ready.
1581 return E_SUCCESS;
1582 }
1583
1584 /* ** Handler Functions ** */
1585
MXC_SPI_RevA2_Handler(mxc_spi_reva_regs_t * spi)1586 void MXC_SPI_RevA2_Handler(mxc_spi_reva_regs_t *spi)
1587 {
1588 int8_t spi_num;
1589 uint32_t status = spi->intfl;
1590
1591 spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
1592
1593 // Master done (TX complete)
1594 if (status & MXC_F_SPI_REVA_INTFL_MST_DONE) {
1595 spi->intfl |= MXC_F_SPI_REVA_INTFL_MST_DONE; // Clear flag
1596
1597 // Callback if valid.
1598 // Note: If Target Select (TS) Control Scheme is set in SW_App mode, then the caller needs to ensure the
1599 // Target Select (TS) pin is asserted or deasserted in their application.
1600 if (STATES[spi_num].callback) {
1601 STATES[spi_num].callback(STATES[spi_num].callback_data, E_NO_ERROR);
1602 }
1603
1604 // Controller is done after callback (if valid) is handled.
1605 STATES[spi_num].transaction_done = true;
1606 }
1607
1608 // Handle RX Threshold
1609 if (status & MXC_F_SPI_REVA_INTFL_RX_THD) {
1610 spi->intfl |= MXC_F_SPI_REVA_INTFL_RX_THD;
1611
1612 // RX threshold has been crossed, there's data to unload from the FIFO
1613 MXC_SPI_RevA2_process(spi);
1614 }
1615
1616 // Handle TX Threshold
1617 if (status & MXC_F_SPI_REVA_INTFL_TX_THD) {
1618 spi->intfl |= MXC_F_SPI_REVA_INTFL_TX_THD;
1619
1620 // TX threshold has been crossed, we need to refill the FIFO
1621 MXC_SPI_RevA2_process(spi);
1622 }
1623 }
1624
MXC_SPI_RevA2_DMA_TX_Handler(mxc_spi_reva_regs_t * spi)1625 void MXC_SPI_RevA2_DMA_TX_Handler(mxc_spi_reva_regs_t *spi)
1626 {
1627 int8_t spi_num;
1628 uint32_t tx_ch;
1629 uint32_t status;
1630
1631 spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
1632
1633 tx_ch = STATES[spi_num].tx_dma_ch;
1634 status = STATES[spi_num].dma->ch[tx_ch].status;
1635
1636 // Count-to-Zero (DMA TX complete)
1637 if (status & MXC_F_DMA_REVA_STATUS_CTZ_IF) {
1638 STATES[spi_num].tx_done = true;
1639 STATES[spi_num].dma->ch[tx_ch].status |= MXC_F_DMA_REVA_STATUS_CTZ_IF;
1640
1641 // For completeness-sake.
1642 STATES[spi_num].tx_count_bytes = STATES[spi_num].tx_length_bytes;
1643
1644 // Callback if valid and if you're only transmitting.
1645 // Note: If Target Select (TS) Control Scheme is set in SW_App mode, then the caller needs to ensure the
1646 // Target Select (TS) pin is asserted or deasserted in their application.
1647 if (STATES[spi_num].rx_buffer == NULL) {
1648 if (STATES[spi_num].callback) {
1649 STATES[spi_num].callback(STATES[spi_num].callback_data, E_NO_ERROR);
1650 }
1651 }
1652
1653 // TX Transaction is done if there's no RX transaction.
1654 if (STATES[spi_num].rx_length_bytes == 0 || STATES[spi_num].tx_buffer == NULL) {
1655 STATES[spi_num].transaction_done = true;
1656 }
1657 }
1658
1659 // Bus Error
1660 if (status & MXC_F_DMA_REVA_STATUS_BUS_ERR) {
1661 STATES[spi_num].dma->ch[tx_ch].status |= MXC_F_DMA_REVA_STATUS_BUS_ERR;
1662 }
1663 }
1664
MXC_SPI_RevA2_DMA_RX_Handler(mxc_spi_reva_regs_t * spi)1665 void MXC_SPI_RevA2_DMA_RX_Handler(mxc_spi_reva_regs_t *spi)
1666 {
1667 int8_t spi_num;
1668 uint32_t rx_ch;
1669 uint32_t status;
1670
1671 spi_num = MXC_SPI_GET_IDX((mxc_spi_regs_t *)spi);
1672
1673 rx_ch = STATES[spi_num].rx_dma_ch;
1674 status = STATES[spi_num].dma->ch[rx_ch].status;
1675
1676 // Count-to-Zero (DMA RX complete).
1677 if (status & MXC_F_DMA_REVA_STATUS_CTZ_IF) {
1678 // HW Bug: For 2-byte wide frame transactions, RX DMA swaps the
1679 // LSB and MSB.
1680 // Example: TX: 0x1234 => RX: 0x3412
1681 if (STATES[spi_num].frame_size > 8) {
1682 MXC_SPI_RevA2_DMA_SwapByte(STATES[spi_num].rx_buffer, STATES[spi_num].rx_length_bytes);
1683 }
1684
1685 STATES[spi_num].rx_done = 1;
1686 STATES[spi_num].dma->ch[rx_ch].status |= MXC_F_DMA_STATUS_CTZ_IF;
1687
1688 // For completeness-sake.
1689 STATES[spi_num].rx_count_bytes = STATES[spi_num].rx_length_bytes;
1690
1691 // Callback if valid.
1692 // Note: If Target Select (TS) Control Scheme is set in SW_App mode, then the caller needs to ensure the
1693 // Target Select (TS) pin is asserted or deasserted in their application.
1694 if (STATES[spi_num].callback) {
1695 STATES[spi_num].callback(STATES[spi_num].callback_data, E_NO_ERROR);
1696 }
1697
1698 // RX transaction determines the controller is done if TX transaction is also present.
1699 if (STATES[spi_num].tx_length_bytes > 0 && STATES[spi_num].tx_buffer != NULL) {
1700 STATES[spi_num].transaction_done = true;
1701 }
1702 }
1703
1704 // Bus Error
1705 if (status & MXC_F_DMA_REVA_STATUS_BUS_ERR) {
1706 STATES[spi_num].dma->ch[rx_ch].status |= MXC_F_DMA_STATUS_BUS_ERR;
1707 }
1708 }
1709