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