1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_flexio_spi.h"
10 
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 
15 /*! @brief FLEXIO SPI transfer state, which is used for SPI transactiaonl APIs' internal state. */
16 enum _flexio_spi_transfer_states
17 {
18     kFLEXIO_SPI_Idle = 0x0U, /*!< Nothing in the transmitter/receiver's queue. */
19     kFLEXIO_SPI_Busy,        /*!< Transmiter/Receive's queue is not finished. */
20 };
21 
22 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
23 extern const clock_ip_name_t s_flexioClocks[];
24 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
25 
26 extern FLEXIO_Type *const s_flexioBases[];
27 
28 /*******************************************************************************
29  * Prototypes
30  ******************************************************************************/
31 
32 extern uint32_t FLEXIO_GetInstance(FLEXIO_Type *base);
33 
34 /*!
35  * @brief Send a piece of data for SPI.
36  *
37  * This function computes the number of data to be written into D register or Tx FIFO,
38  * and write the data into it. At the same time, this function updates the values in
39  * master handle structure.
40  *
41  * @param base pointer to FLEXIO_SPI_Type structure
42  * @param handle Pointer to SPI master handle structure.
43  */
44 static void FLEXIO_SPI_TransferSendTransaction(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle);
45 
46 /*!
47  * @brief Receive a piece of data for SPI master.
48  *
49  * This function computes the number of data to receive from D register or Rx FIFO,
50  * and write the data to destination address. At the same time, this function updates
51  * the values in master handle structure.
52  *
53  * @param base pointer to FLEXIO_SPI_Type structure
54  * @param handle Pointer to SPI master handle structure.
55  */
56 static void FLEXIO_SPI_TransferReceiveTransaction(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle);
57 
58 /*******************************************************************************
59  * Variables
60  ******************************************************************************/
61 
62 /*******************************************************************************
63  * Codes
64  ******************************************************************************/
65 
FLEXIO_SPI_GetInstance(FLEXIO_SPI_Type * base)66 uint32_t FLEXIO_SPI_GetInstance(FLEXIO_SPI_Type *base)
67 {
68     return FLEXIO_GetInstance(base->flexioBase);
69 }
70 
FLEXIO_SPI_TransferSendTransaction(FLEXIO_SPI_Type * base,flexio_spi_master_handle_t * handle)71 static void FLEXIO_SPI_TransferSendTransaction(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle)
72 {
73     uint16_t tmpData = FLEXIO_SPI_DUMMYDATA;
74 
75     if (handle->txData != NULL)
76     {
77         /* Transmit data and update tx size/buff. */
78         if (handle->bytePerFrame == 1U)
79         {
80             tmpData = *(handle->txData);
81             handle->txData++;
82         }
83         else
84         {
85             if (handle->direction == kFLEXIO_SPI_MsbFirst)
86             {
87                 tmpData = (uint32_t)(handle->txData[0]) << 8U;
88                 tmpData += handle->txData[1];
89             }
90             else
91             {
92                 tmpData = (uint32_t)(handle->txData[1]) << 8U;
93                 tmpData += handle->txData[0];
94             }
95             handle->txData += 2U;
96         }
97     }
98     else
99     {
100         tmpData = FLEXIO_SPI_DUMMYDATA;
101     }
102 
103     handle->txRemainingBytes -= handle->bytePerFrame;
104 
105     FLEXIO_SPI_WriteData(base, handle->direction, tmpData);
106 
107     if (!handle->txRemainingBytes)
108     {
109         FLEXIO_SPI_DisableInterrupts(base, kFLEXIO_SPI_TxEmptyInterruptEnable);
110     }
111 }
112 
FLEXIO_SPI_TransferReceiveTransaction(FLEXIO_SPI_Type * base,flexio_spi_master_handle_t * handle)113 static void FLEXIO_SPI_TransferReceiveTransaction(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle)
114 {
115     uint16_t tmpData;
116 
117     tmpData = FLEXIO_SPI_ReadData(base, handle->direction);
118 
119     if (handle->rxData != NULL)
120     {
121         if (handle->bytePerFrame == 1U)
122         {
123             *handle->rxData = tmpData;
124             handle->rxData++;
125         }
126         else
127         {
128             if (handle->direction == kFLEXIO_SPI_MsbFirst)
129             {
130                 *((uint16_t *)(handle->rxData)) = tmpData;
131             }
132             else
133             {
134                 *((uint16_t *)(handle->rxData)) = (((tmpData << 8) & 0xff00U) | ((tmpData >> 8) & 0x00ffU));
135             }
136             handle->rxData += 2U;
137         }
138     }
139     handle->rxRemainingBytes -= handle->bytePerFrame;
140 }
141 
FLEXIO_SPI_MasterInit(FLEXIO_SPI_Type * base,flexio_spi_master_config_t * masterConfig,uint32_t srcClock_Hz)142 void FLEXIO_SPI_MasterInit(FLEXIO_SPI_Type *base, flexio_spi_master_config_t *masterConfig, uint32_t srcClock_Hz)
143 {
144     assert(base);
145     assert(masterConfig);
146 
147     flexio_shifter_config_t shifterConfig;
148     flexio_timer_config_t timerConfig;
149     uint32_t ctrlReg = 0;
150     uint16_t timerDiv = 0;
151     uint16_t timerCmp = 0;
152 
153     /* Clear the shifterConfig & timerConfig struct. */
154     memset(&shifterConfig, 0, sizeof(shifterConfig));
155     memset(&timerConfig, 0, sizeof(timerConfig));
156 
157 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
158     /* Ungate flexio clock. */
159     CLOCK_EnableClock(s_flexioClocks[FLEXIO_SPI_GetInstance(base)]);
160 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
161 
162     /* Configure FLEXIO SPI Master */
163     ctrlReg = base->flexioBase->CTRL;
164     ctrlReg &= ~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
165     ctrlReg |= (FLEXIO_CTRL_DBGE(masterConfig->enableInDebug) | FLEXIO_CTRL_FASTACC(masterConfig->enableFastAccess) |
166                 FLEXIO_CTRL_FLEXEN(masterConfig->enableMaster));
167     if (!masterConfig->enableInDoze)
168     {
169         ctrlReg |= FLEXIO_CTRL_DOZEN_MASK;
170     }
171 
172     base->flexioBase->CTRL = ctrlReg;
173 
174     /* Do hardware configuration. */
175     /* 1. Configure the shifter 0 for tx. */
176     shifterConfig.timerSelect = base->timerIndex[0];
177     shifterConfig.pinConfig = kFLEXIO_PinConfigOutput;
178     shifterConfig.pinSelect = base->SDOPinIndex;
179     shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
180     shifterConfig.shifterMode = kFLEXIO_ShifterModeTransmit;
181     shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
182     if (masterConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
183     {
184         shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
185         shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable;
186         shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
187     }
188     else
189     {
190         shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
191         shifterConfig.shifterStop = kFLEXIO_ShifterStopBitLow;
192         shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnShift;
193     }
194 
195     FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[0], &shifterConfig);
196 
197     /* 2. Configure the shifter 1 for rx. */
198     shifterConfig.timerSelect = base->timerIndex[0];
199     shifterConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
200     shifterConfig.pinSelect = base->SDIPinIndex;
201     shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
202     shifterConfig.shifterMode = kFLEXIO_ShifterModeReceive;
203     shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
204     shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable;
205     shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
206     if (masterConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
207     {
208         shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
209     }
210     else
211     {
212         shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
213     }
214 
215     FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[1], &shifterConfig);
216 
217     /*3. Configure the timer 0 for SCK. */
218     timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->shifterIndex[0]);
219     timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
220     timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
221     timerConfig.pinConfig = kFLEXIO_PinConfigOutput;
222     timerConfig.pinSelect = base->SCKPinIndex;
223     timerConfig.pinPolarity = kFLEXIO_PinActiveHigh;
224     timerConfig.timerMode = kFLEXIO_TimerModeDual8BitBaudBit;
225     timerConfig.timerOutput = kFLEXIO_TimerOutputZeroNotAffectedByReset;
226     timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
227     timerConfig.timerReset = kFLEXIO_TimerResetNever;
228     timerConfig.timerDisable = kFLEXIO_TimerDisableOnTimerCompare;
229     timerConfig.timerEnable = kFLEXIO_TimerEnableOnTriggerHigh;
230     timerConfig.timerStop = kFLEXIO_TimerStopBitEnableOnTimerDisable;
231     timerConfig.timerStart = kFLEXIO_TimerStartBitEnabled;
232 
233     timerDiv = srcClock_Hz / masterConfig->baudRate_Bps;
234     timerDiv = timerDiv / 2 - 1;
235 
236     timerCmp = ((uint32_t)(masterConfig->dataMode * 2 - 1U)) << 8U;
237     timerCmp |= timerDiv;
238 
239     timerConfig.timerCompare = timerCmp;
240 
241     FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[0], &timerConfig);
242 
243     /* 4. Configure the timer 1 for CSn. */
244     timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_TIMn(base->timerIndex[0]);
245     timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveHigh;
246     timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
247     timerConfig.pinConfig = kFLEXIO_PinConfigOutput;
248     timerConfig.pinSelect = base->CSnPinIndex;
249     timerConfig.pinPolarity = kFLEXIO_PinActiveLow;
250     timerConfig.timerMode = kFLEXIO_TimerModeSingle16Bit;
251     timerConfig.timerOutput = kFLEXIO_TimerOutputOneNotAffectedByReset;
252     timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
253     timerConfig.timerReset = kFLEXIO_TimerResetNever;
254     timerConfig.timerDisable = kFLEXIO_TimerDisableOnPreTimerDisable;
255     timerConfig.timerEnable = kFLEXIO_TimerEnableOnPrevTimerEnable;
256     timerConfig.timerStop = kFLEXIO_TimerStopBitDisabled;
257     timerConfig.timerStart = kFLEXIO_TimerStartBitDisabled;
258 
259     timerConfig.timerCompare = 0xFFFFU;
260 
261     FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[1], &timerConfig);
262 }
263 
FLEXIO_SPI_MasterDeinit(FLEXIO_SPI_Type * base)264 void FLEXIO_SPI_MasterDeinit(FLEXIO_SPI_Type *base)
265 {
266     /* Disable FLEXIO SPI module. */
267     FLEXIO_SPI_Enable(base, false);
268 
269 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
270     /* Gate flexio clock. */
271     CLOCK_DisableClock(kCLOCK_Flexio0);
272 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
273 }
274 
FLEXIO_SPI_MasterGetDefaultConfig(flexio_spi_master_config_t * masterConfig)275 void FLEXIO_SPI_MasterGetDefaultConfig(flexio_spi_master_config_t *masterConfig)
276 {
277     assert(masterConfig);
278 
279     masterConfig->enableMaster = true;
280     masterConfig->enableInDoze = false;
281     masterConfig->enableInDebug = true;
282     masterConfig->enableFastAccess = false;
283     /* Default baud rate 500kbps. */
284     masterConfig->baudRate_Bps = 500000U;
285     /* Default CPHA = 0. */
286     masterConfig->phase = kFLEXIO_SPI_ClockPhaseFirstEdge;
287     /* Default bit count at 8. */
288     masterConfig->dataMode = kFLEXIO_SPI_8BitMode;
289 }
290 
FLEXIO_SPI_SlaveInit(FLEXIO_SPI_Type * base,flexio_spi_slave_config_t * slaveConfig)291 void FLEXIO_SPI_SlaveInit(FLEXIO_SPI_Type *base, flexio_spi_slave_config_t *slaveConfig)
292 {
293     assert(base && slaveConfig);
294 
295     flexio_shifter_config_t shifterConfig;
296     flexio_timer_config_t timerConfig;
297     uint32_t ctrlReg = 0;
298 
299     /* Clear the shifterConfig & timerConfig struct. */
300     memset(&shifterConfig, 0, sizeof(shifterConfig));
301     memset(&timerConfig, 0, sizeof(timerConfig));
302 
303 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
304     /* Ungate flexio clock. */
305     CLOCK_EnableClock(kCLOCK_Flexio0);
306 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
307 
308     /* Configure FLEXIO SPI Slave */
309     ctrlReg = base->flexioBase->CTRL;
310     ctrlReg &= ~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
311     ctrlReg |= (FLEXIO_CTRL_DBGE(slaveConfig->enableInDebug) | FLEXIO_CTRL_FASTACC(slaveConfig->enableFastAccess) |
312                 FLEXIO_CTRL_FLEXEN(slaveConfig->enableSlave));
313     if (!slaveConfig->enableInDoze)
314     {
315         ctrlReg |= FLEXIO_CTRL_DOZEN_MASK;
316     }
317 
318     base->flexioBase->CTRL = ctrlReg;
319 
320     /* Do hardware configuration. */
321     /* 1. Configure the shifter 0 for tx. */
322     shifterConfig.timerSelect = base->timerIndex[0];
323     shifterConfig.pinConfig = kFLEXIO_PinConfigOutput;
324     shifterConfig.pinSelect = base->SDOPinIndex;
325     shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
326     shifterConfig.shifterMode = kFLEXIO_ShifterModeTransmit;
327     shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
328     shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable;
329     if (slaveConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
330     {
331         shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
332         shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
333     }
334     else
335     {
336         shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
337         shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnShift;
338     }
339 
340     FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[0], &shifterConfig);
341 
342     /* 2. Configure the shifter 1 for rx. */
343     shifterConfig.timerSelect = base->timerIndex[0];
344     shifterConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
345     shifterConfig.pinSelect = base->SDIPinIndex;
346     shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
347     shifterConfig.shifterMode = kFLEXIO_ShifterModeReceive;
348     shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
349     shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable;
350     shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
351     if (slaveConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
352     {
353         shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
354     }
355     else
356     {
357         shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
358     }
359 
360     FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[1], &shifterConfig);
361 
362     /*3. Configure the timer 0 for shift clock. */
363     timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_PININPUT(base->CSnPinIndex);
364     timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
365     timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
366     timerConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
367     timerConfig.pinSelect = base->SCKPinIndex;
368     timerConfig.pinPolarity = kFLEXIO_PinActiveHigh;
369     timerConfig.timerMode = kFLEXIO_TimerModeSingle16Bit;
370     timerConfig.timerOutput = kFLEXIO_TimerOutputZeroNotAffectedByReset;
371     timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnPinInputShiftPinInput;
372     timerConfig.timerReset = kFLEXIO_TimerResetNever;
373     timerConfig.timerEnable = kFLEXIO_TimerEnableOnTriggerRisingEdge;
374     timerConfig.timerStop = kFLEXIO_TimerStopBitDisabled;
375     if (slaveConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
376     {
377         /* The configuration kFLEXIO_TimerDisableOnTimerCompare only support continuous
378         PCS access, change to kFLEXIO_TimerDisableNever to enable discontinuous PCS access. */
379         timerConfig.timerDisable = kFLEXIO_TimerDisableOnTimerCompare;
380         timerConfig.timerStart = kFLEXIO_TimerStartBitDisabled;
381     }
382     else
383     {
384         timerConfig.timerDisable = kFLEXIO_TimerDisableOnTriggerFallingEdge;
385         timerConfig.timerStart = kFLEXIO_TimerStartBitEnabled;
386     }
387 
388     timerConfig.timerCompare = slaveConfig->dataMode * 2 - 1U;
389 
390     FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[0], &timerConfig);
391 }
392 
FLEXIO_SPI_SlaveDeinit(FLEXIO_SPI_Type * base)393 void FLEXIO_SPI_SlaveDeinit(FLEXIO_SPI_Type *base)
394 {
395     FLEXIO_SPI_MasterDeinit(base);
396 }
397 
FLEXIO_SPI_SlaveGetDefaultConfig(flexio_spi_slave_config_t * slaveConfig)398 void FLEXIO_SPI_SlaveGetDefaultConfig(flexio_spi_slave_config_t *slaveConfig)
399 {
400     assert(slaveConfig);
401 
402     slaveConfig->enableSlave = true;
403     slaveConfig->enableInDoze = false;
404     slaveConfig->enableInDebug = true;
405     slaveConfig->enableFastAccess = false;
406     /* Default CPHA = 0. */
407     slaveConfig->phase = kFLEXIO_SPI_ClockPhaseFirstEdge;
408     /* Default bit count at 8. */
409     slaveConfig->dataMode = kFLEXIO_SPI_8BitMode;
410 }
411 
FLEXIO_SPI_EnableInterrupts(FLEXIO_SPI_Type * base,uint32_t mask)412 void FLEXIO_SPI_EnableInterrupts(FLEXIO_SPI_Type *base, uint32_t mask)
413 {
414     if (mask & kFLEXIO_SPI_TxEmptyInterruptEnable)
415     {
416         FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1 << base->shifterIndex[0]);
417     }
418     if (mask & kFLEXIO_SPI_RxFullInterruptEnable)
419     {
420         FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1 << base->shifterIndex[1]);
421     }
422 }
423 
FLEXIO_SPI_DisableInterrupts(FLEXIO_SPI_Type * base,uint32_t mask)424 void FLEXIO_SPI_DisableInterrupts(FLEXIO_SPI_Type *base, uint32_t mask)
425 {
426     if (mask & kFLEXIO_SPI_TxEmptyInterruptEnable)
427     {
428         FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1 << base->shifterIndex[0]);
429     }
430     if (mask & kFLEXIO_SPI_RxFullInterruptEnable)
431     {
432         FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1 << base->shifterIndex[1]);
433     }
434 }
435 
FLEXIO_SPI_EnableDMA(FLEXIO_SPI_Type * base,uint32_t mask,bool enable)436 void FLEXIO_SPI_EnableDMA(FLEXIO_SPI_Type *base, uint32_t mask, bool enable)
437 {
438     if (mask & kFLEXIO_SPI_TxDmaEnable)
439     {
440         FLEXIO_EnableShifterStatusDMA(base->flexioBase, 1U << base->shifterIndex[0], enable);
441     }
442 
443     if (mask & kFLEXIO_SPI_RxDmaEnable)
444     {
445         FLEXIO_EnableShifterStatusDMA(base->flexioBase, 1U << base->shifterIndex[1], enable);
446     }
447 }
448 
FLEXIO_SPI_GetStatusFlags(FLEXIO_SPI_Type * base)449 uint32_t FLEXIO_SPI_GetStatusFlags(FLEXIO_SPI_Type *base)
450 {
451     uint32_t shifterStatus = FLEXIO_GetShifterStatusFlags(base->flexioBase);
452     uint32_t status = 0;
453 
454     status = ((shifterStatus & (1U << base->shifterIndex[0])) >> base->shifterIndex[0]);
455     status |= (((shifterStatus & (1U << base->shifterIndex[1])) >> (base->shifterIndex[1])) << 1U);
456 
457     return status;
458 }
459 
FLEXIO_SPI_ClearStatusFlags(FLEXIO_SPI_Type * base,uint32_t mask)460 void FLEXIO_SPI_ClearStatusFlags(FLEXIO_SPI_Type *base, uint32_t mask)
461 {
462     if (mask & kFLEXIO_SPI_TxBufferEmptyFlag)
463     {
464         FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1U << base->shifterIndex[0]);
465     }
466     if (mask & kFLEXIO_SPI_RxBufferFullFlag)
467     {
468         FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1U << base->shifterIndex[1]);
469     }
470 }
471 
FLEXIO_SPI_MasterSetBaudRate(FLEXIO_SPI_Type * base,uint32_t baudRate_Bps,uint32_t srcClockHz)472 void FLEXIO_SPI_MasterSetBaudRate(FLEXIO_SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcClockHz)
473 {
474     uint16_t timerDiv = 0;
475     uint16_t timerCmp = 0;
476     FLEXIO_Type *flexioBase = base->flexioBase;
477 
478     /* Set TIMCMP[7:0] = (baud rate divider / 2) - 1.*/
479     timerDiv = srcClockHz / baudRate_Bps;
480     timerDiv = timerDiv / 2 - 1U;
481 
482     timerCmp = flexioBase->TIMCMP[base->timerIndex[0]];
483     timerCmp &= 0xFF00U;
484     timerCmp |= timerDiv;
485 
486     flexioBase->TIMCMP[base->timerIndex[0]] = timerCmp;
487 }
488 
FLEXIO_SPI_WriteBlocking(FLEXIO_SPI_Type * base,flexio_spi_shift_direction_t direction,const uint8_t * buffer,size_t size)489 void FLEXIO_SPI_WriteBlocking(FLEXIO_SPI_Type *base,
490                               flexio_spi_shift_direction_t direction,
491                               const uint8_t *buffer,
492                               size_t size)
493 {
494     assert(buffer);
495     assert(size);
496 
497     while (size--)
498     {
499         /* Wait until data transfer complete. */
500         while (!(FLEXIO_SPI_GetStatusFlags(base) & kFLEXIO_SPI_TxBufferEmptyFlag))
501         {
502         }
503         FLEXIO_SPI_WriteData(base, direction, *buffer++);
504     }
505 }
506 
FLEXIO_SPI_ReadBlocking(FLEXIO_SPI_Type * base,flexio_spi_shift_direction_t direction,uint8_t * buffer,size_t size)507 void FLEXIO_SPI_ReadBlocking(FLEXIO_SPI_Type *base,
508                              flexio_spi_shift_direction_t direction,
509                              uint8_t *buffer,
510                              size_t size)
511 {
512     assert(buffer);
513     assert(size);
514 
515     while (size--)
516     {
517         /* Wait until data transfer complete. */
518         while (!(FLEXIO_SPI_GetStatusFlags(base) & kFLEXIO_SPI_RxBufferFullFlag))
519         {
520         }
521         *buffer++ = FLEXIO_SPI_ReadData(base, direction);
522     }
523 }
524 
FLEXIO_SPI_MasterTransferBlocking(FLEXIO_SPI_Type * base,flexio_spi_transfer_t * xfer)525 void FLEXIO_SPI_MasterTransferBlocking(FLEXIO_SPI_Type *base, flexio_spi_transfer_t *xfer)
526 {
527     flexio_spi_shift_direction_t direction;
528     uint8_t bytesPerFrame;
529     uint32_t dataMode = 0;
530     uint16_t timerCmp = base->flexioBase->TIMCMP[base->timerIndex[0]];
531     uint16_t tmpData = FLEXIO_SPI_DUMMYDATA;
532 
533     timerCmp &= 0x00FFU;
534     /* Configure the values in handle. */
535     switch (xfer->flags)
536     {
537         case kFLEXIO_SPI_8bitMsb:
538             dataMode = (8 * 2 - 1U) << 8U;
539             bytesPerFrame = 1;
540             direction = kFLEXIO_SPI_MsbFirst;
541             break;
542 
543         case kFLEXIO_SPI_8bitLsb:
544             dataMode = (8 * 2 - 1U) << 8U;
545             bytesPerFrame = 1;
546             direction = kFLEXIO_SPI_LsbFirst;
547             break;
548 
549         case kFLEXIO_SPI_16bitMsb:
550             dataMode = (16 * 2 - 1U) << 8U;
551             bytesPerFrame = 2;
552             direction = kFLEXIO_SPI_MsbFirst;
553             break;
554 
555         case kFLEXIO_SPI_16bitLsb:
556             dataMode = (16 * 2 - 1U) << 8U;
557             bytesPerFrame = 2;
558             direction = kFLEXIO_SPI_LsbFirst;
559             break;
560 
561         default:
562             dataMode = (8 * 2 - 1U) << 8U;
563             bytesPerFrame = 1;
564             direction = kFLEXIO_SPI_MsbFirst;
565             assert(true);
566             break;
567     }
568 
569     dataMode |= timerCmp;
570 
571     /* Configure transfer size. */
572     base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
573 
574     while (xfer->dataSize)
575     {
576         /* Wait until data transfer complete. */
577         while (!(FLEXIO_SPI_GetStatusFlags(base) & kFLEXIO_SPI_TxBufferEmptyFlag))
578         {
579         }
580         if (xfer->txData != NULL)
581         {
582             /* Transmit data and update tx size/buff. */
583             if (bytesPerFrame == 1U)
584             {
585                 tmpData = *(xfer->txData);
586                 xfer->txData++;
587             }
588             else
589             {
590                 if (direction == kFLEXIO_SPI_MsbFirst)
591                 {
592                     tmpData = (uint32_t)(xfer->txData[0]) << 8U;
593                     tmpData += xfer->txData[1];
594                 }
595                 else
596                 {
597                     tmpData = (uint32_t)(xfer->txData[1]) << 8U;
598                     tmpData += xfer->txData[0];
599                 }
600                 xfer->txData += 2U;
601             }
602         }
603         else
604         {
605             tmpData = FLEXIO_SPI_DUMMYDATA;
606         }
607 
608         xfer->dataSize -= bytesPerFrame;
609 
610         FLEXIO_SPI_WriteData(base, direction, tmpData);
611 
612         while (!(FLEXIO_SPI_GetStatusFlags(base) & kFLEXIO_SPI_RxBufferFullFlag))
613         {
614         }
615         tmpData = FLEXIO_SPI_ReadData(base, direction);
616 
617         if (xfer->rxData != NULL)
618         {
619             if (bytesPerFrame == 1U)
620             {
621                 *xfer->rxData = tmpData;
622                 xfer->rxData++;
623             }
624             else
625             {
626                 if (direction == kFLEXIO_SPI_MsbFirst)
627                 {
628                     *((uint16_t *)(xfer->rxData)) = tmpData;
629                 }
630                 else
631                 {
632                     *((uint16_t *)(xfer->rxData)) = (((tmpData << 8) & 0xff00U) | ((tmpData >> 8) & 0x00ffU));
633                 }
634                 xfer->rxData += 2U;
635             }
636         }
637     }
638 }
639 
FLEXIO_SPI_MasterTransferCreateHandle(FLEXIO_SPI_Type * base,flexio_spi_master_handle_t * handle,flexio_spi_master_transfer_callback_t callback,void * userData)640 status_t FLEXIO_SPI_MasterTransferCreateHandle(FLEXIO_SPI_Type *base,
641                                                flexio_spi_master_handle_t *handle,
642                                                flexio_spi_master_transfer_callback_t callback,
643                                                void *userData)
644 {
645     assert(handle);
646 
647     IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
648 
649     /* Zero the handle. */
650     memset(handle, 0, sizeof(*handle));
651 
652     /* Register callback and userData. */
653     handle->callback = callback;
654     handle->userData = userData;
655 
656     /* Enable interrupt in NVIC. */
657     EnableIRQ(flexio_irqs[FLEXIO_SPI_GetInstance(base)]);
658 
659     /* Save the context in global variables to support the double weak mechanism. */
660     return FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_SPI_MasterTransferHandleIRQ);
661 }
662 
FLEXIO_SPI_MasterTransferNonBlocking(FLEXIO_SPI_Type * base,flexio_spi_master_handle_t * handle,flexio_spi_transfer_t * xfer)663 status_t FLEXIO_SPI_MasterTransferNonBlocking(FLEXIO_SPI_Type *base,
664                                               flexio_spi_master_handle_t *handle,
665                                               flexio_spi_transfer_t *xfer)
666 {
667     assert(handle);
668     assert(xfer);
669 
670     uint32_t dataMode = 0;
671     uint16_t timerCmp = base->flexioBase->TIMCMP[base->timerIndex[0]];
672     uint16_t tmpData = FLEXIO_SPI_DUMMYDATA;
673 
674     timerCmp &= 0x00FFU;
675 
676     /* Check if SPI is busy. */
677     if (handle->state == kFLEXIO_SPI_Busy)
678     {
679         return kStatus_FLEXIO_SPI_Busy;
680     }
681 
682     /* Check if the argument is legal. */
683     if ((xfer->txData == NULL) && (xfer->rxData == NULL))
684     {
685         return kStatus_InvalidArgument;
686     }
687 
688     /* Configure the values in handle */
689     switch (xfer->flags)
690     {
691         case kFLEXIO_SPI_8bitMsb:
692             dataMode = (8 * 2 - 1U) << 8U;
693             handle->bytePerFrame = 1U;
694             handle->direction = kFLEXIO_SPI_MsbFirst;
695             break;
696         case kFLEXIO_SPI_8bitLsb:
697             dataMode = (8 * 2 - 1U) << 8U;
698             handle->bytePerFrame = 1U;
699             handle->direction = kFLEXIO_SPI_LsbFirst;
700             break;
701         case kFLEXIO_SPI_16bitMsb:
702             dataMode = (16 * 2 - 1U) << 8U;
703             handle->bytePerFrame = 2U;
704             handle->direction = kFLEXIO_SPI_MsbFirst;
705             break;
706         case kFLEXIO_SPI_16bitLsb:
707             dataMode = (16 * 2 - 1U) << 8U;
708             handle->bytePerFrame = 2U;
709             handle->direction = kFLEXIO_SPI_LsbFirst;
710             break;
711         default:
712             dataMode = (8 * 2 - 1U) << 8U;
713             handle->bytePerFrame = 1U;
714             handle->direction = kFLEXIO_SPI_MsbFirst;
715             assert(true);
716             break;
717     }
718 
719     dataMode |= timerCmp;
720 
721     /* Configure transfer size. */
722     base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
723 
724     handle->state = kFLEXIO_SPI_Busy;
725     handle->txData = xfer->txData;
726     handle->rxData = xfer->rxData;
727     handle->rxRemainingBytes = xfer->dataSize;
728 
729     /* Save total transfer size. */
730     handle->transferSize = xfer->dataSize;
731 
732     /* Send first byte of data to trigger the rx interrupt. */
733     if (handle->txData != NULL)
734     {
735         /* Transmit data and update tx size/buff. */
736         if (handle->bytePerFrame == 1U)
737         {
738             tmpData = *(handle->txData);
739             handle->txData++;
740         }
741         else
742         {
743             if (handle->direction == kFLEXIO_SPI_MsbFirst)
744             {
745                 tmpData = (uint32_t)(handle->txData[0]) << 8U;
746                 tmpData += handle->txData[1];
747             }
748             else
749             {
750                 tmpData = (uint32_t)(handle->txData[1]) << 8U;
751                 tmpData += handle->txData[0];
752             }
753             handle->txData += 2U;
754         }
755     }
756     else
757     {
758         tmpData = FLEXIO_SPI_DUMMYDATA;
759     }
760 
761     handle->txRemainingBytes = xfer->dataSize - handle->bytePerFrame;
762 
763     FLEXIO_SPI_WriteData(base, handle->direction, tmpData);
764 
765     /* Enable transmit and receive interrupt to handle rx. */
766     FLEXIO_SPI_EnableInterrupts(base, kFLEXIO_SPI_RxFullInterruptEnable);
767 
768     return kStatus_Success;
769 }
770 
FLEXIO_SPI_MasterTransferGetCount(FLEXIO_SPI_Type * base,flexio_spi_master_handle_t * handle,size_t * count)771 status_t FLEXIO_SPI_MasterTransferGetCount(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle, size_t *count)
772 {
773     assert(handle);
774 
775     if (!count)
776     {
777         return kStatus_InvalidArgument;
778     }
779 
780     /* Return remaing bytes in different cases. */
781     if (handle->rxData)
782     {
783         *count = handle->transferSize - handle->rxRemainingBytes;
784     }
785     else
786     {
787         *count = handle->transferSize - handle->txRemainingBytes;
788     }
789 
790     return kStatus_Success;
791 }
792 
FLEXIO_SPI_MasterTransferAbort(FLEXIO_SPI_Type * base,flexio_spi_master_handle_t * handle)793 void FLEXIO_SPI_MasterTransferAbort(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle)
794 {
795     assert(handle);
796 
797     FLEXIO_SPI_DisableInterrupts(base, kFLEXIO_SPI_RxFullInterruptEnable);
798     FLEXIO_SPI_DisableInterrupts(base, kFLEXIO_SPI_TxEmptyInterruptEnable);
799 
800     /* Transfer finished, set the state to idle. */
801     handle->state = kFLEXIO_SPI_Idle;
802 
803     /* Clear the internal state. */
804     handle->rxRemainingBytes = 0;
805     handle->txRemainingBytes = 0;
806 }
807 
FLEXIO_SPI_MasterTransferHandleIRQ(void * spiType,void * spiHandle)808 void FLEXIO_SPI_MasterTransferHandleIRQ(void *spiType, void *spiHandle)
809 {
810     assert(spiHandle);
811 
812     flexio_spi_master_handle_t *handle = (flexio_spi_master_handle_t *)spiHandle;
813     FLEXIO_SPI_Type *base;
814     uint32_t status;
815 
816     if (handle->state == kFLEXIO_SPI_Idle)
817     {
818         return;
819     }
820 
821     base = (FLEXIO_SPI_Type *)spiType;
822     status = FLEXIO_SPI_GetStatusFlags(base);
823 
824     /* Handle rx. */
825     if ((status & kFLEXIO_SPI_RxBufferFullFlag) && (handle->rxRemainingBytes))
826     {
827         FLEXIO_SPI_TransferReceiveTransaction(base, handle);
828     }
829 
830     /* Handle tx. */
831     if ((status & kFLEXIO_SPI_TxBufferEmptyFlag) && (handle->txRemainingBytes))
832     {
833         FLEXIO_SPI_TransferSendTransaction(base, handle);
834     }
835 
836     /* All the transfer finished. */
837     if ((handle->txRemainingBytes == 0U) && (handle->rxRemainingBytes == 0U))
838     {
839         FLEXIO_SPI_MasterTransferAbort(base, handle);
840         if (handle->callback)
841         {
842             (handle->callback)(base, handle, kStatus_FLEXIO_SPI_Idle, handle->userData);
843         }
844     }
845 }
846 
FLEXIO_SPI_SlaveTransferCreateHandle(FLEXIO_SPI_Type * base,flexio_spi_slave_handle_t * handle,flexio_spi_slave_transfer_callback_t callback,void * userData)847 status_t FLEXIO_SPI_SlaveTransferCreateHandle(FLEXIO_SPI_Type *base,
848                                               flexio_spi_slave_handle_t *handle,
849                                               flexio_spi_slave_transfer_callback_t callback,
850                                               void *userData)
851 {
852     assert(handle);
853 
854     IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
855 
856     /* Zero the handle. */
857     memset(handle, 0, sizeof(*handle));
858 
859     /* Register callback and userData. */
860     handle->callback = callback;
861     handle->userData = userData;
862 
863     /* Enable interrupt in NVIC. */
864     EnableIRQ(flexio_irqs[FLEXIO_SPI_GetInstance(base)]);
865 
866     /* Save the context in global variables to support the double weak mechanism. */
867     return FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_SPI_SlaveTransferHandleIRQ);
868 }
869 
FLEXIO_SPI_SlaveTransferNonBlocking(FLEXIO_SPI_Type * base,flexio_spi_slave_handle_t * handle,flexio_spi_transfer_t * xfer)870 status_t FLEXIO_SPI_SlaveTransferNonBlocking(FLEXIO_SPI_Type *base,
871                                              flexio_spi_slave_handle_t *handle,
872                                              flexio_spi_transfer_t *xfer)
873 {
874     assert(handle);
875     assert(xfer);
876 
877     uint32_t dataMode = 0;
878 
879     /* Check if SPI is busy. */
880     if (handle->state == kFLEXIO_SPI_Busy)
881     {
882         return kStatus_FLEXIO_SPI_Busy;
883     }
884 
885     /* Check if the argument is legal. */
886     if ((xfer->txData == NULL) && (xfer->rxData == NULL))
887     {
888         return kStatus_InvalidArgument;
889     }
890 
891     /* Configure the values in handle */
892     switch (xfer->flags)
893     {
894         case kFLEXIO_SPI_8bitMsb:
895             dataMode = 8 * 2 - 1U;
896             handle->bytePerFrame = 1U;
897             handle->direction = kFLEXIO_SPI_MsbFirst;
898             break;
899         case kFLEXIO_SPI_8bitLsb:
900             dataMode = 8 * 2 - 1U;
901             handle->bytePerFrame = 1U;
902             handle->direction = kFLEXIO_SPI_LsbFirst;
903             break;
904         case kFLEXIO_SPI_16bitMsb:
905             dataMode = 16 * 2 - 1U;
906             handle->bytePerFrame = 2U;
907             handle->direction = kFLEXIO_SPI_MsbFirst;
908             break;
909         case kFLEXIO_SPI_16bitLsb:
910             dataMode = 16 * 2 - 1U;
911             handle->bytePerFrame = 2U;
912             handle->direction = kFLEXIO_SPI_LsbFirst;
913             break;
914         default:
915             dataMode = 8 * 2 - 1U;
916             handle->bytePerFrame = 1U;
917             handle->direction = kFLEXIO_SPI_MsbFirst;
918             assert(true);
919             break;
920     }
921 
922     /* Configure transfer size. */
923     base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
924 
925     handle->state = kFLEXIO_SPI_Busy;
926     handle->txData = xfer->txData;
927     handle->rxData = xfer->rxData;
928     handle->txRemainingBytes = xfer->dataSize;
929     handle->rxRemainingBytes = xfer->dataSize;
930 
931     /* Save total transfer size. */
932     handle->transferSize = xfer->dataSize;
933 
934     /* Enable transmit and receive interrupt to handle tx and rx. */
935     FLEXIO_SPI_EnableInterrupts(base, kFLEXIO_SPI_TxEmptyInterruptEnable);
936     FLEXIO_SPI_EnableInterrupts(base, kFLEXIO_SPI_RxFullInterruptEnable);
937 
938     return kStatus_Success;
939 }
940 
FLEXIO_SPI_SlaveTransferHandleIRQ(void * spiType,void * spiHandle)941 void FLEXIO_SPI_SlaveTransferHandleIRQ(void *spiType, void *spiHandle)
942 {
943     assert(spiHandle);
944 
945     flexio_spi_master_handle_t *handle = (flexio_spi_master_handle_t *)spiHandle;
946     FLEXIO_SPI_Type *base;
947     uint32_t status;
948 
949     if (handle->state == kFLEXIO_SPI_Idle)
950     {
951         return;
952     }
953 
954     base = (FLEXIO_SPI_Type *)spiType;
955     status = FLEXIO_SPI_GetStatusFlags(base);
956 
957     /* Handle tx. */
958     if ((status & kFLEXIO_SPI_TxBufferEmptyFlag) && (handle->txRemainingBytes))
959     {
960         FLEXIO_SPI_TransferSendTransaction(base, handle);
961     }
962 
963     /* Handle rx. */
964     if ((status & kFLEXIO_SPI_RxBufferFullFlag) && (handle->rxRemainingBytes))
965     {
966         FLEXIO_SPI_TransferReceiveTransaction(base, handle);
967     }
968 
969     /* All the transfer finished. */
970     if ((handle->txRemainingBytes == 0U) && (handle->rxRemainingBytes == 0U))
971     {
972         FLEXIO_SPI_SlaveTransferAbort(base, handle);
973         if (handle->callback)
974         {
975             (handle->callback)(base, handle, kStatus_FLEXIO_SPI_Idle, handle->userData);
976         }
977     }
978 }
979