1 /*
2  * Copyright 2021-2022 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "fsl_smartcard_usim.h"
8 #include "fsl_smartcard_phy.h"
9 
10 /* Component ID definition, used by tools. */
11 #ifndef FSL_COMPONENT_ID
12 #define FSL_COMPONENT_ID "platform.drivers.smartcard_phy_usim"
13 #endif
14 
15 /*******************************************************************************
16  * Variables
17  ******************************************************************************/
18 
19 /*******************************************************************************
20  * Private Functions
21  ******************************************************************************/
22 static void SMARTCARD_PHY_USIM_InterfaceClockInit(USIM_Type *base,
23                                                   const smartcard_interface_config_t *config,
24                                                   uint32_t srcClock_Hz);
25 
26 /*******************************************************************************
27  * Code
28  ******************************************************************************/
29 
30 /*!
31  * @brief This function initializes clock module used for card clock generation
32  */
SMARTCARD_PHY_USIM_InterfaceClockInit(USIM_Type * base,const smartcard_interface_config_t * config,uint32_t srcClock_Hz)33 static void SMARTCARD_PHY_USIM_InterfaceClockInit(USIM_Type *base,
34                                                   const smartcard_interface_config_t *config,
35                                                   uint32_t srcClock_Hz)
36 {
37     assert((NULL != config) && (0u != srcClock_Hz));
38 
39     uint32_t usimClkMhz = 0u;
40     uint8_t usimPRSCValue;
41 
42     /* Retrieve USIM clock */
43     usimClkMhz = srcClock_Hz / 1000000u;
44     /* Calculate MOD value */
45     usimPRSCValue = (uint8_t)((usimClkMhz * 1000u) / (config->smartCardClock / 1000u) / 2U);
46     while (0UL != (base->CLKR & USIM_CLKR_RQST_MASK))
47     {
48     }
49     /* Set clock prescaler */
50     base->CLKR = (base->CLKR & ~USIM_CLKR_DIVISOR_MASK) | USIM_CLKR_DIVISOR(usimPRSCValue);
51 }
52 
SMARTCARD_PHY_GetDefaultConfig(smartcard_interface_config_t * config)53 void SMARTCARD_PHY_GetDefaultConfig(smartcard_interface_config_t *config)
54 {
55     assert((NULL != config));
56 
57     /* Initializes the configure structure to zero. */
58     (void)memset(config, 0, sizeof(*config));
59 
60     config->clockToResetDelay = SMARTCARD_INIT_DELAY_CLOCK_CYCLES;
61     config->vcc               = kSMARTCARD_VoltageClassB3_3V;
62 }
63 
SMARTCARD_PHY_Init(void * base,smartcard_interface_config_t const * config,uint32_t srcClock_Hz)64 status_t SMARTCARD_PHY_Init(void *base, smartcard_interface_config_t const *config, uint32_t srcClock_Hz)
65 {
66     if ((NULL == config) || (0u == srcClock_Hz))
67     {
68         return kStatus_SMARTCARD_InvalidInput;
69     }
70     USIM_Type *usimBase = (USIM_Type *)base;
71 
72     /* SMARTCARD clock initialization. Clock is still not active after this call */
73     SMARTCARD_PHY_USIM_InterfaceClockInit(usimBase, config, srcClock_Hz);
74 
75     return kStatus_SMARTCARD_Success;
76 }
77 
SMARTCARD_PHY_Deinit(void * base,smartcard_interface_config_t const * config)78 void SMARTCARD_PHY_Deinit(void *base, smartcard_interface_config_t const *config)
79 {
80     assert((NULL != config));
81     /* Stop CARD CLOCK */
82     while (0U != (((USIM_Type *)base)->CLKR & USIM_CLKR_RQST_MASK))
83     {
84     }
85     ((USIM_Type *)base)->CLKR |= USIM_CLKR_STOP_UCLK_MASK;
86     /* Deactivate VCC */
87     ((USIM_Type *)base)->USCCR &= ~USIM_USCCR_VCC_MASK;
88 }
89 
SMARTCARD_PHY_Activate(void * base,smartcard_context_t * context,smartcard_reset_type_t resetType)90 status_t SMARTCARD_PHY_Activate(void *base, smartcard_context_t *context, smartcard_reset_type_t resetType)
91 {
92     if ((NULL == context) || (NULL == context->timeDelay))
93     {
94         return kStatus_SMARTCARD_InvalidInput;
95     }
96     assert(context->interfaceConfig.vcc == kSMARTCARD_VoltageClassB3_3V);
97 
98     USIM_Type *usimBase = (USIM_Type *)base;
99 
100     context->timersState.initCharTimerExpired = false;
101     context->resetType                        = resetType;
102 
103     /* Hold Transmission. */
104     usimBase->FCR |= USIM_FCR_TX_HOLD_MASK;
105     if (resetType == kSMARTCARD_ColdReset)
106     {
107         /* Set Reset low */
108         usimBase->USCCR &= ~USIM_USCCR_RST_CARD_N_MASK;
109         /* Enable VCC for SMARTCARD, Enable smart card clock */
110         usimBase->USCCR = (usimBase->USCCR & ~USIM_USCCR_VCC_MASK) | USIM_USCCR_VCC(1);
111         usimBase->USCCR &= ~USIM_USCCR_TXD_FORCE_MASK;
112         usimBase->CLKR &= ~USIM_CLKR_STOP_UCLK_MASK;
113         /* Set transfer mode to default(direct convention) */
114         usimBase->LCR &= ~(USIM_LCR_ORDER_MASK | USIM_LCR_INVERSE_MASK);
115     }
116     else if (resetType == kSMARTCARD_WarmReset)
117     {
118         /* Ensure that card is already active */
119         if (!context->cardParams.active)
120         { /* Card is not active;hence return */
121             return kStatus_SMARTCARD_CardNotActivated;
122         }
123         /* Set Reset low */
124         usimBase->USCCR &= ~USIM_USCCR_RST_CARD_N_MASK;
125     }
126     else
127     {
128         return kStatus_SMARTCARD_InvalidInput;
129     }
130     /* Calculate time delay needed for reset */
131     uint32_t temp =
132         ((((uint32_t)10000u * context->interfaceConfig.clockToResetDelay) / context->interfaceConfig.smartCardClock) *
133          100u) +
134         1u;
135     context->timeDelay(temp);
136     /* Pull reset HIGH Now to mark the end of Activation sequence */
137     usimBase->USCCR |= USIM_USCCR_RST_CARD_N_MASK;
138 
139     /* Enable external timer for TS detection time-out */
140     SMARTCARD_USIM_TimerStart((SMARTCARD_INIT_DELAY_CLOCK_CYCLES + SMARTCARD_INIT_DELAY_CLOCK_CYCLES_ADJUSTMENT) *
141                               (SystemCoreClock / context->interfaceConfig.smartCardClock));
142     /* Here the card was activated */
143     context->cardParams.active = true;
144 
145     return kStatus_SMARTCARD_Success;
146 }
147 
SMARTCARD_PHY_Deactivate(void * base,smartcard_context_t * context)148 status_t SMARTCARD_PHY_Deactivate(void *base, smartcard_context_t *context)
149 {
150     if ((NULL == context))
151     {
152         return kStatus_SMARTCARD_InvalidInput;
153     }
154 
155     USIM_Type *usimBase = (USIM_Type *)base;
156 
157     /* Set Reset low */
158     usimBase->USCCR &= ~USIM_USCCR_RST_CARD_N_MASK;
159     /* Stop SMARTCARD clock generation */
160     while (0UL != (usimBase->CLKR & USIM_CLKR_RQST_MASK))
161     {
162     }
163     usimBase->CLKR &= ~USIM_CLKR_STOP_LEVEL_MASK;
164     usimBase->CLKR |= USIM_CLKR_STOP_UCLK_MASK;
165     /* Force the I/O line to ground level. */
166     usimBase->USCCR |= USIM_USCCR_TXD_FORCE_MASK;
167     /* Turn the VCC voltage to ground level. */
168     usimBase->USCCR &= ~USIM_USCCR_VCC_MASK;
169     /* According EMV 4.3 specification deactivation sequence should be done within 100ms.
170      * The period is measured from the time that RST is set to state L to the time that Vcc
171      * reaches 0.4 V or less.
172      */
173     context->timeDelay(100 * 1000);
174     /* Here the card was deactivated */
175     context->cardParams.active = false;
176 
177     return kStatus_SMARTCARD_Success;
178 }
179 
SMARTCARD_PHY_Control(void * base,smartcard_context_t * context,smartcard_interface_control_t control,uint32_t param)180 status_t SMARTCARD_PHY_Control(void *base,
181                                smartcard_context_t *context,
182                                smartcard_interface_control_t control,
183                                uint32_t param)
184 {
185     if ((NULL == context))
186     {
187         return kStatus_SMARTCARD_InvalidInput;
188     }
189 
190     status_t status = kStatus_SMARTCARD_Success;
191 
192     switch (control)
193     {
194         case kSMARTCARD_InterfaceSetVcc:
195             /* Only 3.3V interface supported by the interface */
196             assert((smartcard_card_voltage_class_t)param == kSMARTCARD_VoltageClassB3_3V);
197             context->interfaceConfig.vcc = (smartcard_card_voltage_class_t)param;
198             break;
199         case kSMARTCARD_InterfaceSetClockToResetDelay:
200             /* Set interface clock to Reset delay set by caller */
201             context->interfaceConfig.clockToResetDelay = param;
202             break;
203         case kSMARTCARD_InterfaceReadStatus:
204             /* Workaround, RW610 board no Card detect PIN */
205             context->cardParams.present = true;
206             break;
207         default:
208             status = kStatus_SMARTCARD_InvalidInput;
209             break;
210     }
211 
212     return status;
213 }
214