1 /*
2  * Copyright 2021-2022 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "fsl_smartcard_usim.h"
8 
9 /* Component ID definition, used by tools. */
10 #ifndef FSL_COMPONENT_ID
11 #define FSL_COMPONENT_ID "platform.drivers.smartcard_usim"
12 #endif
13 
14 /*******************************************************************************
15  * Variables
16  ******************************************************************************/
17 /*! @brief Pointers to usim bases for each instance. */
18 static USIM_Type *const s_usimBases[] = USIM_BASE_PTRS;
19 
20 /*! @brief Pointers to usim IRQ number for each instance. */
21 static const IRQn_Type s_usimIRQ[] = USIM_IRQS;
22 
23 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
24 /*! @brief Pointers to usim clocks for each instance. */
25 static const clock_ip_name_t s_usimClock[] = USIM_CLOCKS;
26 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
27 
28 #if !(defined(FSL_FEATURE_USIM_HAS_NO_RESET) && FSL_FEATURE_USIM_HAS_NO_RESET)
29 /*! @brief Pointers to usim resets for each instance. */
30 static const reset_ip_name_t s_usimResets[] = USIM_RSTS;
31 #endif
32 
33 /* #define CARDSIM_EXTRADELAY_USED */
34 
35 /*******************************************************************************
36  * Private Functions
37  ******************************************************************************/
38 static void SMARTCARD_USIM_CompleteSendData(USIM_Type *base, smartcard_context_t *context);
39 static void SMARTCARD_USIM_StartSendData(USIM_Type *base, smartcard_context_t *context);
40 static void SMARTCARD_USIM_CompleteReceiveData(USIM_Type *base, smartcard_context_t *context);
41 static void SMARTCARD_USIM_StartReceiveData(USIM_Type *base, smartcard_context_t *context);
42 static bool SMARTCARD_USIM_SetTransferType(USIM_Type *base, smartcard_context_t *context, smartcard_control_t control);
43 static void SMARTCARD_USIM_TimerInit(void);
44 static void SMARTCARD_USIM_TimerDeinit(void);
45 static void SMARTCARD_USIM_TimerStop(void);
46 static uint32_t SMARTCARD_USIM_GetInstance(USIM_Type *base);
47 
48 /*******************************************************************************
49  * Code
50  ******************************************************************************/
51 /*!
52  * @brief Get the USIM instance from peripheral base address.
53  *
54  * @param base USIM peripheral base address.
55  * @return USIM instance.
56  */
SMARTCARD_USIM_GetInstance(USIM_Type * base)57 static uint32_t SMARTCARD_USIM_GetInstance(USIM_Type *base)
58 {
59     uint8_t instance        = 0;
60     uint32_t usimArrayCount = (sizeof(s_usimBases) / sizeof(s_usimBases[0]));
61 
62     /* Find the instance index from base address mappings. */
63     for (instance = 0; instance < usimArrayCount; instance++)
64     {
65         if (s_usimBases[instance] == base)
66         {
67             break;
68         }
69     }
70 
71     assert(instance < usimArrayCount);
72 
73     return instance;
74 }
75 
76 /*!
77  * @brief Calculate FACTOR and DIVISOR value according to given Fi/Di.
78  *
79  * @param base The USIM peripheral base address.
80  * @param fi clock rate conversion integer.
81  * @param di baud rate divisor.
82  */
SMARTCARD_USIM_SetBaudRate(USIM_Type * base,uint32_t fi,uint32_t di)83 static bool SMARTCARD_USIM_SetBaudRate(USIM_Type *base, uint32_t fi, uint32_t di)
84 {
85     uint32_t clkDivisor = (base->CLKR & USIM_CLKR_DIVISOR_MASK) * 2UL * fi;
86     uint32_t facTmp, divTmp;
87 
88     for (facTmp = 6; facTmp < (uint32_t)USIM_FLR_FACTOR_MASK; facTmp++)
89     {
90         for (divTmp = 1; divTmp < (uint32_t)USIM_DLR_DIVISOR_MASK; divTmp++)
91         {
92             if (clkDivisor == (divTmp * facTmp * di))
93             {
94                 base->DLR = divTmp;
95                 base->FLR = facTmp - 1U;
96                 return true;
97             }
98             else if (clkDivisor < (divTmp * facTmp * di))
99             {
100                 return false;
101             }
102             else
103             {
104                 continue;
105             }
106         }
107     }
108     return false;
109 }
110 /*!
111  * @brief Finish up a transmit by completing the process of sending data and disabling the interrupt.
112  *
113  * @param base The USIM peripheral base address.
114  * @param context A pointer to a SMARTCARD driver context structure.
115  */
SMARTCARD_USIM_CompleteSendData(USIM_Type * base,smartcard_context_t * context)116 static void SMARTCARD_USIM_CompleteSendData(USIM_Type *base, smartcard_context_t *context)
117 {
118     assert((NULL != context));
119 
120     /* Disable TDR interrupt */
121     base->IER &= ~USIM_IER_TDR_MASK;
122 
123     /* Wait until Tx fifo empty */
124     while ((base->FSR & USIM_FSR_TX_LENGTH_MASK) != 0u)
125     {
126     }
127     /* Update the information of the module driver context */
128     context->xIsBusy       = false;
129     context->transferState = kSMARTCARD_IdleState;
130     /* Clear txSize to avoid any spurious transmit from ISR */
131     context->xSize = 0u;
132     /* Invoke user call-back */
133     if (NULL != context->transferCallback)
134     {
135         context->transferCallback(context, context->transferCallbackParam);
136     }
137 }
138 
139 /*!
140  * @brief Finish up a receive by completing the process of receiving data and disabling the interrupt.
141  *
142  * @param base The USIM peripheral base address.
143  * @param context A pointer to a SMARTCARD driver context structure.
144  */
SMARTCARD_USIM_CompleteReceiveData(USIM_Type * base,smartcard_context_t * context)145 static void SMARTCARD_USIM_CompleteReceiveData(USIM_Type *base, smartcard_context_t *context)
146 {
147     assert((NULL != context));
148 
149     /* Disable RDR interrupt */
150     base->IER &= ~USIM_IER_RDR_MASK;
151 
152     /* Read data from fifo */
153     while (((base->FSR & USIM_FSR_RX_LENGTH_MASK) != 0u) && ((context->xSize) > 0u))
154     {
155         /* Get data and put into receive buffer */
156         *context->xBuff = (uint8_t)(base->RBR);
157         ++context->xBuff;
158         --context->xSize;
159     }
160 
161     /* Update the information of the module driver context */
162     context->xIsBusy = false;
163     /* Invoke user call-back */
164     if (NULL != context->transferCallback)
165     {
166         context->transferCallback(context, context->transferCallbackParam);
167     }
168 }
169 
170 /*!
171  * @brief Initiate (start) a transmit by beginning the process of sending data and enabling the interrupt.
172  *
173  * @param base The USIM peripheral base address.
174  * @param context A pointer to a SMARTCARD driver context structure.
175  */
SMARTCARD_USIM_StartSendData(USIM_Type * base,smartcard_context_t * context)176 static void SMARTCARD_USIM_StartSendData(USIM_Type *base, smartcard_context_t *context)
177 {
178     assert((NULL != context));
179 
180     /* Update transferState */
181     context->transferState = kSMARTCARD_TransmittingState;
182     context->xIsBusy       = true;
183 
184     /* Reset transmitter FIFO */
185     base->FCR |= USIM_FCR_RESETTF_MASK;
186 
187     /* Clear transmitter hold bit. */
188     base->FCR &= ~USIM_FCR_TX_HOLD_MASK;
189 
190     /* Re-write DLR to restarts all waiting timers. */
191     base->DLR = base->DLR;
192 
193     /* Set transmitter data trigger level to 0 - TDR is set when the fifo is empty. */
194     base->FCR &= ~USIM_FCR_TX_TL_MASK;
195 
196     /* Enable TDR interrupt. */
197     base->IER |= USIM_IER_TDR_MASK;
198 }
199 
200 /*!
201  * @brief Initiate (start) a receive by beginning the process of receiving data and enabling the interrupt.
202  *
203  * @param base The USIM peripheral base address.
204  * @param context A pointer to a SMARTCARD driver context structure.
205  */
SMARTCARD_USIM_StartReceiveData(USIM_Type * base,smartcard_context_t * context)206 static void SMARTCARD_USIM_StartReceiveData(USIM_Type *base, smartcard_context_t *context)
207 {
208     assert((NULL != context));
209 
210     /* Initialize the module driver context structure to indicate transfer in progress. */
211     context->xIsBusy = true;
212 
213     /* Set rx trigger value - number of bytes that must exist in the Receive FIFO to trigger the receive data
214      * ready interrupt flag (RDR).*/
215     if (context->tType == kSMARTCARD_T0Transport)
216     {
217         if (context->xSize < context->rxFifoThreshold)
218         {
219             base->FCR = (base->FCR & ~USIM_FCR_RX_TL_MASK) | USIM_FIND_RX_FIFO_TRIGGER_LEVEL(context->xSize);
220         }
221         else
222         {
223             /* Set receiver Trigger level to max value. */
224             base->FCR |= USIM_FCR_RX_TL_MASK;
225         }
226     }
227     else
228     {
229         /* Enable interrupt when new byte is received - in T=1 is necessary to disable BWT interrupt and enable CWT
230          * interrupt after receiving the first byte */
231         base->FCR &= ~USIM_FCR_RX_TL_MASK;
232     }
233 
234     /* Enable RDR interrupt - count of bytes in rx fifo is equal or greater than Receiver Trigger Level */
235     base->IER |= USIM_IER_RDR_MASK;
236 }
237 
238 /*!
239  * @brief Sets up the USIM hardware for T=0 or T=1 protocol data exchange and initialize timer values.
240  *
241  * @param base The USIM peripheral base address.
242  * @param context A pointer to a SMARTCARD driver context structure.
243  */
SMARTCARD_USIM_SetTransferType(USIM_Type * base,smartcard_context_t * context,smartcard_control_t control)244 static bool SMARTCARD_USIM_SetTransferType(USIM_Type *base, smartcard_context_t *context, smartcard_control_t control)
245 {
246     assert((NULL != context));
247     assert((control == kSMARTCARD_SetupATRMode) || (control == kSMARTCARD_SetupT0Mode) ||
248            (control == kSMARTCARD_SetupT1Mode));
249 
250     uint16_t temp16 = 0u;
251     uint32_t bwiVal = 0u;
252 
253     if (control == kSMARTCARD_SetupATRMode)
254     {
255         /* Select T=0 protocol for transmitter and receiver. */
256         base->LCR &= ~(USIM_LCR_TX_T1_MASK | USIM_LCR_RX_T1_MASK);
257         /* Set default values as per EMV specification */
258         context->cardParams.Fi       = 372u;
259         context->cardParams.Di       = 1u;
260         context->cardParams.currentD = 1u;
261         context->cardParams.WI       = 0x0Au;
262         context->cardParams.GTN      = 0x00u;
263         /* Set default baudrate/ETU time based on EMV parameters */
264         if (!SMARTCARD_USIM_SetBaudRate(base, (uint32_t)context->cardParams.Fi, (uint32_t)context->cardParams.currentD))
265         {
266             return false;
267         }
268 
269         /* EMV expectation: WWT = (960 x D x WI) + (D x 480)
270          * USIM formula under T=0: CWTR[15:0] = WWT -12 */
271         temp16 = (960u * context->cardParams.currentD * context->cardParams.WI) + (context->cardParams.currentD * 480u);
272         base->CWTR = (uint32_t)temp16 - SMARTCARD_T0_CWT_ADJUSTMENT;
273         base->BWTR = (uint32_t)temp16 - SMARTCARD_T0_BWT_ADJUSTMENT;
274         /* Set Extended Guard Timer value
275          * EMV expectation: GT = (12 + GTN) etu or 12 etu
276          * USIM formula under T=0: EGTR[EGTM] = GT - 12*/
277         context->cardParams.GTN = (context->cardParams.GTN == 0xFFu) ? 0x00u : context->cardParams.GTN;
278         base->EGTR              = context->cardParams.GTN;
279         /* Setting Parity Error level and T0 error level so that an interrupt is generated when parity/T0 error
280          * reach threshold.  */
281         base->ECR = (base->ECR & ~(USIM_ECR_T0ERR_TL_MASK | USIM_ECR_PE_TL_MASK)) |
282                     USIM_ECR_T0ERR_TL(SMARTCARD_EMV_TX_NACK_THRESHOLD - 1UL) |
283                     USIM_ECR_PE_TL(SMARTCARD_EMV_RX_NACK_THRESHOLD - 1UL);
284         /* Clear all pending interrupts */
285         base->IIR = 0x37u;
286         /* Enable T0 Error and Parity Error interrupts to occur */
287         base->IER |= USIM_IER_T0ERR_MASK | USIM_IER_PERR_MASK;
288         /* Set transport type to T=0 in SMARTCARD context structure */
289         context->tType = kSMARTCARD_T0Transport;
290     }
291     else if (control == kSMARTCARD_SetupT0Mode)
292     {
293         /* Select T=0 protocol for transmitter and receiver. */
294         base->LCR &= ~(USIM_LCR_TX_T1_MASK | USIM_LCR_RX_T1_MASK);
295         /* EMV expectation: WWT = (960 x D x WI) + (D x 480)
296          * USIM formula under T=0: CWTR[15:0] = WWT -12 */
297         temp16 = (960u * context->cardParams.currentD * context->cardParams.WI) + (context->cardParams.currentD * 480u);
298         base->CWTR = (uint32_t)temp16 - SMARTCARD_T0_CWT_ADJUSTMENT;
299         base->BWTR = (uint32_t)temp16 - SMARTCARD_T0_BWT_ADJUSTMENT;
300         /* Set Extended Guard Timer value
301          * EMV expectation: GT = (12 + GTN) etu or 12 etu
302          * USIM formula under T=0: EGTR[EGTM] = GT - 12*/
303         context->cardParams.GTN = (context->cardParams.GTN == 0xFFu) ? 0x00u : context->cardParams.GTN;
304         base->EGTR              = context->cardParams.GTN;
305         /* Setting Parity Error level and T0 error level so that an interrupt is generated when parity/T0 error
306          * reach threshold.  */
307         base->ECR = (base->ECR & ~(USIM_ECR_T0ERR_TL_MASK | USIM_ECR_PE_TL_MASK)) |
308                     USIM_ECR_T0ERR_TL(SMARTCARD_EMV_TX_NACK_THRESHOLD - 1UL) |
309                     USIM_ECR_PE_TL(SMARTCARD_EMV_RX_NACK_THRESHOLD - 1UL);
310         /* Clear all pending interrupts */
311         base->IIR = 0x37u;
312         /* Enable T0 Error and Parity Error interrupts to occur */
313         base->IER |= USIM_IER_T0ERR_MASK | USIM_IER_PERR_MASK;
314         /* Set transport type to T=0 in SMARTCARD context structure */
315         context->tType = kSMARTCARD_T0Transport;
316     }
317     else
318     {
319         /* Select T=1 protocol for transmitter and receiver. */
320         base->LCR |= USIM_LCR_TX_T1_MASK | USIM_LCR_RX_T1_MASK;
321         /* Calculate and set Block Wait Timer (BWT) value
322          * EMV expectation: BWT = 11 + (2^BWI x 960 x D) + (D x 960) = 11 + (2^BWI + 1) x 960 x D
323          * USIM formula: BWTR[15:0] = BWT - 11 */
324         bwiVal     = 11u + ((((uint32_t)1u << context->cardParams.BWI) + 1u) * 960u * context->cardParams.currentD);
325         base->BWTR = bwiVal - SMARTCARD_T1_BWT_ADJUSTMENT;
326         /* Calculate and set Character Wait Timer (CWT) value
327          * EMV expectation: CWT = ((2^CWI + 11) + 4)
328          * USIM formula: CWTR[15:0] = CWT -11 */
329         temp16     = ((uint16_t)1u << context->cardParams.CWI) + 15u;
330         base->CWTR = (uint32_t)temp16 - SMARTCARD_T1_CWT_ADJUSTMENT;
331         /* EMV expectation: BGT = 22
332          * USIM formula: BGTR = BGT - 11 */
333         context->cardParams.BGI = 22u;
334         base->BGTR              = (uint32_t)context->cardParams.BGI - 11U;
335         /* Set Extended Guard Timer value
336          * EMV expectation: GT = (12 + GTN) etu or 11 etu
337          * USIM formula under T=0: EGTR[EGTM] = GT - 11*/
338         context->cardParams.GTN = (context->cardParams.GTN == 0xFFu) ? 0x00u : (context->cardParams.GTN + 1U);
339         base->EGTR              = context->cardParams.GTN;
340         /* Clear all pending interrupts */
341         base->IIR = 0x37u;
342         /* Enable Framing Error interrupts to occur */
343         base->IER |= USIM_IER_FRAMERR_MASK;
344         /* Set transport type to T=1 in SMARTCARD context structure */
345         context->tType = kSMARTCARD_T1Transport;
346     }
347     return true;
348 }
349 
350 #if defined(FSL_FEATURE_SOC_CTIMER_COUNT) && (FSL_FEATURE_SOC_CTIMER_COUNT)
351 /*!
352  * @brief Function un-gates peripheral clock of CTIMER0.
353  */
SMARTCARD_USIM_TimerInit(void)354 static void SMARTCARD_USIM_TimerInit(void)
355 {
356 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
357     /* Un-gate the CTIMER timer clock*/
358     CLOCK_EnableClock(kCLOCK_Ct32b0);
359 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
360 #if !(defined(FSL_SDK_DISABLE_DRIVER_RESET_CONTROL) && FSL_SDK_DISABLE_DRIVER_RESET_CONTROL)
361     /* Reset the module. */
362 #if !(defined(FSL_FEATURE_CTIMER_HAS_NO_RESET) && (FSL_FEATURE_CTIMER_HAS_NO_RESET))
363     RESET_PeripheralReset(kCT32B0_RST_SHIFT_RSTn);
364 #endif
365 #endif /* FSL_SDK_DISABLE_DRIVER_RESET_CONTROL */
366     /* Setup the cimer mode */
367     CTIMER0->CTCR = 0U;
368     /* Setup the timer prescale value */
369     CTIMER0->PR = 0U;
370     /* Stop timer */
371     CTIMER0->TCR &= ~CTIMER_TCR_CEN_MASK;
372     /* Enable timer interrupt to occur */
373     NVIC_EnableIRQ(CTIMER0_IRQn);
374 }
375 
376 /*!
377  * @brief Function gates peripheral clock of CTIMER0.
378  */
SMARTCARD_USIM_TimerDeinit(void)379 static void SMARTCARD_USIM_TimerDeinit(void)
380 {
381 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
382     /* Gate the CTIMER timer clock*/
383     CLOCK_DisableClock(kCLOCK_Ct32b0);
384 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
385 
386     /* Disable CTIMER IRQ interrupt to occur */
387     NVIC_DisableIRQ(CTIMER0_IRQn);
388 }
389 
390 /*!
391  * brief Initializes timer with input period, enable interrupt and start counter.
392  *
393  * param channel The timer channel.
394  * param time The time period.
395  */
SMARTCARD_USIM_TimerStart(uint32_t time)396 void SMARTCARD_USIM_TimerStart(uint32_t time)
397 {
398     /* Set timer period */
399     CTIMER0->MR[0] = time;
400     /* Enable timer interrupt and timer */
401     CTIMER0->MCR = CTIMER_MCR_MR0I_MASK | CTIMER_MCR_MR0R_MASK | CTIMER_MCR_MR0S_MASK;
402     CTIMER0->TCR |= CTIMER_TCR_CEN_MASK;
403 }
404 
405 /*!
406  * @brief Stop timer specific channel, disable channel interrupts and stops counter.
407  */
SMARTCARD_USIM_TimerStop(void)408 static void SMARTCARD_USIM_TimerStop(void)
409 {
410     /* Stop timer*/
411     CTIMER0->TCR &= ~CTIMER_TCR_CEN_MASK;
412 }
413 #endif /* FSL_FEATURE_SOC_CTIMER_COUNT */
414 
415 /*!
416  * brief Fills in the smartcard_card_params structure with default values according to the EMV 4.3 specification.
417  *
418  * param cardParams The configuration structure of type smartcard_interface_config_t.
419  * Function fill in members:
420  *        Fi = 372;
421  *        Di = 1;
422  *        currentD = 1;
423  *        WI = 0x0A;
424  *        GTN = 0x00;
425  * with default values.
426  */
SMARTCARD_USIM_GetDefaultConfig(smartcard_card_params_t * cardParams)427 void SMARTCARD_USIM_GetDefaultConfig(smartcard_card_params_t *cardParams)
428 {
429     /* Initializes the configure structure to zero. */
430     (void)memset(cardParams, 0, sizeof(*cardParams));
431 
432     /* EMV default values */
433     cardParams->Fi       = 372u;
434     cardParams->Di       = 1u;
435     cardParams->currentD = 1u;
436     cardParams->WI       = 0x0Au;
437     cardParams->GTN      = 0x00u;
438 }
439 
440 /*!
441  * brief Initializes an USIM peripheral for the Smart card/ISO-7816 operation.
442  *
443  * This function un-gates the USIM clock, initializes the module to EMV default settings,
444  * configures the IRQ, enables the module-level interrupt to the core and, initializes the driver context.
445  *
446  * param base The USIM peripheral base address.
447  * param context A pointer to the smart card driver context structure.
448  * param srcClock_Hz Smart card clock generation module source clock.
449  *
450  * return An error code or kStatus_SMARTCARD_Success.
451  */
SMARTCARD_USIM_Init(USIM_Type * base,smartcard_context_t * context,uint32_t srcClock_Hz)452 status_t SMARTCARD_USIM_Init(USIM_Type *base, smartcard_context_t *context, uint32_t srcClock_Hz)
453 {
454     assert((NULL != base));
455 
456     if ((NULL == context) || (0UL == srcClock_Hz) || (0UL != (srcClock_Hz % context->interfaceConfig.smartCardClock)))
457     {
458         return kStatus_SMARTCARD_InvalidInput;
459     }
460 
461     uint32_t instance = SMARTCARD_USIM_GetInstance(base);
462 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
463     /* Enable usim clock */
464     CLOCK_EnableClock(s_usimClock[instance]);
465 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
466 
467 #if !(defined(FSL_FEATURE_USIM_HAS_NO_RESET) && FSL_FEATURE_USIM_HAS_NO_RESET)
468     /* Reset the usim module */
469     RESET_PeripheralReset(s_usimResets[instance]);
470 #endif /* FSL_FEATURE_USIM_HAS_NO_RESET */
471 
472     context->base = base;
473     /* Initialize USIM to a known context. */
474     /* Starts the USIM_IF's clock, stop Card Clock and set card's clock divisor. */
475     base->CLKR =
476         USIM_CLKR_STOP_UCLK_MASK | USIM_CLKR_DIVISOR(srcClock_Hz / context->interfaceConfig.smartCardClock / 2U);
477     base->USCCR |= USIM_USCCR_TXD_FORCE_MASK;
478     /* Clears FIFOs. */
479     base->FCR |= USIM_FCR_RESETTF_MASK | USIM_FCR_RESETRF_MASK;
480     /* Initialize USIM module for SMARTCARD mode of default operation */
481     if (!SMARTCARD_USIM_SetTransferType(base, context, kSMARTCARD_SetupATRMode))
482     {
483         return kStatus_SMARTCARD_InvalidInput;
484     }
485     /* Store information about tx fifo depth */
486     context->txFifoEntryCount = FSL_FEATURE_USIM_FIFO_DEPTH;
487     /* Compute max value of rx fifo threshold */
488     context->rxFifoThreshold = SMARTCARD_MAX_RX_TRIGGER_LEVEL;
489     /* Enable USIM interrupt on NVIC level. */
490     NVIC_EnableIRQ(s_usimIRQ[instance]);
491 #if defined(FSL_FEATURE_SOC_CTIMER_COUNT) && (FSL_FEATURE_SOC_CTIMER_COUNT)
492     /* Initialize HW timer for the initial character (TS) delay measurement */
493     SMARTCARD_USIM_TimerInit();
494 #endif /* FSL_FEATURE_SOC_CTIMER_COUNT */
495     /* Finally, disable the USIM transmitter */
496     base->FCR |= USIM_FCR_TX_HOLD_MASK;
497 
498     return kStatus_SMARTCARD_Success;
499 }
500 
501 /*!
502  * brief This function disables the USIM interrupts, disables the transmitter and receiver,
503  * flushes the FIFOs, and gates USIM clock in SIM.
504  *
505  * param base The USIM module base address.
506  */
SMARTCARD_USIM_Deinit(USIM_Type * base)507 void SMARTCARD_USIM_Deinit(USIM_Type *base)
508 {
509     uint32_t instance = 0u;
510     /* In case there is still data in the TX FIFO that is being transmitted wait till transmit is complete. */
511     while ((base->FSR & USIM_FSR_TX_LENGTH_MASK) != 0u)
512     {
513     }
514     while ((base->LSR & USIM_LSR_TX_WORKING_MASK) != 0u)
515     {
516     }
517     instance = SMARTCARD_USIM_GetInstance(base);
518 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
519     /* Gate USIM module clock */
520     CLOCK_DisableClock(s_usimClock[instance]);
521 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
522     /* Disable usim interrupt in NVIC */
523     NVIC_DisableIRQ(s_usimIRQ[instance]);
524 /* De-initialize also external CTIMER timer */
525 #if defined(FSL_FEATURE_SOC_CTIMER_COUNT) && (FSL_FEATURE_SOC_CTIMER_COUNT)
526     SMARTCARD_USIM_TimerDeinit();
527 #endif /* FSL_FEATURE_SOC_CTIMER_COUNT */
528 }
529 
530 /*!
531  * brief Transfer data using interrupts.
532  *
533  * A non-blocking (also known as asynchronous) function means that the function returns
534  * immediately after initiating the transfer function. The application has to get the
535  * transfer status to see when the transfer is complete. In other words, after calling the non-blocking
536  * (asynchronous) transfer function, the application must get the transfer status to check if the transmit
537  * is completed or not.
538  *
539  * param base The USIM peripheral base address.
540  * param context A pointer to a smart card driver context structure.
541  * param xfer A pointer to the smart card transfer structure where the linked buffers and sizes are stored.
542  *
543  * return An error code or kStatus_SMARTCARD_Success.
544  */
SMARTCARD_USIM_TransferNonBlocking(USIM_Type * base,smartcard_context_t * context,smartcard_xfer_t * xfer)545 status_t SMARTCARD_USIM_TransferNonBlocking(USIM_Type *base, smartcard_context_t *context, smartcard_xfer_t *xfer)
546 {
547     if ((NULL == context) || (NULL == xfer) || (xfer->buff == NULL))
548     {
549         return kStatus_SMARTCARD_InvalidInput;
550     }
551 
552     /* Check input parameters */
553     if ((0u == xfer->size))
554     {
555         return kStatus_SMARTCARD_Success;
556     }
557     /* Check if some transfer is in progress */
558     if (0 != SMARTCARD_USIM_GetTransferRemainingBytes(base, context))
559     {
560         if (kSMARTCARD_Receive == context->direction)
561         {
562             return kStatus_SMARTCARD_RxBusy;
563         }
564         else
565         {
566             return kStatus_SMARTCARD_TxBusy;
567         }
568     }
569     /* Initialize error check flags */
570     context->rxtCrossed  = false;
571     context->txtCrossed  = false;
572     context->parityError = false;
573     /* Initialize SMARTCARD context structure to start transfer */
574     context->xBuff = xfer->buff;
575     context->xSize = xfer->size;
576 
577     if (kSMARTCARD_Receive == xfer->direction)
578     {
579         context->direction     = xfer->direction;
580         context->transferState = kSMARTCARD_ReceivingState;
581         /* Start transfer */
582         SMARTCARD_USIM_StartReceiveData(base, context);
583     }
584     else if (kSMARTCARD_Transmit == xfer->direction)
585     {
586         context->direction     = xfer->direction;
587         context->transferState = kSMARTCARD_TransmittingState;
588         /* Start transfer */
589         SMARTCARD_USIM_StartSendData(base, context);
590     }
591     else
592     {
593         return kStatus_SMARTCARD_InvalidInput;
594     }
595 
596     return kStatus_SMARTCARD_Success;
597 }
598 
599 /*!
600  * brief Returns whether the previous USIM transfer has finished.
601  *
602  * When performing an async transfer, call this function to ascertain the context of the
603  * current transfer: in progress (or busy) or complete (success). If the
604  * transfer is still in progress, the user can obtain the number of words that have not been
605  * transferred.
606  *
607  * param base The USIM module base address.
608  * param context A pointer to a smart card driver context structure.
609  *
610  * return The number of bytes not transferred.
611  */
SMARTCARD_USIM_GetTransferRemainingBytes(USIM_Type * base,smartcard_context_t * context)612 int32_t SMARTCARD_USIM_GetTransferRemainingBytes(USIM_Type *base, smartcard_context_t *context)
613 {
614     if ((NULL == context))
615     {
616         return -1;
617     }
618     if (context->xIsBusy)
619     {
620         if (context->direction == kSMARTCARD_Transmit)
621         {
622             /* Count of bytes in buffer + data in fifo */
623             uint32_t count;
624             count = context->xSize;
625             count += ((base->FSR & USIM_FSR_TX_LENGTH_MASK) >> USIM_FSR_TX_LENGTH_SHIFT);
626             return (int32_t)count;
627         }
628         return (int32_t)context->xSize;
629     }
630 
631     return 0;
632 }
633 
634 /*!
635  * brief Terminates an asynchronous USIM transfer early.
636  *
637  * During an async USIM transfer, the user can terminate the transfer early
638  * if the transfer is still in progress.
639  *
640  * param base The USIM peripheral address.
641  * param context A pointer to a smart card driver context structure.
642  * retval kStatus_SMARTCARD_Success The transmit abort was successful.
643  * retval kStatus_SMARTCARD_NoTransmitInProgress No transmission is currently in progress.
644  */
SMARTCARD_USIM_AbortTransfer(USIM_Type * base,smartcard_context_t * context)645 status_t SMARTCARD_USIM_AbortTransfer(USIM_Type *base, smartcard_context_t *context)
646 {
647     if ((NULL == context))
648     {
649         return kStatus_SMARTCARD_InvalidInput;
650     }
651 
652     context->abortTransfer = true;
653 
654     /* Check if a transfer is running. */
655     if ((!context->xIsBusy))
656     {
657         return kStatus_SMARTCARD_NoTransferInProgress;
658     }
659     /* Call transfer complete to abort transfer */
660     if (kSMARTCARD_Receive == context->direction)
661     { /* Finish up current running transfer. */
662         SMARTCARD_USIM_CompleteReceiveData(base, context);
663     }
664     else if (kSMARTCARD_Transmit == context->direction)
665     { /* Finish up current running transfer. */
666         SMARTCARD_USIM_CompleteSendData(base, context);
667     }
668     else
669     {
670         return kStatus_SMARTCARD_InvalidInput;
671     }
672 
673     return kStatus_SMARTCARD_Success;
674 }
675 
676 /*!
677  * brief Handles USIM module interrupts.
678  *
679  * param base The USIM peripheral base address.
680  * param context A pointer to a smart card driver context structure.
681  */
SMARTCARD_USIM_IRQHandler(USIM_Type * base,smartcard_context_t * context)682 void SMARTCARD_USIM_IRQHandler(USIM_Type *base, smartcard_context_t *context)
683 {
684     if (NULL == context)
685     {
686         return;
687     }
688 
689     /* Check if Character Waiting Time has expired */
690     if (((base->IIR & USIM_IIR_CWT_MASK) != 0u) && ((base->IER & USIM_IER_CWT_MASK) != 0u))
691     {
692         /*Clear Character Wait Timer interrupt status. */
693         base->IIR |= USIM_IIR_CWT_MASK;
694         /*Restart Character Wait Timer. */
695         base->DLR = base->DLR;
696 
697         if (kSMARTCARD_T0Transport == context->tType)
698         { /* Indicate WWT expired */
699             context->timersState.wwtExpired = true;
700         }
701         else
702         { /* Indicate CWT expired */
703             context->timersState.cwtExpired = true;
704         }
705 
706         if (context->xIsBusy)
707         {
708             if (kSMARTCARD_Receive == context->direction)
709             { /* Terminate and un-block any caller */
710                 SMARTCARD_USIM_CompleteReceiveData(base, context);
711             }
712             else
713             { /* Terminate and un-block any caller */
714                 SMARTCARD_USIM_CompleteSendData(base, context);
715             }
716         }
717     }
718 
719     /* Check if a Block Wait Timer expired */
720     if (((base->IIR & USIM_IIR_BWT_MASK) != 0u) && ((base->IER & USIM_IER_BWT_MASK) != 0u))
721     {
722         /* Clear Block Wait Timer interrupt status flag. */
723         base->IIR |= USIM_IIR_BWT_MASK;
724         /*Restart Block Wait Timer. */
725         base->DLR = base->DLR;
726 
727         if (kSMARTCARD_T0Transport == context->tType)
728         { /* Indicate WWT expired */
729             context->timersState.wwtExpired = true;
730         }
731         else
732         { /* Indicate BWT expired */
733             context->timersState.bwtExpired = true;
734         }
735         /* Check if Wait Time Extension(WTX) was requested */
736         if (context->wtxRequested)
737         { /* Reset WTX to default */
738             (void)SMARTCARD_USIM_Control(base, context, kSMARTCARD_ResetWaitTimeMultiplier, 1u);
739         }
740         if (context->xIsBusy)
741         {
742             if (kSMARTCARD_Receive == context->direction)
743             { /* Terminate and un-block any caller */
744                 SMARTCARD_USIM_CompleteReceiveData(base, context);
745             }
746             else
747             { /* Terminate and un-block any caller */
748                 SMARTCARD_USIM_CompleteSendData(base, context);
749             }
750         }
751     }
752 
753     /* Check if parity error trigger level was reached */
754     if ((base->IIR & USIM_IIR_PERR_MASK) != 0u)
755     {
756         /* Clear parity error interrupt status. */
757         base->IIR |= USIM_IIR_PERR_MASK;
758         if (kSMARTCARD_WaitingForTSState == context->transferState)
759         {
760             /* A parity error detected during initial character (TS) detection phase */
761             context->transferState = kSMARTCARD_InvalidTSDetecetedState;
762             /* Un-block any caller waiting for initial character detection */
763             if ((context->xIsBusy) && (context->direction == kSMARTCARD_Receive))
764             {
765                 SMARTCARD_USIM_CompleteReceiveData(base, context);
766             }
767         }
768         else
769         { /* Parity error detected after initial character detection phase */
770             context->parityError = true;
771             if (context->tType == kSMARTCARD_T0Transport)
772             {
773                 /* Indicate T=0 Rx parity error trigger level expired. */
774                 context->rxtCrossed = true;
775                 SMARTCARD_USIM_CompleteReceiveData(base, context);
776             }
777         }
778     }
779 
780     /* Check if framing error trigger level was reached */
781     if ((base->IIR & USIM_IIR_FRAMERR_MASK) != 0u)
782     {
783         /* Indicate framing Rx error trigger level expired. */
784         context->rxtCrossed = true;
785         /* Clear framing error interrupt status. */
786         base->IIR |= USIM_IIR_FRAMERR_MASK;
787         if (context->xIsBusy)
788         { /* Unblock the caller */
789             SMARTCARD_USIM_CompleteReceiveData(base, context);
790         }
791     }
792 
793     /* Check if T=0 error trigger level was reached */
794     if ((base->IIR & USIM_IIR_T0ERR_MASK) != 0u)
795     {
796         /* Indicate T=0 Tx error trigger level expired. */
797         context->txtCrossed = true;
798         /* Clear T=0 error interrupt status. */
799         base->IIR |= USIM_IIR_T0ERR_MASK;
800         if (context->xIsBusy)
801         { /* Unblock the caller */
802             SMARTCARD_USIM_CompleteSendData(base, context);
803         }
804     }
805 
806     /* RDR IRQ - count of bytes in rx fifo is equal to or greater than FCR[RX_TL]. */
807     if (((base->IIR & USIM_IIR_RDR_MASK) != 0u) && ((base->IER & USIM_IER_RDR_MASK) != 0u))
808     {
809         /* IF in T=1 after receive 1st byte - disable BWT and enable CWT interrupt */
810         if ((context->tType == kSMARTCARD_T1Transport) && (context->xSize > 0u) &&
811             ((base->IER & USIM_IER_BWT_MASK) != 0u))
812         {
813             context->timersState.cwtExpired = false;
814             /* Clear CWT error flag */
815             base->IIR = USIM_IIR_CWT_MASK;
816 
817             /* Disable BWT interrupt and enable CWT interrupt. */
818             base->IER = (base->IER & ~USIM_IER_BWT_MASK) | USIM_IER_CWT_MASK;
819         }
820         if (kSMARTCARD_WaitingForTSState == context->transferState)
821         {
822 #if defined(FSL_FEATURE_SOC_CTIMER_COUNT) && (FSL_FEATURE_SOC_CTIMER_COUNT)
823             /* Stop TS timer */
824             SMARTCARD_USIM_TimerStop();
825 #endif /* FSL_FEATURE_SOC_CTIMER_COUNT */
826             /* Read TS byte */
827             uint8_t ts = (uint8_t)base->RBR;
828             if (ts == SMARTCARD_TS_INVERSE_CONVENTION)
829             {
830                 /* Received valid TS */
831                 context->transferState = kSMARTCARD_ReceivingState;
832                 /* Card encodes/decodes data in the inverse convention. */
833                 context->cardParams.convention = kSMARTCARD_InverseConvention;
834                 base->LCR |= USIM_LCR_ORDER_MASK;
835                 base->LCR &= ~USIM_LCR_EPS_MASK;
836             }
837             else if (ts == SMARTCARD_TS_DIRECT_CONVENTION)
838             {
839                 /* Received valid TS */
840                 context->transferState = kSMARTCARD_ReceivingState;
841                 /* Card encodes/decodes data in the direct convention. */
842                 context->cardParams.convention = kSMARTCARD_DirectConvention;
843                 base->LCR &= ~USIM_LCR_ORDER_MASK;
844                 base->LCR |= USIM_LCR_EPS_MASK;
845             }
846             else
847             {
848                 context->transferState = kSMARTCARD_InvalidTSDetecetedState;
849             }
850             /* Complete receive transfer */
851             SMARTCARD_USIM_CompleteReceiveData(base, context);
852         }
853         else
854         {
855             while (((base->FSR & USIM_FSR_RX_LENGTH_MASK) != 0u) && ((context->xSize) > 0u))
856             {
857                 /* Get data and put into receive buffer */
858                 *context->xBuff = (uint8_t)(base->RBR);
859                 ++context->xBuff;
860                 --context->xSize;
861             }
862 
863             /* Check if the last byte was received */
864             if (context->xSize == 0u)
865             {
866                 SMARTCARD_USIM_CompleteReceiveData(base, context);
867             }
868             else
869             {
870                 /* If the count of remaining bytes to receive is less than depth of fifo, update the value of the
871                  * receiver data trigger level. */
872                 if (context->xSize < context->rxFifoThreshold)
873                 {
874                     /* Set receiver data trigger level to the value closest to the number of bytes remaining. */
875                     base->FCR = (base->FCR & ~USIM_FCR_RX_TL_MASK) | USIM_FIND_RX_FIFO_TRIGGER_LEVEL(context->xSize);
876                 }
877             }
878         }
879     }
880 
881     /* TDR IRQ -  the number of bytes in the TX-FIFO is less than FCR[TX_TL]. */
882     if (((base->IIR & USIM_IIR_TDR_MASK) != 0u) && ((base->IER & USIM_IER_TDR_MASK) != 0u))
883     {
884         if (context->xSize == 0u)
885         {
886             SMARTCARD_USIM_CompleteSendData(base, context);
887         }
888         else
889         {
890             while (((context->txFifoEntryCount -
891                      (uint8_t)((base->FSR & USIM_FSR_TX_LENGTH_MASK) >> USIM_FSR_TX_LENGTH_SHIFT)) > 0u) &&
892                    (context->xSize > 0u))
893             {
894                 /* Write data to fifo */
895                 base->THR = *(context->xBuff);
896                 ++context->xBuff;
897                 --context->xSize;
898             }
899         }
900     }
901 
902     SDK_ISR_EXIT_BARRIER;
903 }
904 
905 /*!
906  * brief Controls the USIM module per different user request.
907  *
908  * param base The USIM peripheral base address.
909  * param context A pointer to a smart card driver context structure.
910  * param control Control type.
911  * param param Integer value of specific to control command.
912  *
913  * return kStatus_SMARTCARD_Success in success.
914  * return kStatus_SMARTCARD_OtherError in case of error.
915  */
SMARTCARD_USIM_Control(USIM_Type * base,smartcard_context_t * context,smartcard_control_t control,uint32_t param)916 status_t SMARTCARD_USIM_Control(USIM_Type *base,
917                                 smartcard_context_t *context,
918                                 smartcard_control_t control,
919                                 uint32_t param)
920 {
921     if ((NULL == context))
922     {
923         return kStatus_SMARTCARD_InvalidInput;
924     }
925 
926     status_t status = kStatus_SMARTCARD_Success;
927     uint32_t temp32 = 0u;
928 
929     switch (control)
930     {
931         case kSMARTCARD_EnableADT:
932             break;
933         case kSMARTCARD_DisableADT:
934             break;
935         case kSMARTCARD_EnableGTV:
936             break;
937         case kSMARTCARD_DisableGTV:
938             break;
939         case kSMARTCARD_ResetWWT:
940             /* Re-write DLR to reset WWT Timer. */
941             base->DLR = base->DLR;
942             break;
943         case kSMARTCARD_EnableWWT:
944             /* Enable BWT/CWT Timer interrupt to occur. */
945             base->IER |= USIM_IER_BWT_MASK | USIM_IER_CWT_MASK;
946             break;
947         case kSMARTCARD_DisableWWT:
948             /* Disable BWT/CWT Timer interrupt to occur. */
949             base->IER &= ~(USIM_IER_BWT_MASK | USIM_IER_CWT_MASK);
950             break;
951         case kSMARTCARD_ResetCWT:
952             /* Re-write DLR to reset CWT Timer. */
953             base->DLR = base->DLR;
954             break;
955         case kSMARTCARD_EnableCWT:
956             /* Enable CWT Timer interrupt to occur. */
957             base->IER |= USIM_IER_CWT_MASK;
958             break;
959         case kSMARTCARD_DisableCWT:
960             /* Disable CWT Timer interrupt to occur. */
961             base->IER &= ~USIM_IER_CWT_MASK;
962             break;
963         case kSMARTCARD_ResetBWT:
964             /* Re-write DLR to reset BWT Timer. */
965             base->DLR = base->DLR;
966             break;
967         case kSMARTCARD_EnableBWT:
968             /* Enable BWT Timer interrupt to occur. */
969             base->IER |= USIM_IER_BWT_MASK;
970             break;
971         case kSMARTCARD_DisableBWT:
972             /* Disable BWT Timer interrupt to occur. */
973             base->IER &= ~USIM_IER_BWT_MASK;
974             break;
975         case kSMARTCARD_EnableInitDetect:
976             /* Enable initial character detection : hardware method. */
977             context->transferState = kSMARTCARD_WaitingForTSState;
978             /* Set receiver triggrt level to 1 byte. */
979             base->FCR &= ~USIM_FCR_RX_TL_MASK;
980             /* Enable RDT interrupt. */
981             base->IER |= USIM_IER_RDR_MASK;
982             break;
983         case kSMARTCARD_EnableAnack:
984             /* Enable all error interrupt. */
985             base->IER |= USIM_IER_T0ERR_MASK | USIM_IER_PERR_MASK | USIM_IER_FRAMERR_MASK;
986             break;
987         case kSMARTCARD_DisableAnack:
988             /* Disable error interrupt to occur. */
989             base->IER &= ~(USIM_IER_T0ERR_MASK | USIM_IER_PERR_MASK | USIM_IER_FRAMERR_MASK);
990             break;
991         case kSMARTCARD_ConfigureBaudrate:
992             /* Set baudrate/ETU time based on Fi/Di parameters. */
993             if (!SMARTCARD_USIM_SetBaudRate(base, (uint32_t)context->cardParams.Fi,
994                                             (uint32_t)context->cardParams.currentD))
995             {
996                 status = kStatus_SMARTCARD_InvalidInput;
997             }
998             break;
999         case kSMARTCARD_SetupATRMode:
1000             /* Set in default ATR mode. */
1001             if (!SMARTCARD_USIM_SetTransferType(base, context, kSMARTCARD_SetupATRMode))
1002             {
1003                 status = kStatus_SMARTCARD_InvalidInput;
1004             }
1005             break;
1006         case kSMARTCARD_SetupT0Mode:
1007             /* Set transport protocol type to T=0. */
1008             if (!SMARTCARD_USIM_SetTransferType(base, context, kSMARTCARD_SetupT0Mode))
1009             {
1010                 status = kStatus_SMARTCARD_InvalidInput;
1011             }
1012             break;
1013         case kSMARTCARD_SetupT1Mode:
1014             /* Set transport protocol type to T=1. */
1015             if (!SMARTCARD_USIM_SetTransferType(base, context, kSMARTCARD_SetupT1Mode))
1016             {
1017                 status = kStatus_SMARTCARD_InvalidInput;
1018             }
1019             break;
1020         case kSMARTCARD_EnableReceiverMode:
1021             /* Enable RDT interrupt */
1022             base->IER |= USIM_IER_RDR_MASK;
1023             break;
1024         case kSMARTCARD_DisableReceiverMode:
1025             /* Disable RDT interrupt */
1026             base->IER &= ~USIM_IER_RDR_MASK;
1027             break;
1028         case kSMARTCARD_EnableTransmitterMode:
1029             /* Enable TDR interrupt */
1030             base->IER |= USIM_IER_TDR_MASK;
1031             break;
1032         case kSMARTCARD_DisableTransmitterMode:
1033             /* Disable TDR interrupt */
1034             base->IER &= ~USIM_IER_TDR_MASK;
1035             break;
1036         case kSMARTCARD_ResetWaitTimeMultiplier:
1037             /* Reset Wait Timer Multiplier
1038              * EMV Formula : WTX x (11 + ((2^BWI + 1) x 960 x D)) */
1039             temp32 = ((uint8_t)param) *
1040                      (11u + ((((uint32_t)1u << context->cardParams.BWI) + 1u) * 960u * context->cardParams.currentD));
1041             base->BWTR = temp32 - SMARTCARD_T1_BWT_ADJUSTMENT;
1042             /* Set flag to SMARTCARD context accordingly */
1043             if (param > 1u)
1044             {
1045                 context->wtxRequested = true;
1046             }
1047             else
1048             {
1049                 context->wtxRequested = false;
1050             }
1051             break;
1052         default:
1053             status = kStatus_SMARTCARD_InvalidInput;
1054             break;
1055     }
1056     return status;
1057 }
1058 
1059 /*!
1060  * brief Handles initial TS character timer time-out event.
1061  *
1062  * param base The USIM peripheral base address.
1063  * param context A pointer to a Smart card driver context structure.
1064  */
SMARTCARD_USIM_TSExpiryCallback(USIM_Type * base,smartcard_context_t * context)1065 void SMARTCARD_USIM_TSExpiryCallback(USIM_Type *base, smartcard_context_t *context)
1066 {
1067     if ((NULL == context))
1068     {
1069         return;
1070     }
1071 #if defined(FSL_FEATURE_SOC_CTIMER_COUNT) && FSL_FEATURE_SOC_CTIMER_COUNT
1072     /* Clear the status flags that were set */
1073     CTIMER0->IR = CTIMER0->IR;
1074     /* Stop TS timer */
1075     SMARTCARD_USIM_TimerStop();
1076 #endif /* FSL_FEATURE_SOC_CTIMER_COUNT */
1077     /* Set timer has expired */
1078     context->timersState.initCharTimerExpired = true;
1079     context->transferState                    = kSMARTCARD_IdleState;
1080     /* Un-block the caller */
1081     SMARTCARD_USIM_CompleteReceiveData(base, context);
1082 
1083     return;
1084 }
1085