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_lpspi.h"
10 
11 /*******************************************************************************
12 * Definitions
13 ******************************************************************************/
14 /*!
15  * @brief Default watermark values.
16  *
17  * The default watermarks are set to zero.
18  */
19 enum _lpspi_default_watermarks
20 {
21     kLpspiDefaultTxWatermark = 0,
22     kLpspiDefaultRxWatermark = 0,
23 };
24 
25 /*! @brief Typedef for master interrupt handler. */
26 typedef void (*lpspi_master_isr_t)(LPSPI_Type *base, lpspi_master_handle_t *handle);
27 
28 /*! @brief Typedef for slave interrupt handler. */
29 typedef void (*lpspi_slave_isr_t)(LPSPI_Type *base, lpspi_slave_handle_t *handle);
30 
31 /*******************************************************************************
32 * Prototypes
33 ******************************************************************************/
34 /*!
35 * @brief Get instance number for LPSPI module.
36 *
37 * @param base LPSPI peripheral base address.
38 */
39 uint32_t LPSPI_GetInstance(LPSPI_Type *base);
40 
41 /*!
42 * @brief Configures the LPSPI peripheral chip select polarity.
43 *
44 * This function  takes in the desired peripheral chip select (Pcs) and it's corresponding desired polarity and
45 * configures the Pcs signal to operate with the desired characteristic.
46 *
47 * @param base LPSPI peripheral address.
48 * @param pcs The particular peripheral chip select (parameter value is of type lpspi_which_pcs_t) for which we wish to
49 *            apply the active high or active low characteristic.
50 * @param activeLowOrHigh The setting for either "active high, inactive low (0)"  or "active low, inactive high(1)" of
51 *                        type lpspi_pcs_polarity_config_t.
52 */
53 static void LPSPI_SetOnePcsPolarity(LPSPI_Type *base,
54                                     lpspi_which_pcs_t pcs,
55                                     lpspi_pcs_polarity_config_t activeLowOrHigh);
56 
57 /*!
58 * @brief Combine the write data for 1 byte to 4 bytes.
59 * This is not a public API.
60 */
61 static uint32_t LPSPI_CombineWriteData(uint8_t *txData, uint32_t bytesEachWrite, bool isByteSwap);
62 
63 /*!
64 * @brief Separate the read data for 1 byte to 4 bytes.
65 * This is not a public API.
66 */
67 static void LPSPI_SeparateReadData(uint8_t *rxData, uint32_t readData, uint32_t bytesEachRead, bool isByteSwap);
68 
69 /*!
70 * @brief Master fill up the TX FIFO with data.
71 * This is not a public API.
72 */
73 static void LPSPI_MasterTransferFillUpTxFifo(LPSPI_Type *base, lpspi_master_handle_t *handle);
74 
75 /*!
76 * @brief Master finish up a transfer.
77 * It would call back if there is callback function and set the state to idle.
78 * This is not a public API.
79 */
80 static void LPSPI_MasterTransferComplete(LPSPI_Type *base, lpspi_master_handle_t *handle);
81 
82 /*!
83 * @brief Slave fill up the TX FIFO with data.
84 * This is not a public API.
85 */
86 static void LPSPI_SlaveTransferFillUpTxFifo(LPSPI_Type *base, lpspi_slave_handle_t *handle);
87 
88 /*!
89 * @brief Slave finish up a transfer.
90 * It would call back if there is callback function and set the state to idle.
91 * This is not a public API.
92 */
93 static void LPSPI_SlaveTransferComplete(LPSPI_Type *base, lpspi_slave_handle_t *handle);
94 
95 /*!
96 * @brief Check the argument for transfer .
97 * This is not a public API. Not static because lpspi_edma.c will use this API.
98 */
99 bool LPSPI_CheckTransferArgument(lpspi_transfer_t *transfer, uint32_t bitsPerFrame, uint32_t bytesPerFrame);
100 
101 /*!
102 * @brief LPSPI common interrupt handler.
103 *
104 * @param handle pointer to s_lpspiHandle which stores the transfer state.
105 */
106 static void LPSPI_CommonIRQHandler(LPSPI_Type *base, void *param);
107 
108 /*******************************************************************************
109 * Variables
110 ******************************************************************************/
111 
112 /* Defines constant value arrays for the baud rate pre-scalar and scalar divider values.*/
113 static const uint8_t s_baudratePrescaler[] = {1, 2, 4, 8, 16, 32, 64, 128};
114 
115 /*! @brief Pointers to lpspi bases for each instance. */
116 static LPSPI_Type *const s_lpspiBases[] = LPSPI_BASE_PTRS;
117 
118 /*! @brief Pointers to lpspi IRQ number for each instance. */
119 static const IRQn_Type s_lpspiIRQ[] = LPSPI_IRQS;
120 
121 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
122 /*! @brief Pointers to lpspi clocks for each instance. */
123 static const clock_ip_name_t s_lpspiClocks[] = LPSPI_CLOCKS;
124 
125 #if defined(LPSPI_PERIPH_CLOCKS)
126 static const clock_ip_name_t s_LpspiPeriphClocks[] = LPSPI_PERIPH_CLOCKS;
127 #endif
128 
129 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
130 
131 /*! @brief Pointers to lpspi handles for each instance. */
132 static void *s_lpspiHandle[FSL_FEATURE_SOC_LPSPI_COUNT] = {NULL};
133 
134 /*! @brief Pointer to master IRQ handler for each instance. */
135 static lpspi_master_isr_t s_lpspiMasterIsr;
136 /*! @brief Pointer to slave IRQ handler for each instance. */
137 static lpspi_slave_isr_t s_lpspiSlaveIsr;
138 /* @brief Dummy data for each instance. This data is used when user's tx buffer is NULL*/
139 volatile uint8_t s_dummyData[ARRAY_SIZE(s_lpspiBases)] = {0};
140 /**********************************************************************************************************************
141 * Code
142 *********************************************************************************************************************/
LPSPI_GetInstance(LPSPI_Type * base)143 uint32_t LPSPI_GetInstance(LPSPI_Type *base)
144 {
145     uint8_t instance = 0;
146 
147     /* Find the instance index from base address mappings. */
148     for (instance = 0; instance < ARRAY_SIZE(s_lpspiBases); instance++)
149     {
150         if (s_lpspiBases[instance] == base)
151         {
152             break;
153         }
154     }
155 
156     assert(instance < ARRAY_SIZE(s_lpspiBases));
157 
158     return instance;
159 }
160 
LPSPI_SetDummyData(LPSPI_Type * base,uint8_t dummyData)161 void LPSPI_SetDummyData(LPSPI_Type *base, uint8_t dummyData)
162 {
163     uint32_t instance = LPSPI_GetInstance(base);
164     s_dummyData[instance] = dummyData;
165 }
166 
LPSPI_MasterInit(LPSPI_Type * base,const lpspi_master_config_t * masterConfig,uint32_t srcClock_Hz)167 void LPSPI_MasterInit(LPSPI_Type *base, const lpspi_master_config_t *masterConfig, uint32_t srcClock_Hz)
168 {
169     assert(masterConfig);
170 
171     uint32_t tcrPrescaleValue = 0;
172 
173 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
174 
175     uint32_t instance = LPSPI_GetInstance(base);
176     /* Enable LPSPI clock */
177     CLOCK_EnableClock(s_lpspiClocks[instance]);
178 
179 #if defined(LPSPI_PERIPH_CLOCKS)
180     CLOCK_EnableClock(s_LpspiPeriphClocks[instance]);
181 #endif
182 
183 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
184 
185     /* Reset to known status */
186     LPSPI_Reset(base);
187 
188     /* Set LPSPI to master */
189     LPSPI_SetMasterSlaveMode(base, kLPSPI_Master);
190 
191     /* Set specific PCS to active high or low */
192     LPSPI_SetOnePcsPolarity(base, masterConfig->whichPcs, masterConfig->pcsActiveHighOrLow);
193 
194     /* Set Configuration Register 1 related setting.*/
195     base->CFGR1 = (base->CFGR1 & ~(LPSPI_CFGR1_OUTCFG_MASK | LPSPI_CFGR1_PINCFG_MASK | LPSPI_CFGR1_NOSTALL_MASK)) |
196                   LPSPI_CFGR1_OUTCFG(masterConfig->dataOutConfig) | LPSPI_CFGR1_PINCFG(masterConfig->pinCfg) |
197                   LPSPI_CFGR1_NOSTALL(0);
198 
199     /* Set baudrate and delay times*/
200     LPSPI_MasterSetBaudRate(base, masterConfig->baudRate, srcClock_Hz, &tcrPrescaleValue);
201 
202     /* Set default watermarks */
203     LPSPI_SetFifoWatermarks(base, kLpspiDefaultTxWatermark, kLpspiDefaultRxWatermark);
204 
205     /* Set Transmit Command Register*/
206     base->TCR = LPSPI_TCR_CPOL(masterConfig->cpol) | LPSPI_TCR_CPHA(masterConfig->cpha) |
207                 LPSPI_TCR_LSBF(masterConfig->direction) | LPSPI_TCR_FRAMESZ(masterConfig->bitsPerFrame - 1) |
208                 LPSPI_TCR_PRESCALE(tcrPrescaleValue) | LPSPI_TCR_PCS(masterConfig->whichPcs);
209 
210     LPSPI_Enable(base, true);
211 
212     LPSPI_MasterSetDelayTimes(base, masterConfig->pcsToSckDelayInNanoSec, kLPSPI_PcsToSck, srcClock_Hz);
213     LPSPI_MasterSetDelayTimes(base, masterConfig->lastSckToPcsDelayInNanoSec, kLPSPI_LastSckToPcs, srcClock_Hz);
214     LPSPI_MasterSetDelayTimes(base, masterConfig->betweenTransferDelayInNanoSec, kLPSPI_BetweenTransfer, srcClock_Hz);
215 
216     LPSPI_SetDummyData(base, LPSPI_DUMMY_DATA);
217 }
218 
LPSPI_MasterGetDefaultConfig(lpspi_master_config_t * masterConfig)219 void LPSPI_MasterGetDefaultConfig(lpspi_master_config_t *masterConfig)
220 {
221     assert(masterConfig);
222 
223     masterConfig->baudRate = 500000;
224     masterConfig->bitsPerFrame = 8;
225     masterConfig->cpol = kLPSPI_ClockPolarityActiveHigh;
226     masterConfig->cpha = kLPSPI_ClockPhaseFirstEdge;
227     masterConfig->direction = kLPSPI_MsbFirst;
228 
229     masterConfig->pcsToSckDelayInNanoSec = 1000000000 / masterConfig->baudRate * 2;
230     masterConfig->lastSckToPcsDelayInNanoSec = 1000000000 / masterConfig->baudRate * 2;
231     masterConfig->betweenTransferDelayInNanoSec = 1000000000 / masterConfig->baudRate * 2;
232 
233     masterConfig->whichPcs = kLPSPI_Pcs0;
234     masterConfig->pcsActiveHighOrLow = kLPSPI_PcsActiveLow;
235 
236     masterConfig->pinCfg = kLPSPI_SdiInSdoOut;
237     masterConfig->dataOutConfig = kLpspiDataOutRetained;
238 }
239 
LPSPI_SlaveInit(LPSPI_Type * base,const lpspi_slave_config_t * slaveConfig)240 void LPSPI_SlaveInit(LPSPI_Type *base, const lpspi_slave_config_t *slaveConfig)
241 {
242     assert(slaveConfig);
243 
244 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
245 
246     uint32_t instance = LPSPI_GetInstance(base);
247     /* Enable LPSPI clock */
248     CLOCK_EnableClock(s_lpspiClocks[instance]);
249 
250 #if defined(LPSPI_PERIPH_CLOCKS)
251     CLOCK_EnableClock(s_LpspiPeriphClocks[instance]);
252 #endif
253 
254 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
255 
256     /* Reset to known status */
257     LPSPI_Reset(base);
258 
259     LPSPI_SetMasterSlaveMode(base, kLPSPI_Slave);
260 
261     LPSPI_SetOnePcsPolarity(base, slaveConfig->whichPcs, slaveConfig->pcsActiveHighOrLow);
262 
263     base->CFGR1 = (base->CFGR1 & ~(LPSPI_CFGR1_OUTCFG_MASK | LPSPI_CFGR1_PINCFG_MASK)) |
264                   LPSPI_CFGR1_OUTCFG(slaveConfig->dataOutConfig) | LPSPI_CFGR1_PINCFG(slaveConfig->pinCfg);
265 
266     LPSPI_SetFifoWatermarks(base, kLpspiDefaultTxWatermark, kLpspiDefaultRxWatermark);
267 
268     base->TCR = LPSPI_TCR_CPOL(slaveConfig->cpol) | LPSPI_TCR_CPHA(slaveConfig->cpha) |
269                 LPSPI_TCR_LSBF(slaveConfig->direction) | LPSPI_TCR_FRAMESZ(slaveConfig->bitsPerFrame - 1) | LPSPI_TCR_PCS(slaveConfig->whichPcs);
270 
271     /* This operation will set the dummy data for edma transfer, no effect in interrupt way. */
272     LPSPI_SetDummyData(base, LPSPI_DUMMY_DATA);
273 
274     LPSPI_Enable(base, true);
275 }
276 
LPSPI_SlaveGetDefaultConfig(lpspi_slave_config_t * slaveConfig)277 void LPSPI_SlaveGetDefaultConfig(lpspi_slave_config_t *slaveConfig)
278 {
279     assert(slaveConfig);
280 
281     slaveConfig->bitsPerFrame = 8;                      /*!< Bits per frame, minimum 8, maximum 4096.*/
282     slaveConfig->cpol = kLPSPI_ClockPolarityActiveHigh; /*!< Clock polarity. */
283     slaveConfig->cpha = kLPSPI_ClockPhaseFirstEdge;     /*!< Clock phase. */
284     slaveConfig->direction = kLPSPI_MsbFirst;           /*!< MSB or LSB data shift direction. */
285 
286     slaveConfig->whichPcs = kLPSPI_Pcs0;                   /*!< Desired Peripheral Chip Select (pcs) */
287     slaveConfig->pcsActiveHighOrLow = kLPSPI_PcsActiveLow; /*!< Desired PCS active high or low */
288 
289     slaveConfig->pinCfg = kLPSPI_SdiInSdoOut;
290     slaveConfig->dataOutConfig = kLpspiDataOutRetained;
291 }
292 
LPSPI_Reset(LPSPI_Type * base)293 void LPSPI_Reset(LPSPI_Type *base)
294 {
295     /* Reset all internal logic and registers, except the Control Register. Remains set until cleared by software.*/
296     base->CR |= LPSPI_CR_RST_MASK;
297 
298     /* Software reset doesn't reset the CR, so manual reset the FIFOs */
299     base->CR |= LPSPI_CR_RRF_MASK | LPSPI_CR_RTF_MASK;
300 
301     /* Master logic is not reset and module is disabled.*/
302     base->CR = 0x00U;
303 }
304 
LPSPI_Deinit(LPSPI_Type * base)305 void LPSPI_Deinit(LPSPI_Type *base)
306 {
307     /* Reset to default value */
308     LPSPI_Reset(base);
309 
310 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
311 
312     uint32_t instance = LPSPI_GetInstance(base);
313     /* Enable LPSPI clock */
314     CLOCK_DisableClock(s_lpspiClocks[instance]);
315 
316 #if defined(LPSPI_PERIPH_CLOCKS)
317     CLOCK_DisableClock(s_LpspiPeriphClocks[instance]);
318 #endif
319 
320 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
321 }
322 
LPSPI_SetOnePcsPolarity(LPSPI_Type * base,lpspi_which_pcs_t pcs,lpspi_pcs_polarity_config_t activeLowOrHigh)323 static void LPSPI_SetOnePcsPolarity(LPSPI_Type *base,
324                                     lpspi_which_pcs_t pcs,
325                                     lpspi_pcs_polarity_config_t activeLowOrHigh)
326 {
327     uint32_t cfgr1Value = 0;
328     /* Clear the PCS polarity bit */
329     cfgr1Value = base->CFGR1 & ~(1U << (LPSPI_CFGR1_PCSPOL_SHIFT + pcs));
330 
331     /* Configure the PCS polarity bit according to the activeLowOrHigh setting */
332     base->CFGR1 = cfgr1Value | ((uint32_t)activeLowOrHigh << (LPSPI_CFGR1_PCSPOL_SHIFT + pcs));
333 }
334 
LPSPI_MasterSetBaudRate(LPSPI_Type * base,uint32_t baudRate_Bps,uint32_t srcClock_Hz,uint32_t * tcrPrescaleValue)335 uint32_t LPSPI_MasterSetBaudRate(LPSPI_Type *base,
336                                  uint32_t baudRate_Bps,
337                                  uint32_t srcClock_Hz,
338                                  uint32_t *tcrPrescaleValue)
339 {
340     assert(tcrPrescaleValue);
341 
342     /* For master mode configuration only, if slave mode detected, return 0.
343     * Also, the LPSPI module needs to be disabled first, if enabled, return 0
344     */
345     if ((!LPSPI_IsMaster(base)) || (base->CR & LPSPI_CR_MEN_MASK))
346     {
347         return 0;
348     }
349 
350     uint32_t prescaler, bestPrescaler;
351     uint32_t scaler, bestScaler;
352     uint32_t realBaudrate, bestBaudrate;
353     uint32_t diff, min_diff;
354     uint32_t desiredBaudrate = baudRate_Bps;
355 
356     /* find combination of prescaler and scaler resulting in baudrate closest to the
357     * requested value
358     */
359     min_diff = 0xFFFFFFFFU;
360 
361     /* Set to maximum divisor value bit settings so that if baud rate passed in is less
362     * than the minimum possible baud rate, then the SPI will be configured to the lowest
363     * possible baud rate
364     */
365     bestPrescaler = 7;
366     bestScaler = 255;
367 
368     bestBaudrate = 0; /* required to avoid compilation warning */
369 
370     /* In all for loops, if min_diff = 0, the exit for loop*/
371     for (prescaler = 0; (prescaler < 8) && min_diff; prescaler++)
372     {
373         for (scaler = 0; (scaler < 256) && min_diff; scaler++)
374         {
375             realBaudrate = (srcClock_Hz / (s_baudratePrescaler[prescaler] * (scaler + 2U)));
376 
377             /* calculate the baud rate difference based on the conditional statement
378             * that states that the calculated baud rate must not exceed the desired baud rate
379             */
380             if (desiredBaudrate >= realBaudrate)
381             {
382                 diff = desiredBaudrate - realBaudrate;
383                 if (min_diff > diff)
384                 {
385                     /* a better match found */
386                     min_diff = diff;
387                     bestPrescaler = prescaler;
388                     bestScaler = scaler;
389                     bestBaudrate = realBaudrate;
390                 }
391             }
392         }
393     }
394 
395     /* Write the best baud rate scalar to the CCR.
396     * Note, no need to check for error since we've already checked to make sure the module is
397     * disabled and in master mode. Also, there is a limit on the maximum divider so we will not
398     * exceed this.
399     */
400     base->CCR = (base->CCR & ~LPSPI_CCR_SCKDIV_MASK) | LPSPI_CCR_SCKDIV(bestScaler);
401 
402     /* return the best prescaler value for user to use later */
403     *tcrPrescaleValue = bestPrescaler;
404 
405     /* return the actual calculated baud rate */
406     return bestBaudrate;
407 }
408 
LPSPI_MasterSetDelayScaler(LPSPI_Type * base,uint32_t scaler,lpspi_delay_type_t whichDelay)409 void LPSPI_MasterSetDelayScaler(LPSPI_Type *base, uint32_t scaler, lpspi_delay_type_t whichDelay)
410 {
411     /*These settings are only relevant in master mode */
412     switch (whichDelay)
413     {
414         case kLPSPI_PcsToSck:
415             base->CCR = (base->CCR & (~LPSPI_CCR_PCSSCK_MASK)) | LPSPI_CCR_PCSSCK(scaler);
416 
417             break;
418         case kLPSPI_LastSckToPcs:
419             base->CCR = (base->CCR & (~LPSPI_CCR_SCKPCS_MASK)) | LPSPI_CCR_SCKPCS(scaler);
420 
421             break;
422         case kLPSPI_BetweenTransfer:
423             base->CCR = (base->CCR & (~LPSPI_CCR_DBT_MASK)) | LPSPI_CCR_DBT(scaler);
424 
425             break;
426         default:
427             assert(false);
428             break;
429     }
430 }
431 
LPSPI_MasterSetDelayTimes(LPSPI_Type * base,uint32_t delayTimeInNanoSec,lpspi_delay_type_t whichDelay,uint32_t srcClock_Hz)432 uint32_t LPSPI_MasterSetDelayTimes(LPSPI_Type *base,
433                                    uint32_t delayTimeInNanoSec,
434                                    lpspi_delay_type_t whichDelay,
435                                    uint32_t srcClock_Hz)
436 {
437     uint64_t realDelay, bestDelay;
438     uint32_t scaler, bestScaler;
439     uint32_t diff, min_diff;
440     uint64_t initialDelayNanoSec;
441     uint32_t clockDividedPrescaler;
442 
443     /* For delay between transfer, an additional scaler value is needed */
444     uint32_t additionalScaler = 0;
445 
446     /*As the RM note, the LPSPI baud rate clock is itself divided by the PRESCALE setting, which can vary between
447      * transfers.*/
448     clockDividedPrescaler =
449         srcClock_Hz / s_baudratePrescaler[(base->TCR & LPSPI_TCR_PRESCALE_MASK) >> LPSPI_TCR_PRESCALE_SHIFT];
450 
451     /* Find combination of prescaler and scaler resulting in the delay closest to the requested value.*/
452     min_diff = 0xFFFFFFFFU;
453 
454     /* Initialize scaler to max value to generate the max delay */
455     bestScaler = 0xFFU;
456 
457     /* Calculate the initial (min) delay and maximum possible delay based on the specific delay as
458     * the delay divisors are slightly different based on which delay we are configuring.
459     */
460     if (whichDelay == kLPSPI_BetweenTransfer)
461     {
462         /* First calculate the initial, default delay, note min delay is 2 clock cycles. Due to large size of
463          calculated values (uint64_t), we need to break up the calculation into several steps to ensure
464          accurate calculated results
465          */
466         initialDelayNanoSec = 1000000000U;
467         initialDelayNanoSec *= 2U;
468         initialDelayNanoSec /= clockDividedPrescaler;
469 
470         /* Calculate the maximum delay */
471         bestDelay = 1000000000U;
472         bestDelay *= 257U; /* based on DBT+2, or 255 + 2 */
473         bestDelay /= clockDividedPrescaler;
474 
475         additionalScaler = 1U;
476     }
477     else
478     {
479         /* First calculate the initial, default delay, min delay is 1 clock cycle. Due to large size of calculated
480         values (uint64_t), we need to break up the calculation into several steps to ensure accurate calculated
481         results.
482         */
483         initialDelayNanoSec = 1000000000U;
484         initialDelayNanoSec /= clockDividedPrescaler;
485 
486         /* Calculate the maximum delay */
487         bestDelay = 1000000000U;
488         bestDelay *= 256U; /* based on SCKPCS+1 or PCSSCK+1, or 255 + 1 */
489         bestDelay /= clockDividedPrescaler;
490 
491         additionalScaler = 0;
492     }
493 
494     /* If the initial, default delay is already greater than the desired delay, then
495     * set the delay to their initial value (0) and return the delay. In other words,
496     * there is no way to decrease the delay value further.
497     */
498     if (initialDelayNanoSec >= delayTimeInNanoSec)
499     {
500         LPSPI_MasterSetDelayScaler(base, 0, whichDelay);
501         return initialDelayNanoSec;
502     }
503 
504     /* If min_diff = 0, the exit for loop */
505     for (scaler = 0; (scaler < 256U) && min_diff; scaler++)
506     {
507         /* Calculate the real delay value as we cycle through the scaler values.
508         Due to large size of calculated values (uint64_t), we need to break up the
509         calculation into several steps to ensure accurate calculated results
510         */
511         realDelay = 1000000000U;
512         realDelay *= (scaler + 1 + additionalScaler);
513         realDelay /= clockDividedPrescaler;
514 
515         /* calculate the delay difference based on the conditional statement
516         * that states that the calculated delay must not be less then the desired delay
517         */
518         if (realDelay >= delayTimeInNanoSec)
519         {
520             diff = realDelay - delayTimeInNanoSec;
521             if (min_diff > diff)
522             {
523                 /* a better match found */
524                 min_diff = diff;
525                 bestScaler = scaler;
526                 bestDelay = realDelay;
527             }
528         }
529     }
530 
531     /* write the best scaler value for the delay */
532     LPSPI_MasterSetDelayScaler(base, bestScaler, whichDelay);
533 
534     /* return the actual calculated delay value (in ns) */
535     return bestDelay;
536 }
537 
538 /*Transactional APIs -- Master*/
539 
LPSPI_MasterTransferCreateHandle(LPSPI_Type * base,lpspi_master_handle_t * handle,lpspi_master_transfer_callback_t callback,void * userData)540 void LPSPI_MasterTransferCreateHandle(LPSPI_Type *base,
541                                       lpspi_master_handle_t *handle,
542                                       lpspi_master_transfer_callback_t callback,
543                                       void *userData)
544 {
545     assert(handle);
546 
547     /* Zero the handle. */
548     memset(handle, 0, sizeof(*handle));
549 
550     s_lpspiHandle[LPSPI_GetInstance(base)] = handle;
551 
552     /* Set irq handler. */
553     s_lpspiMasterIsr = LPSPI_MasterTransferHandleIRQ;
554 
555     handle->callback = callback;
556     handle->userData = userData;
557 }
558 
LPSPI_CheckTransferArgument(lpspi_transfer_t * transfer,uint32_t bitsPerFrame,uint32_t bytesPerFrame)559 bool LPSPI_CheckTransferArgument(lpspi_transfer_t *transfer, uint32_t bitsPerFrame, uint32_t bytesPerFrame)
560 {
561     assert(transfer);
562 
563     /* If the transfer count is zero, then return immediately.*/
564     if (transfer->dataSize == 0)
565     {
566         return false;
567     }
568 
569     /* If both send buffer and receive buffer is null */
570     if ((!(transfer->txData)) && (!(transfer->rxData)))
571     {
572         return false;
573     }
574 
575     /*The transfer data size should be integer multiples of bytesPerFrame if bytesPerFrame is less than or equal to 4 .
576      *For bytesPerFrame greater than 4 situation:
577      *the transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not integer multiples of 4 ,
578      *otherwise , the transfer data size can be integer multiples of bytesPerFrame.
579      */
580     if (bytesPerFrame <= 4)
581     {
582         if ((transfer->dataSize % bytesPerFrame) != 0)
583         {
584             return false;
585         }
586     }
587     else
588     {
589         if ((bytesPerFrame % 4U) != 0)
590         {
591             if (transfer->dataSize != bytesPerFrame)
592             {
593                 return false;
594             }
595         }
596         else
597         {
598             if ((transfer->dataSize % bytesPerFrame) != 0)
599             {
600                 return false;
601             }
602         }
603     }
604 
605     return true;
606 }
607 
LPSPI_MasterTransferBlocking(LPSPI_Type * base,lpspi_transfer_t * transfer)608 status_t LPSPI_MasterTransferBlocking(LPSPI_Type *base, lpspi_transfer_t *transfer)
609 {
610     assert(transfer);
611 
612     uint32_t bitsPerFrame = ((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) + 1;
613     uint32_t bytesPerFrame = (bitsPerFrame + 7) / 8;
614     uint8_t dummyData = s_dummyData[LPSPI_GetInstance(base)];
615 
616     if (!LPSPI_CheckTransferArgument(transfer, bitsPerFrame, bytesPerFrame))
617     {
618         return kStatus_InvalidArgument;
619     }
620 
621     /* Check that LPSPI is not busy.*/
622     if (LPSPI_GetStatusFlags(base) & kLPSPI_ModuleBusyFlag)
623     {
624         return kStatus_LPSPI_Busy;
625     }
626 
627     uint8_t *txData = transfer->txData;
628     uint8_t *rxData = transfer->rxData;
629     uint32_t txRemainingByteCount = transfer->dataSize;
630     uint32_t rxRemainingByteCount = transfer->dataSize;
631 
632     uint8_t bytesEachWrite;
633     uint8_t bytesEachRead;
634 
635     uint32_t readData = 0;
636     uint32_t wordToSend =
637         ((uint32_t)dummyData) | ((uint32_t)dummyData << 8) | ((uint32_t)dummyData << 16) | ((uint32_t)dummyData << 24);
638 
639     /*The TX and RX FIFO sizes are always the same*/
640     uint32_t fifoSize = LPSPI_GetRxFifoSize(base);
641 
642     uint32_t whichPcs = (transfer->configFlags & LPSPI_MASTER_PCS_MASK) >> LPSPI_MASTER_PCS_SHIFT;
643 
644     bool isPcsContinuous = (bool)(transfer->configFlags & kLPSPI_MasterPcsContinuous);
645     bool isRxMask = false;
646     bool isByteSwap = (bool)(transfer->configFlags & kLPSPI_MasterByteSwap);
647 
648     LPSPI_FlushFifo(base, true, true);
649     LPSPI_ClearStatusFlags(base, kLPSPI_AllStatusFlag);
650 
651     if (!rxData)
652     {
653         isRxMask = true;
654     }
655 
656     LPSPI_Enable(base, false);
657     base->CFGR1 &= (~LPSPI_CFGR1_NOSTALL_MASK);
658     LPSPI_Enable(base, true);
659 
660     base->TCR =
661         (base->TCR & ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_RXMSK_MASK | LPSPI_TCR_PCS_MASK)) |
662         LPSPI_TCR_CONT(isPcsContinuous) | LPSPI_TCR_CONTC(0) | LPSPI_TCR_RXMSK(isRxMask) | LPSPI_TCR_PCS(whichPcs);
663 
664     if (bytesPerFrame <= 4)
665     {
666         bytesEachWrite = bytesPerFrame;
667         bytesEachRead = bytesPerFrame;
668     }
669     else
670     {
671         bytesEachWrite = 4;
672         bytesEachRead = 4;
673     }
674 
675     /*Write the TX data until txRemainingByteCount is equal to 0 */
676     while (txRemainingByteCount > 0)
677     {
678         if (txRemainingByteCount < bytesEachWrite)
679         {
680             bytesEachWrite = txRemainingByteCount;
681         }
682 
683         /*Wait until TX FIFO is not full*/
684         while (LPSPI_GetTxFifoCount(base) == fifoSize)
685         {
686         }
687 
688         if (txData)
689         {
690             wordToSend = LPSPI_CombineWriteData(txData, bytesEachWrite, isByteSwap);
691             txData += bytesEachWrite;
692         }
693 
694         LPSPI_WriteData(base, wordToSend);
695         txRemainingByteCount -= bytesEachWrite;
696 
697         /*Check whether there is RX data in RX FIFO . Read out the RX data so that the RX FIFO would not overrun.*/
698         if (rxData)
699         {
700             while (LPSPI_GetRxFifoCount(base))
701             {
702                 readData = LPSPI_ReadData(base);
703                 if (rxRemainingByteCount < bytesEachRead)
704                 {
705                     bytesEachRead = rxRemainingByteCount;
706                 }
707 
708                 LPSPI_SeparateReadData(rxData, readData, bytesEachRead, isByteSwap);
709                 rxData += bytesEachRead;
710 
711                 rxRemainingByteCount -= bytesEachRead;
712             }
713         }
714     }
715 
716     /* After write all the data in TX FIFO , should write the TCR_CONTC to 0 to de-assert the PCS. Note that TCR
717      * register also use the TX FIFO.
718      */
719     while ((LPSPI_GetTxFifoCount(base) == fifoSize))
720     {
721     }
722     base->TCR = (base->TCR & ~(LPSPI_TCR_CONTC_MASK));
723 
724     /*Read out the RX data in FIFO*/
725     if (rxData)
726     {
727         while (rxRemainingByteCount > 0)
728         {
729             while (LPSPI_GetRxFifoCount(base))
730             {
731                 readData = LPSPI_ReadData(base);
732 
733                 if (rxRemainingByteCount < bytesEachRead)
734                 {
735                     bytesEachRead = rxRemainingByteCount;
736                 }
737 
738                 LPSPI_SeparateReadData(rxData, readData, bytesEachRead, isByteSwap);
739                 rxData += bytesEachRead;
740 
741                 rxRemainingByteCount -= bytesEachRead;
742             }
743         }
744     }
745     else
746     {
747         /* If no RX buffer, then transfer is not complete until transfer complete flag sets */
748         while (!(LPSPI_GetStatusFlags(base) & kLPSPI_TransferCompleteFlag))
749         {
750         }
751     }
752 
753     return kStatus_Success;
754 }
755 
LPSPI_MasterTransferNonBlocking(LPSPI_Type * base,lpspi_master_handle_t * handle,lpspi_transfer_t * transfer)756 status_t LPSPI_MasterTransferNonBlocking(LPSPI_Type *base, lpspi_master_handle_t *handle, lpspi_transfer_t *transfer)
757 {
758     assert(handle);
759     assert(transfer);
760 
761     uint32_t bitsPerFrame = ((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) + 1;
762     uint32_t bytesPerFrame = (bitsPerFrame + 7) / 8;
763     uint8_t dummyData = s_dummyData[LPSPI_GetInstance(base)];
764 
765     if (!LPSPI_CheckTransferArgument(transfer, bitsPerFrame, bytesPerFrame))
766     {
767         return kStatus_InvalidArgument;
768     }
769 
770     /* Check that we're not busy.*/
771     if (handle->state == kLPSPI_Busy)
772     {
773         return kStatus_LPSPI_Busy;
774     }
775 
776     handle->state = kLPSPI_Busy;
777 
778     bool isRxMask = false;
779 
780     uint8_t txWatermark;
781 
782     uint32_t whichPcs = (transfer->configFlags & LPSPI_MASTER_PCS_MASK) >> LPSPI_MASTER_PCS_SHIFT;
783 
784     handle->txData = transfer->txData;
785     handle->rxData = transfer->rxData;
786     handle->txRemainingByteCount = transfer->dataSize;
787     handle->rxRemainingByteCount = transfer->dataSize;
788     handle->totalByteCount = transfer->dataSize;
789 
790     handle->writeTcrInIsr = false;
791 
792     handle->writeRegRemainingTimes = (transfer->dataSize / bytesPerFrame) * ((bytesPerFrame + 3) / 4);
793     handle->readRegRemainingTimes = handle->writeRegRemainingTimes;
794 
795     handle->txBuffIfNull =
796         ((uint32_t)dummyData) | ((uint32_t)dummyData << 8) | ((uint32_t)dummyData << 16) | ((uint32_t)dummyData << 24);
797 
798     /*The TX and RX FIFO sizes are always the same*/
799     handle->fifoSize = LPSPI_GetRxFifoSize(base);
800 
801     handle->isPcsContinuous = (bool)(transfer->configFlags & kLPSPI_MasterPcsContinuous);
802     handle->isByteSwap = (bool)(transfer->configFlags & kLPSPI_MasterByteSwap);
803 
804     /*Set the RX and TX watermarks to reduce the ISR times.*/
805     if (handle->fifoSize > 1)
806     {
807         txWatermark = 1;
808         handle->rxWatermark = handle->fifoSize - 2;
809     }
810     else
811     {
812         txWatermark = 0;
813         handle->rxWatermark = 0;
814     }
815 
816     LPSPI_SetFifoWatermarks(base, txWatermark, handle->rxWatermark);
817 
818     /*Transfers will stall when transmit FIFO is empty or receive FIFO is full. */
819     LPSPI_Enable(base, false);
820     base->CFGR1 &= (~LPSPI_CFGR1_NOSTALL_MASK);
821     LPSPI_Enable(base, true);
822 
823     /*Flush FIFO , clear status , disable all the inerrupts.*/
824     LPSPI_FlushFifo(base, true, true);
825     LPSPI_ClearStatusFlags(base, kLPSPI_AllStatusFlag);
826     LPSPI_DisableInterrupts(base, kLPSPI_AllInterruptEnable);
827 
828     /* If there is not rxData , can mask the receive data (receive data is not stored in receive FIFO).
829      * For master transfer , we'd better not masked the transmit data in TCR since the transfer flow is hard to
830      * controlled by software.*/
831     if (handle->rxData == NULL)
832     {
833         isRxMask = true;
834         handle->rxRemainingByteCount = 0;
835     }
836 
837     base->TCR =
838         (base->TCR & ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_RXMSK_MASK | LPSPI_TCR_PCS_MASK)) |
839         LPSPI_TCR_CONT(handle->isPcsContinuous) | LPSPI_TCR_CONTC(0) | LPSPI_TCR_RXMSK(isRxMask) |
840         LPSPI_TCR_PCS(whichPcs);
841 
842     /*Calculate the bytes for write/read the TX/RX register each time*/
843     if (bytesPerFrame <= 4)
844     {
845         handle->bytesEachWrite = bytesPerFrame;
846         handle->bytesEachRead = bytesPerFrame;
847     }
848     else
849     {
850         handle->bytesEachWrite = 4;
851         handle->bytesEachRead = 4;
852     }
853 
854     /* Enable the NVIC for LPSPI peripheral. Note that below code is useless if the LPSPI interrupt is in INTMUX ,
855      * and you should also enable the INTMUX interupt in your application.
856      */
857     EnableIRQ(s_lpspiIRQ[LPSPI_GetInstance(base)]);
858 
859     /*TCR is also shared the FIFO , so wait for TCR written.*/
860     while (LPSPI_GetTxFifoCount(base) != 0)
861     {
862     }
863     /*Fill up the TX data in FIFO */
864     LPSPI_MasterTransferFillUpTxFifo(base, handle);
865 
866     /* Since SPI is a synchronous interface, we only need to enable the RX interrupt if there is RX data.
867      * The IRQ handler will get the status of RX and TX interrupt flags.
868      */
869     if (handle->rxData)
870     {
871         /*Set rxWatermark to (readRegRemainingTimes-1) if readRegRemainingTimes less than rxWatermark. Otherwise there
872          *is not RX interrupt for the last datas because the RX count is not greater than rxWatermark.
873          */
874         if ((handle->readRegRemainingTimes) <= handle->rxWatermark)
875         {
876             base->FCR = (base->FCR & (~LPSPI_FCR_RXWATER_MASK)) | LPSPI_FCR_RXWATER(handle->readRegRemainingTimes - 1);
877         }
878 
879         LPSPI_EnableInterrupts(base, kLPSPI_RxInterruptEnable);
880     }
881     else
882     {
883         LPSPI_EnableInterrupts(base, kLPSPI_TxInterruptEnable);
884     }
885 
886     return kStatus_Success;
887 }
888 
LPSPI_MasterTransferFillUpTxFifo(LPSPI_Type * base,lpspi_master_handle_t * handle)889 static void LPSPI_MasterTransferFillUpTxFifo(LPSPI_Type *base, lpspi_master_handle_t *handle)
890 {
891     assert(handle);
892 
893     uint32_t wordToSend = 0;
894 
895     /* Make sure the difference in remaining TX and RX byte counts does not exceed FIFO depth
896     * and that the number of TX FIFO entries does not exceed the FIFO depth.
897     * But no need to make the protection if there is no rxData.
898     */
899     while ((LPSPI_GetTxFifoCount(base) < (handle->fifoSize)) &&
900            (((handle->readRegRemainingTimes - handle->writeRegRemainingTimes) < handle->fifoSize) ||
901             (handle->rxData == NULL)))
902     {
903         if (handle->txRemainingByteCount < handle->bytesEachWrite)
904         {
905             handle->bytesEachWrite = handle->txRemainingByteCount;
906         }
907 
908         if (handle->txData)
909         {
910             wordToSend = LPSPI_CombineWriteData(handle->txData, handle->bytesEachWrite, handle->isByteSwap);
911             handle->txData += handle->bytesEachWrite;
912         }
913         else
914         {
915             wordToSend = handle->txBuffIfNull;
916         }
917 
918         /*Write the word to TX register*/
919         LPSPI_WriteData(base, wordToSend);
920 
921         /*Decrease the write TX register times.*/
922         --handle->writeRegRemainingTimes;
923 
924         /*Decrease the remaining TX byte count.*/
925         handle->txRemainingByteCount -= handle->bytesEachWrite;
926 
927         if (handle->txRemainingByteCount == 0)
928         {
929             /* If PCS is continuous, update TCR to de-assert PCS */
930             if (handle->isPcsContinuous)
931             {
932                 /* Only write to the TCR if the FIFO has room */
933                 if ((LPSPI_GetTxFifoCount(base) < (handle->fifoSize)))
934                 {
935                     base->TCR = (base->TCR & ~(LPSPI_TCR_CONTC_MASK));
936                     handle->writeTcrInIsr = false;
937                 }
938                 /* Else, set a global flag to tell the ISR to do write to the TCR */
939                 else
940                 {
941                     handle->writeTcrInIsr = true;
942                 }
943             }
944             break;
945         }
946     }
947 }
948 
LPSPI_MasterTransferComplete(LPSPI_Type * base,lpspi_master_handle_t * handle)949 static void LPSPI_MasterTransferComplete(LPSPI_Type *base, lpspi_master_handle_t *handle)
950 {
951     assert(handle);
952 
953     /* Disable interrupt requests*/
954     LPSPI_DisableInterrupts(base, kLPSPI_AllInterruptEnable);
955 
956     handle->state = kLPSPI_Idle;
957 
958     if (handle->callback)
959     {
960         handle->callback(base, handle, kStatus_Success, handle->userData);
961     }
962 }
963 
LPSPI_MasterTransferGetCount(LPSPI_Type * base,lpspi_master_handle_t * handle,size_t * count)964 status_t LPSPI_MasterTransferGetCount(LPSPI_Type *base, lpspi_master_handle_t *handle, size_t *count)
965 {
966     assert(handle);
967 
968     if (!count)
969     {
970         return kStatus_InvalidArgument;
971     }
972 
973     /* Catch when there is not an active transfer. */
974     if (handle->state != kLPSPI_Busy)
975     {
976         *count = 0;
977         return kStatus_NoTransferInProgress;
978     }
979 
980     size_t remainingByte;
981 
982     if (handle->rxData)
983     {
984         remainingByte = handle->rxRemainingByteCount;
985     }
986     else
987     {
988         remainingByte = handle->txRemainingByteCount;
989     }
990 
991     *count = handle->totalByteCount - remainingByte;
992 
993     return kStatus_Success;
994 }
995 
LPSPI_MasterTransferAbort(LPSPI_Type * base,lpspi_master_handle_t * handle)996 void LPSPI_MasterTransferAbort(LPSPI_Type *base, lpspi_master_handle_t *handle)
997 {
998     assert(handle);
999 
1000     /* Disable interrupt requests*/
1001     LPSPI_DisableInterrupts(base, kLPSPI_AllInterruptEnable);
1002 
1003     LPSPI_Reset(base);
1004 
1005     handle->state = kLPSPI_Idle;
1006     handle->txRemainingByteCount = 0;
1007     handle->rxRemainingByteCount = 0;
1008 }
1009 
LPSPI_MasterTransferHandleIRQ(LPSPI_Type * base,lpspi_master_handle_t * handle)1010 void LPSPI_MasterTransferHandleIRQ(LPSPI_Type *base, lpspi_master_handle_t *handle)
1011 {
1012     assert(handle);
1013 
1014     uint32_t readData;
1015 
1016     if (handle->rxData != NULL)
1017     {
1018         if (handle->rxRemainingByteCount)
1019         {
1020             /* First, disable the interrupts to avoid potentially triggering another interrupt
1021             * while reading out the RX FIFO as more data may be coming into the RX FIFO. We'll
1022             * re-enable the interrupts based on the LPSPI state after reading out the FIFO.
1023             */
1024             LPSPI_DisableInterrupts(base, kLPSPI_RxInterruptEnable);
1025 
1026             while ((LPSPI_GetRxFifoCount(base)) && (handle->rxRemainingByteCount))
1027             {
1028                 /*Read out the data*/
1029                 readData = LPSPI_ReadData(base);
1030 
1031                 /*Decrease the read RX register times.*/
1032                 --handle->readRegRemainingTimes;
1033 
1034                 if (handle->rxRemainingByteCount < handle->bytesEachRead)
1035                 {
1036                     handle->bytesEachRead = handle->rxRemainingByteCount;
1037                 }
1038 
1039                 LPSPI_SeparateReadData(handle->rxData, readData, handle->bytesEachRead, handle->isByteSwap);
1040                 handle->rxData += handle->bytesEachRead;
1041 
1042                 /*Decrease the remaining RX byte count.*/
1043                 handle->rxRemainingByteCount -= handle->bytesEachRead;
1044             }
1045 
1046             /* Re-enable the interrupts only if rxCount indicates there is more data to receive,
1047             * else we may get a spurious interrupt.
1048             * */
1049             if (handle->rxRemainingByteCount)
1050             {
1051                 /* Set the TDF and RDF interrupt enables simultaneously to avoid race conditions */
1052                 LPSPI_EnableInterrupts(base, kLPSPI_RxInterruptEnable);
1053             }
1054         }
1055 
1056         /*Set rxWatermark to (readRegRemainingTimes-1) if readRegRemainingTimes less than rxWatermark. Otherwise there
1057          *is not RX interrupt for the last datas because the RX count is not greater than rxWatermark.
1058          */
1059         if ((handle->readRegRemainingTimes) <= (handle->rxWatermark))
1060         {
1061             base->FCR =
1062                 (base->FCR & (~LPSPI_FCR_RXWATER_MASK)) |
1063                 LPSPI_FCR_RXWATER((handle->readRegRemainingTimes > 1) ? (handle->readRegRemainingTimes - 1U) : (0U));
1064         }
1065     }
1066 
1067     if (handle->txRemainingByteCount)
1068     {
1069         LPSPI_MasterTransferFillUpTxFifo(base, handle);
1070     }
1071     else
1072     {
1073         if ((LPSPI_GetTxFifoCount(base) < (handle->fifoSize)))
1074         {
1075             if ((handle->isPcsContinuous) && (handle->writeTcrInIsr))
1076             {
1077                 base->TCR = (base->TCR & ~(LPSPI_TCR_CONTC_MASK));
1078                 handle->writeTcrInIsr = false;
1079             }
1080         }
1081     }
1082 
1083     if ((handle->txRemainingByteCount == 0) && (handle->rxRemainingByteCount == 0) && (!handle->writeTcrInIsr))
1084     {
1085         /* If no RX buffer, then transfer is not complete until transfer complete flag sets */
1086         if (handle->rxData == NULL)
1087         {
1088             if (LPSPI_GetStatusFlags(base) & kLPSPI_TransferCompleteFlag)
1089             {
1090                 /* Complete the transfer and disable the interrupts */
1091                 LPSPI_MasterTransferComplete(base, handle);
1092             }
1093             else
1094             {
1095                 LPSPI_EnableInterrupts(base, kLPSPI_TransferCompleteInterruptEnable);
1096                 LPSPI_DisableInterrupts(base, kLPSPI_TxInterruptEnable | kLPSPI_RxInterruptEnable);
1097             }
1098         }
1099         else
1100         {
1101             /* Complete the transfer and disable the interrupts */
1102             LPSPI_MasterTransferComplete(base, handle);
1103         }
1104     }
1105 }
1106 
1107 /*Transactional APIs -- Slave*/
LPSPI_SlaveTransferCreateHandle(LPSPI_Type * base,lpspi_slave_handle_t * handle,lpspi_slave_transfer_callback_t callback,void * userData)1108 void LPSPI_SlaveTransferCreateHandle(LPSPI_Type *base,
1109                                      lpspi_slave_handle_t *handle,
1110                                      lpspi_slave_transfer_callback_t callback,
1111                                      void *userData)
1112 {
1113     assert(handle);
1114 
1115     /* Zero the handle. */
1116     memset(handle, 0, sizeof(*handle));
1117 
1118     s_lpspiHandle[LPSPI_GetInstance(base)] = handle;
1119 
1120     /* Set irq handler. */
1121     s_lpspiSlaveIsr = LPSPI_SlaveTransferHandleIRQ;
1122 
1123     handle->callback = callback;
1124     handle->userData = userData;
1125 }
1126 
LPSPI_SlaveTransferNonBlocking(LPSPI_Type * base,lpspi_slave_handle_t * handle,lpspi_transfer_t * transfer)1127 status_t LPSPI_SlaveTransferNonBlocking(LPSPI_Type *base, lpspi_slave_handle_t *handle, lpspi_transfer_t *transfer)
1128 {
1129     assert(handle);
1130     assert(transfer);
1131 
1132     uint32_t bitsPerFrame = ((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) + 1;
1133     uint32_t bytesPerFrame = (bitsPerFrame + 7) / 8;
1134 
1135     if (!LPSPI_CheckTransferArgument(transfer, bitsPerFrame, bytesPerFrame))
1136     {
1137         return kStatus_InvalidArgument;
1138     }
1139 
1140     /* Check that we're not busy.*/
1141     if (handle->state == kLPSPI_Busy)
1142     {
1143         return kStatus_LPSPI_Busy;
1144     }
1145     handle->state = kLPSPI_Busy;
1146 
1147     bool isRxMask = false;
1148     bool isTxMask = false;
1149 
1150     uint32_t whichPcs = (transfer->configFlags & LPSPI_SLAVE_PCS_MASK) >> LPSPI_SLAVE_PCS_SHIFT;
1151 
1152     handle->txData = transfer->txData;
1153     handle->rxData = transfer->rxData;
1154     handle->txRemainingByteCount = transfer->dataSize;
1155     handle->rxRemainingByteCount = transfer->dataSize;
1156     handle->totalByteCount = transfer->dataSize;
1157 
1158     handle->writeRegRemainingTimes = (transfer->dataSize / bytesPerFrame) * ((bytesPerFrame + 3) / 4);
1159     handle->readRegRemainingTimes = handle->writeRegRemainingTimes;
1160 
1161     /*The TX and RX FIFO sizes are always the same*/
1162     handle->fifoSize = LPSPI_GetRxFifoSize(base);
1163 
1164     handle->isByteSwap = (bool)(transfer->configFlags & kLPSPI_SlaveByteSwap);
1165 
1166     /*Set the RX and TX watermarks to reduce the ISR times.*/
1167     uint8_t txWatermark;
1168     if (handle->fifoSize > 1)
1169     {
1170         txWatermark = 1;
1171         handle->rxWatermark = handle->fifoSize - 2;
1172     }
1173     else
1174     {
1175         txWatermark = 0;
1176         handle->rxWatermark = 0;
1177     }
1178     LPSPI_SetFifoWatermarks(base, txWatermark, handle->rxWatermark);
1179 
1180     /*Flush FIFO , clear status , disable all the inerrupts.*/
1181     LPSPI_FlushFifo(base, true, true);
1182     LPSPI_ClearStatusFlags(base, kLPSPI_AllStatusFlag);
1183     LPSPI_DisableInterrupts(base, kLPSPI_AllInterruptEnable);
1184 
1185     /*If there is not rxData , can mask the receive data (receive data is not stored in receive FIFO).*/
1186     if (handle->rxData == NULL)
1187     {
1188         isRxMask = true;
1189         handle->rxRemainingByteCount = 0;
1190     }
1191 
1192     /*If there is not txData , can mask the transmit data (no data is loaded from transmit FIFO and output pin
1193      * is tristated).
1194      */
1195     if (handle->txData == NULL)
1196     {
1197         isTxMask = true;
1198         handle->txRemainingByteCount = 0;
1199     }
1200 
1201     base->TCR = (base->TCR &
1202                  ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_RXMSK_MASK | LPSPI_TCR_TXMSK_MASK |
1203                    LPSPI_TCR_PCS_MASK)) |
1204                 LPSPI_TCR_CONT(0) | LPSPI_TCR_CONTC(0) | LPSPI_TCR_RXMSK(isRxMask) | LPSPI_TCR_TXMSK(isTxMask) |
1205                 LPSPI_TCR_PCS(whichPcs);
1206 
1207     /*Calculate the bytes for write/read the TX/RX register each time*/
1208     if (bytesPerFrame <= 4)
1209     {
1210         handle->bytesEachWrite = bytesPerFrame;
1211         handle->bytesEachRead = bytesPerFrame;
1212     }
1213     else
1214     {
1215         handle->bytesEachWrite = 4;
1216         handle->bytesEachRead = 4;
1217     }
1218 
1219     /* Enable the NVIC for LPSPI peripheral. Note that below code is useless if the LPSPI interrupt is in INTMUX ,
1220      * and you should also enable the INTMUX interupt in your application.
1221      */
1222     EnableIRQ(s_lpspiIRQ[LPSPI_GetInstance(base)]);
1223 
1224     /*TCR is also shared the FIFO , so wait for TCR written.*/
1225     while (LPSPI_GetTxFifoCount(base) != 0)
1226     {
1227     }
1228 
1229     /*Fill up the TX data in FIFO */
1230     if (handle->txData)
1231     {
1232         LPSPI_SlaveTransferFillUpTxFifo(base, handle);
1233     }
1234 
1235     /* Since SPI is a synchronous interface, we only need to enable the RX interrupt if there is RX data.
1236      * The IRQ handler will get the status of RX and TX interrupt flags.
1237      */
1238     if (handle->rxData)
1239     {
1240         /*Set rxWatermark to (readRegRemainingTimes-1) if readRegRemainingTimes less than rxWatermark. Otherwise there
1241          *is not RX interrupt for the last datas because the RX count is not greater than rxWatermark.
1242          */
1243         if ((handle->readRegRemainingTimes) <= handle->rxWatermark)
1244         {
1245             base->FCR = (base->FCR & (~LPSPI_FCR_RXWATER_MASK)) | LPSPI_FCR_RXWATER(handle->readRegRemainingTimes - 1);
1246         }
1247 
1248         LPSPI_EnableInterrupts(base, kLPSPI_RxInterruptEnable);
1249     }
1250     else
1251     {
1252         LPSPI_EnableInterrupts(base, kLPSPI_TxInterruptEnable);
1253     }
1254 
1255     if (handle->rxData)
1256     {
1257         /* RX FIFO overflow request enable */
1258         LPSPI_EnableInterrupts(base, kLPSPI_ReceiveErrorInterruptEnable);
1259     }
1260     if (handle->txData)
1261     {
1262         /* TX FIFO underflow request enable */
1263         LPSPI_EnableInterrupts(base, kLPSPI_TransmitErrorInterruptEnable);
1264     }
1265 
1266     return kStatus_Success;
1267 }
1268 
LPSPI_SlaveTransferFillUpTxFifo(LPSPI_Type * base,lpspi_slave_handle_t * handle)1269 static void LPSPI_SlaveTransferFillUpTxFifo(LPSPI_Type *base, lpspi_slave_handle_t *handle)
1270 {
1271     assert(handle);
1272 
1273     uint32_t wordToSend = 0;
1274 
1275     while (LPSPI_GetTxFifoCount(base) < (handle->fifoSize))
1276     {
1277         if (handle->txRemainingByteCount < handle->bytesEachWrite)
1278         {
1279             handle->bytesEachWrite = handle->txRemainingByteCount;
1280         }
1281 
1282         wordToSend = LPSPI_CombineWriteData(handle->txData, handle->bytesEachWrite, handle->isByteSwap);
1283         handle->txData += handle->bytesEachWrite;
1284 
1285         /*Decrease the remaining TX byte count.*/
1286         handle->txRemainingByteCount -= handle->bytesEachWrite;
1287 
1288         /*Write the word to TX register*/
1289         LPSPI_WriteData(base, wordToSend);
1290 
1291         if (handle->txRemainingByteCount == 0)
1292         {
1293             break;
1294         }
1295     }
1296 }
1297 
LPSPI_SlaveTransferComplete(LPSPI_Type * base,lpspi_slave_handle_t * handle)1298 static void LPSPI_SlaveTransferComplete(LPSPI_Type *base, lpspi_slave_handle_t *handle)
1299 {
1300     assert(handle);
1301 
1302     status_t status = 0;
1303 
1304     /* Disable interrupt requests*/
1305     LPSPI_DisableInterrupts(base, kLPSPI_AllInterruptEnable);
1306 
1307     if (handle->state == kLPSPI_Error)
1308     {
1309         status = kStatus_LPSPI_Error;
1310     }
1311     else
1312     {
1313         status = kStatus_Success;
1314     }
1315 
1316     handle->state = kLPSPI_Idle;
1317 
1318     if (handle->callback)
1319     {
1320         handle->callback(base, handle, status, handle->userData);
1321     }
1322 }
1323 
LPSPI_SlaveTransferGetCount(LPSPI_Type * base,lpspi_slave_handle_t * handle,size_t * count)1324 status_t LPSPI_SlaveTransferGetCount(LPSPI_Type *base, lpspi_slave_handle_t *handle, size_t *count)
1325 {
1326     assert(handle);
1327 
1328     if (!count)
1329     {
1330         return kStatus_InvalidArgument;
1331     }
1332 
1333     /* Catch when there is not an active transfer. */
1334     if (handle->state != kLPSPI_Busy)
1335     {
1336         *count = 0;
1337         return kStatus_NoTransferInProgress;
1338     }
1339 
1340     size_t remainingByte;
1341 
1342     if (handle->rxData)
1343     {
1344         remainingByte = handle->rxRemainingByteCount;
1345     }
1346     else
1347     {
1348         remainingByte = handle->txRemainingByteCount;
1349     }
1350 
1351     *count = handle->totalByteCount - remainingByte;
1352 
1353     return kStatus_Success;
1354 }
1355 
LPSPI_SlaveTransferAbort(LPSPI_Type * base,lpspi_slave_handle_t * handle)1356 void LPSPI_SlaveTransferAbort(LPSPI_Type *base, lpspi_slave_handle_t *handle)
1357 {
1358     assert(handle);
1359 
1360     /* Disable interrupt requests*/
1361     LPSPI_DisableInterrupts(base, kLPSPI_TxInterruptEnable | kLPSPI_RxInterruptEnable);
1362 
1363     LPSPI_Reset(base);
1364 
1365     handle->state = kLPSPI_Idle;
1366     handle->txRemainingByteCount = 0;
1367     handle->rxRemainingByteCount = 0;
1368 }
1369 
LPSPI_SlaveTransferHandleIRQ(LPSPI_Type * base,lpspi_slave_handle_t * handle)1370 void LPSPI_SlaveTransferHandleIRQ(LPSPI_Type *base, lpspi_slave_handle_t *handle)
1371 {
1372     assert(handle);
1373 
1374     uint32_t readData;   /* variable to store word read from RX FIFO */
1375     uint32_t wordToSend; /* variable to store word to write to TX FIFO */
1376 
1377     if (handle->rxData != NULL)
1378     {
1379         if (handle->rxRemainingByteCount > 0)
1380         {
1381             while (LPSPI_GetRxFifoCount(base))
1382             {
1383                 /*Read out the data*/
1384                 readData = LPSPI_ReadData(base);
1385 
1386                 /*Decrease the read RX register times.*/
1387                 --handle->readRegRemainingTimes;
1388 
1389                 if (handle->rxRemainingByteCount < handle->bytesEachRead)
1390                 {
1391                     handle->bytesEachRead = handle->rxRemainingByteCount;
1392                 }
1393 
1394                 LPSPI_SeparateReadData(handle->rxData, readData, handle->bytesEachRead, handle->isByteSwap);
1395                 handle->rxData += handle->bytesEachRead;
1396 
1397                 /*Decrease the remaining RX byte count.*/
1398                 handle->rxRemainingByteCount -= handle->bytesEachRead;
1399 
1400                 if ((handle->txRemainingByteCount > 0) && (handle->txData != NULL))
1401                 {
1402                     if (handle->txRemainingByteCount < handle->bytesEachWrite)
1403                     {
1404                         handle->bytesEachWrite = handle->txRemainingByteCount;
1405                     }
1406 
1407                     wordToSend = LPSPI_CombineWriteData(handle->txData, handle->bytesEachWrite, handle->isByteSwap);
1408                     handle->txData += handle->bytesEachWrite;
1409 
1410                     /*Decrease the remaining TX byte count.*/
1411                     handle->txRemainingByteCount -= handle->bytesEachWrite;
1412 
1413                     /*Write the word to TX register*/
1414                     LPSPI_WriteData(base, wordToSend);
1415                 }
1416 
1417                 if (handle->rxRemainingByteCount == 0)
1418                 {
1419                     break;
1420                 }
1421             }
1422         }
1423 
1424         /*Set rxWatermark to (readRegRemainingTimes-1) if readRegRemainingTimes less than rxWatermark. Otherwise there
1425          *is not RX interrupt for the last datas because the RX count is not greater than rxWatermark.
1426          */
1427         if ((handle->readRegRemainingTimes) <= (handle->rxWatermark))
1428         {
1429             base->FCR =
1430                 (base->FCR & (~LPSPI_FCR_RXWATER_MASK)) |
1431                 LPSPI_FCR_RXWATER((handle->readRegRemainingTimes > 1) ? (handle->readRegRemainingTimes - 1U) : (0U));
1432         }
1433     }
1434     else if ((handle->txRemainingByteCount) && (handle->txData != NULL))
1435     {
1436         LPSPI_SlaveTransferFillUpTxFifo(base, handle);
1437     }
1438     else
1439     {
1440         __NOP();
1441     }
1442 
1443     if ((handle->txRemainingByteCount == 0) && (handle->rxRemainingByteCount == 0))
1444     {
1445         /* If no RX buffer, then transfer is not complete until transfer complete flag sets and the TX FIFO empty*/
1446         if (handle->rxData == NULL)
1447         {
1448             if ((LPSPI_GetStatusFlags(base) & kLPSPI_FrameCompleteFlag) && (LPSPI_GetTxFifoCount(base) == 0))
1449             {
1450                 /* Complete the transfer and disable the interrupts */
1451                 LPSPI_SlaveTransferComplete(base, handle);
1452             }
1453             else
1454             {
1455                 LPSPI_ClearStatusFlags(base, kLPSPI_FrameCompleteFlag);
1456                 LPSPI_EnableInterrupts(base, kLPSPI_FrameCompleteInterruptEnable);
1457                 LPSPI_DisableInterrupts(base, kLPSPI_TxInterruptEnable | kLPSPI_RxInterruptEnable);
1458             }
1459         }
1460         else
1461         {
1462             /* Complete the transfer and disable the interrupts */
1463             LPSPI_SlaveTransferComplete(base, handle);
1464         }
1465     }
1466 
1467     /* Catch tx fifo underflow conditions, service only if tx under flow interrupt enabled */
1468     if ((LPSPI_GetStatusFlags(base) & kLPSPI_TransmitErrorFlag) && (base->IER & LPSPI_IER_TEIE_MASK))
1469     {
1470         LPSPI_ClearStatusFlags(base, kLPSPI_TransmitErrorFlag);
1471         /* Change state to error and clear flag */
1472         if (handle->txData)
1473         {
1474             handle->state = kLPSPI_Error;
1475         }
1476         handle->errorCount++;
1477     }
1478     /* Catch rx fifo overflow conditions, service only if rx over flow interrupt enabled */
1479     if ((LPSPI_GetStatusFlags(base) & kLPSPI_ReceiveErrorFlag) && (base->IER & LPSPI_IER_REIE_MASK))
1480     {
1481         LPSPI_ClearStatusFlags(base, kLPSPI_ReceiveErrorFlag);
1482         /* Change state to error and clear flag */
1483         if (handle->txData)
1484         {
1485             handle->state = kLPSPI_Error;
1486         }
1487         handle->errorCount++;
1488     }
1489 }
1490 
LPSPI_CombineWriteData(uint8_t * txData,uint32_t bytesEachWrite,bool isByteSwap)1491 static uint32_t LPSPI_CombineWriteData(uint8_t *txData, uint32_t bytesEachWrite, bool isByteSwap)
1492 {
1493     assert(txData);
1494 
1495     uint32_t wordToSend = 0;
1496 
1497     switch (bytesEachWrite)
1498     {
1499         case 1:
1500             wordToSend = *txData;
1501             ++txData;
1502             break;
1503 
1504         case 2:
1505             if (!isByteSwap)
1506             {
1507                 wordToSend = *txData;
1508                 ++txData;
1509                 wordToSend |= (unsigned)(*txData) << 8U;
1510                 ++txData;
1511             }
1512             else
1513             {
1514                 wordToSend = (unsigned)(*txData) << 8U;
1515                 ++txData;
1516                 wordToSend |= *txData;
1517                 ++txData;
1518             }
1519 
1520             break;
1521 
1522         case 3:
1523             if (!isByteSwap)
1524             {
1525                 wordToSend = *txData;
1526                 ++txData;
1527                 wordToSend |= (unsigned)(*txData) << 8U;
1528                 ++txData;
1529                 wordToSend |= (unsigned)(*txData) << 16U;
1530                 ++txData;
1531             }
1532             else
1533             {
1534                 wordToSend = (unsigned)(*txData) << 16U;
1535                 ++txData;
1536                 wordToSend |= (unsigned)(*txData) << 8U;
1537                 ++txData;
1538                 wordToSend |= *txData;
1539                 ++txData;
1540             }
1541             break;
1542 
1543         case 4:
1544             if (!isByteSwap)
1545             {
1546                 wordToSend = *txData;
1547                 ++txData;
1548                 wordToSend |= (unsigned)(*txData) << 8U;
1549                 ++txData;
1550                 wordToSend |= (unsigned)(*txData) << 16U;
1551                 ++txData;
1552                 wordToSend |= (unsigned)(*txData) << 24U;
1553                 ++txData;
1554             }
1555             else
1556             {
1557                 wordToSend = (unsigned)(*txData) << 24U;
1558                 ++txData;
1559                 wordToSend |= (unsigned)(*txData) << 16U;
1560                 ++txData;
1561                 wordToSend |= (unsigned)(*txData) << 8U;
1562                 ++txData;
1563                 wordToSend |= *txData;
1564                 ++txData;
1565             }
1566             break;
1567 
1568         default:
1569             assert(false);
1570             break;
1571     }
1572     return wordToSend;
1573 }
1574 
LPSPI_SeparateReadData(uint8_t * rxData,uint32_t readData,uint32_t bytesEachRead,bool isByteSwap)1575 static void LPSPI_SeparateReadData(uint8_t *rxData, uint32_t readData, uint32_t bytesEachRead, bool isByteSwap)
1576 {
1577     assert(rxData);
1578 
1579     switch (bytesEachRead)
1580     {
1581         case 1:
1582             *rxData = readData;
1583             ++rxData;
1584             break;
1585 
1586         case 2:
1587             if (!isByteSwap)
1588             {
1589                 *rxData = readData;
1590                 ++rxData;
1591                 *rxData = readData >> 8;
1592                 ++rxData;
1593             }
1594             else
1595             {
1596                 *rxData = readData >> 8;
1597                 ++rxData;
1598                 *rxData = readData;
1599                 ++rxData;
1600             }
1601             break;
1602 
1603         case 3:
1604             if (!isByteSwap)
1605             {
1606                 *rxData = readData;
1607                 ++rxData;
1608                 *rxData = readData >> 8;
1609                 ++rxData;
1610                 *rxData = readData >> 16;
1611                 ++rxData;
1612             }
1613             else
1614             {
1615                 *rxData = readData >> 16;
1616                 ++rxData;
1617                 *rxData = readData >> 8;
1618                 ++rxData;
1619                 *rxData = readData;
1620                 ++rxData;
1621             }
1622             break;
1623 
1624         case 4:
1625             if (!isByteSwap)
1626             {
1627                 *rxData = readData;
1628                 ++rxData;
1629                 *rxData = readData >> 8;
1630                 ++rxData;
1631                 *rxData = readData >> 16;
1632                 ++rxData;
1633                 *rxData = readData >> 24;
1634                 ++rxData;
1635             }
1636             else
1637             {
1638                 *rxData = readData >> 24;
1639                 ++rxData;
1640                 *rxData = readData >> 16;
1641                 ++rxData;
1642                 *rxData = readData >> 8;
1643                 ++rxData;
1644                 *rxData = readData;
1645                 ++rxData;
1646             }
1647             break;
1648 
1649         default:
1650             assert(false);
1651             break;
1652     }
1653 }
1654 
LPSPI_CommonIRQHandler(LPSPI_Type * base,void * param)1655 static void LPSPI_CommonIRQHandler(LPSPI_Type *base, void *param)
1656 {
1657     if (LPSPI_IsMaster(base))
1658     {
1659         s_lpspiMasterIsr(base, (lpspi_master_handle_t *)param);
1660     }
1661     else
1662     {
1663         s_lpspiSlaveIsr(base, (lpspi_slave_handle_t *)param);
1664     }
1665 }
1666 
1667 #if defined(LPSPI0)
LPSPI0_DriverIRQHandler(void)1668 void LPSPI0_DriverIRQHandler(void)
1669 {
1670     assert(s_lpspiHandle[0]);
1671     LPSPI_CommonIRQHandler(LPSPI0, s_lpspiHandle[0]);
1672 }
1673 #endif
1674 
1675 #if defined(LPSPI1)
LPSPI1_DriverIRQHandler(void)1676 void LPSPI1_DriverIRQHandler(void)
1677 {
1678     assert(s_lpspiHandle[1]);
1679     LPSPI_CommonIRQHandler(LPSPI1, s_lpspiHandle[1]);
1680 }
1681 #endif
1682 
1683 #if defined(LPSPI2)
LPSPI2_DriverIRQHandler(void)1684 void LPSPI2_DriverIRQHandler(void)
1685 {
1686     assert(s_lpspiHandle[2]);
1687     LPSPI_CommonIRQHandler(LPSPI2, s_lpspiHandle[2]);
1688 }
1689 #endif
1690 
1691 #if defined(LPSPI3)
LPSPI3_DriverIRQHandler(void)1692 void LPSPI3_DriverIRQHandler(void)
1693 {
1694     assert(s_lpspiHandle[3]);
1695     LPSPI_CommonIRQHandler(LPSPI3, s_lpspiHandle[3]);
1696 }
1697 #endif
1698 
1699 #if defined(LPSPI4)
LPSPI4_DriverIRQHandler(void)1700 void LPSPI4_DriverIRQHandler(void)
1701 {
1702     assert(s_lpspiHandle[4]);
1703     LPSPI_CommonIRQHandler(LPSPI4, s_lpspiHandle[4]);
1704 }
1705 #endif
1706 
1707 #if defined(LPSPI5)
LPSPI5_DriverIRQHandler(void)1708 void LPSPI5_DriverIRQHandler(void)
1709 {
1710     assert(s_lpspiHandle[5]);
1711     LPSPI_CommonIRQHandler(LPSPI5, s_lpspiHandle[5]);
1712 }
1713 #endif
1714 
1715 #if defined(DMA_LPSPI0)
DMA_SPI0_INT_IRQHandler(void)1716 void DMA_SPI0_INT_IRQHandler(void)
1717 {
1718     assert(s_lpspiHandle[0]);
1719     LPSPI_CommonIRQHandler(DMA_LPSPI0, s_lpspiHandle[0]);
1720 }
1721 #endif
1722 
1723 #if defined(DMA_LPSPI1)
DMA_SPI1_INT_IRQHandler(void)1724 void DMA_SPI1_INT_IRQHandler(void)
1725 {
1726     assert(s_lpspiHandle[1]);
1727     LPSPI_CommonIRQHandler(DMA_LPSPI1, s_lpspiHandle[1]);
1728 }
1729 #endif
1730 #if defined(DMA_LPSPI2)
DMA_SPI2_INT_IRQHandler(void)1731 void DMA_SPI2_INT_IRQHandler(void)
1732 {
1733     assert(s_lpspiHandle[2]);
1734     LPSPI_CommonIRQHandler(DMA_LPSPI2, s_lpspiHandle[2]);
1735 }
1736 #endif
1737 
1738 #if defined(DMA_LPSPI3)
DMA_SPI3_INT_IRQHandler(void)1739 void DMA_SPI3_INT_IRQHandler(void)
1740 {
1741     assert(s_lpspiHandle[3]);
1742     LPSPI_CommonIRQHandler(DMA_LPSPI3, s_lpspiHandle[3]);
1743 }
1744 #endif
1745