1 /*
2  * Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_smartcard_emvsim.h"
10 #include "fsl_smartcard_phy.h"
11 
12 /* Component ID definition, used by tools. */
13 #ifndef FSL_COMPONENT_ID
14 #define FSL_COMPONENT_ID "platform.drivers.smartcard_phy_emvsim"
15 #endif
16 
17 /*******************************************************************************
18  * Variables
19  ******************************************************************************/
20 
21 /*******************************************************************************
22  * Private Functions
23  ******************************************************************************/
24 static uint32_t smartcard_phy_emvsim_InterfaceClockInit(EMVSIM_Type *base,
25                                                         const smartcard_interface_config_t *config,
26                                                         uint32_t srcClock_Hz);
27 
28 /*******************************************************************************
29  * Code
30  ******************************************************************************/
31 
32 /*!
33  * @brief This function initializes clock module used for card clock generation
34  */
smartcard_phy_emvsim_InterfaceClockInit(EMVSIM_Type * base,const smartcard_interface_config_t * config,uint32_t srcClock_Hz)35 static uint32_t smartcard_phy_emvsim_InterfaceClockInit(EMVSIM_Type *base,
36                                                         const smartcard_interface_config_t *config,
37                                                         uint32_t srcClock_Hz)
38 {
39     assert((NULL != config) && (0u != srcClock_Hz));
40 
41     uint32_t emvsimClkMhz = 0u;
42     uint8_t emvsimPRSCValue;
43 
44     /* Retrieve EMV SIM clock */
45     emvsimClkMhz = srcClock_Hz / 1000000u;
46     /* Calculate MOD value */
47     emvsimPRSCValue = (uint8_t)((emvsimClkMhz * 1000u) / (config->smartCardClock / 1000u));
48     /* Set clock prescaler */
49     base->CLKCFG = (base->CLKCFG & ~EMVSIM_CLKCFG_CLK_PRSC_MASK) | EMVSIM_CLKCFG_CLK_PRSC(emvsimPRSCValue);
50 
51     return config->smartCardClock;
52 }
53 
SMARTCARD_PHY_GetDefaultConfig(smartcard_interface_config_t * config)54 void SMARTCARD_PHY_GetDefaultConfig(smartcard_interface_config_t *config)
55 {
56     assert((NULL != config));
57 
58     /* Initializes the configure structure to zero. */
59     (void)memset(config, 0, sizeof(*config));
60 
61     config->clockToResetDelay = SMARTCARD_INIT_DELAY_CLOCK_CYCLES;
62     config->vcc               = kSMARTCARD_VoltageClassB3_3V;
63 }
64 
SMARTCARD_PHY_Init(void * base,smartcard_interface_config_t const * config,uint32_t srcClock_Hz)65 status_t SMARTCARD_PHY_Init(void *base, smartcard_interface_config_t const *config, uint32_t srcClock_Hz)
66 {
67     if ((NULL == config) || (0u == srcClock_Hz))
68     {
69         return kStatus_SMARTCARD_InvalidInput;
70     }
71     EMVSIM_Type *emvsimBase = (EMVSIM_Type *)base;
72 
73     /* SMARTCARD clock initialization. Clock is still not active after this call */
74     (void)smartcard_phy_emvsim_InterfaceClockInit(emvsimBase, config, srcClock_Hz);
75 
76     /* Configure EMVSIM direct interface driver interrupt occur according card presence */
77     if ((emvsimBase->PCSR & EMVSIM_PCSR_SPDP_MASK) != 0u)
78     {
79         emvsimBase->PCSR &= ~EMVSIM_PCSR_SPDES_MASK;
80     }
81     else
82     {
83         emvsimBase->PCSR |= EMVSIM_PCSR_SPDES_MASK;
84     }
85     /* Un-mask presence detect interrupt flag */
86     emvsimBase->PCSR &= ~EMVSIM_PCSR_SPDIM_MASK;
87 
88     return kStatus_SMARTCARD_Success;
89 }
90 
SMARTCARD_PHY_Deinit(void * base,smartcard_interface_config_t const * config)91 void SMARTCARD_PHY_Deinit(void *base, smartcard_interface_config_t const *config)
92 {
93     assert((NULL != config));
94     /* Deactivate VCC, CLOCK */
95     ((EMVSIM_Type *)base)->PCSR &= ~(EMVSIM_PCSR_SCEN_MASK | EMVSIM_PCSR_SVCC_EN_MASK);
96 }
97 
SMARTCARD_PHY_Activate(void * base,smartcard_context_t * context,smartcard_reset_type_t resetType)98 status_t SMARTCARD_PHY_Activate(void *base, smartcard_context_t *context, smartcard_reset_type_t resetType)
99 {
100     if ((NULL == context) || (NULL == context->timeDelay))
101     {
102         return kStatus_SMARTCARD_InvalidInput;
103     }
104     assert(context->interfaceConfig.vcc == kSMARTCARD_VoltageClassB3_3V);
105 
106     EMVSIM_Type *emvsimBase = (EMVSIM_Type *)base;
107 
108     context->timersState.initCharTimerExpired = false;
109     context->resetType                        = resetType;
110 
111     /* Disable receiver to deactivate GPC timers trigger */
112     emvsimBase->CTRL &= ~EMVSIM_CTRL_RCV_EN_MASK;
113     if (resetType == kSMARTCARD_ColdReset)
114     { /* Set polarity of VCC to active high, Enable VCC for SMARTCARD, Enable smart card clock */
115         emvsimBase->PCSR =
116             (emvsimBase->PCSR & ~EMVSIM_PCSR_VCCENP_MASK) | (EMVSIM_PCSR_SVCC_EN_MASK | EMVSIM_PCSR_SCEN_MASK);
117         /* Set transfer inversion to default(direct) value */
118         emvsimBase->CTRL &= ~EMVSIM_CTRL_IC_MASK;
119     }
120     else if (resetType == kSMARTCARD_WarmReset)
121     { /* Ensure that card is already active */
122         if (!context->cardParams.active)
123         { /* Card is not active;hence return */
124             return kStatus_SMARTCARD_CardNotActivated;
125         }
126     }
127     else
128     {
129         return kStatus_SMARTCARD_InvalidInput;
130     }
131     /* Set Reset low */
132     emvsimBase->PCSR &= ~EMVSIM_PCSR_SRST_MASK;
133     /* Calculate time delay needed for reset */
134     uint32_t temp =
135         ((((uint32_t)10000u * context->interfaceConfig.clockToResetDelay) / context->interfaceConfig.smartCardClock) *
136          100u) +
137         1u;
138     context->timeDelay(temp);
139     /* Pull reset HIGH Now to mark the end of Activation sequence */
140     emvsimBase->PCSR |= EMVSIM_PCSR_SRST_MASK;
141     /* Disable GPC timers input clock */
142     emvsimBase->CLKCFG &= ~(EMVSIM_CLKCFG_GPCNT0_CLK_SEL_MASK | EMVSIM_CLKCFG_GPCNT1_CLK_SEL_MASK);
143     /* Down counter trigger, and clear any pending counter status flag */
144     emvsimBase->TX_STATUS = EMVSIM_TX_STATUS_GPCNT1_TO_MASK | EMVSIM_TX_STATUS_GPCNT0_TO_MASK;
145     /* Set counter value for TS detection delay */
146     emvsimBase->GPCNT0_VAL = (SMARTCARD_INIT_DELAY_CLOCK_CYCLES + SMARTCARD_INIT_DELAY_CLOCK_CYCLES_ADJUSTMENT);
147     /* Pre-load counter value for ATR duration delay */
148     emvsimBase->GPCNT1_VAL = (SMARTCARD_EMV_ATR_DURATION_ETU + SMARTCARD_ATR_DURATION_ADJUSTMENT);
149     /* Select the clock for GPCNT for both TS detection and early start of ATR duration counter */
150     emvsimBase->CLKCFG |=
151         (EMVSIM_CLKCFG_GPCNT0_CLK_SEL(kEMVSIM_GPCCardClock) | EMVSIM_CLKCFG_GPCNT1_CLK_SEL(kEMVSIM_GPCTxClock));
152     /* Set receiver to ICM mode, Flush RX FIFO */
153     emvsimBase->CTRL |= (EMVSIM_CTRL_ICM_MASK | EMVSIM_CTRL_FLSH_RX_MASK);
154     /* Enable counter interrupt for TS detection */
155     emvsimBase->INT_MASK &= ~EMVSIM_INT_MASK_GPCNT0_IM_MASK;
156     /* Clear any pending status flags */
157     emvsimBase->RX_STATUS = 0xFFFFFFFFu;
158     /* Enable receiver */
159     emvsimBase->CTRL |= EMVSIM_CTRL_RCV_EN_MASK;
160     /* Here the card was activated */
161     context->cardParams.active = true;
162 
163     return kStatus_SMARTCARD_Success;
164 }
165 
SMARTCARD_PHY_Deactivate(void * base,smartcard_context_t * context)166 status_t SMARTCARD_PHY_Deactivate(void *base, smartcard_context_t *context)
167 {
168     if ((NULL == context))
169     {
170         return kStatus_SMARTCARD_InvalidInput;
171     }
172 
173     EMVSIM_Type *emvsimBase = (EMVSIM_Type *)base;
174 
175     /* Assert Reset */
176     emvsimBase->PCSR &= ~EMVSIM_PCSR_SRST_MASK;
177     /* Stop SMARTCARD clock generation */
178     emvsimBase->PCSR &= ~EMVSIM_PCSR_SCEN_MASK;
179     /* Deactivate card by disabling VCC */
180     emvsimBase->PCSR &= ~EMVSIM_PCSR_SVCC_EN_MASK;
181     /* According EMV 4.3 specification deactivation sequence should be done within 100ms.
182      * The period is measured from the time that RST is set to state L to the time that Vcc
183      * reaches 0.4 V or less.
184      */
185     context->timeDelay(100 * 1000);
186     /* Here the card was deactivated */
187     context->cardParams.active = false;
188 
189     return kStatus_SMARTCARD_Success;
190 }
191 
SMARTCARD_PHY_Control(void * base,smartcard_context_t * context,smartcard_interface_control_t control,uint32_t param)192 status_t SMARTCARD_PHY_Control(void *base,
193                                smartcard_context_t *context,
194                                smartcard_interface_control_t control,
195                                uint32_t param)
196 {
197     if ((NULL == context))
198     {
199         return kStatus_SMARTCARD_InvalidInput;
200     }
201 
202     status_t status = kStatus_SMARTCARD_Success;
203 
204     switch (control)
205     {
206         case kSMARTCARD_InterfaceSetVcc:
207             /* Only 3.3V interface supported by the direct interface */
208             assert((smartcard_card_voltage_class_t)param == kSMARTCARD_VoltageClassB3_3V);
209             context->interfaceConfig.vcc = (smartcard_card_voltage_class_t)param;
210             break;
211         case kSMARTCARD_InterfaceSetClockToResetDelay:
212             /* Set interface clock to Reset delay set by caller */
213             context->interfaceConfig.clockToResetDelay = param;
214             break;
215         case kSMARTCARD_InterfaceReadStatus:
216             /* Expecting active low present detect */
217             context->cardParams.present = (bool)((emvsim_presence_detect_status_t)(uint32_t)(
218                                                      (((EMVSIM_Type *)base)->PCSR & EMVSIM_PCSR_SPDP_MASK) >>
219                                                      EMVSIM_PCSR_SPDP_SHIFT) == kEMVSIM_DetectPinIsLow);
220             break;
221         default:
222             status = kStatus_SMARTCARD_InvalidInput;
223             break;
224     }
225 
226     return status;
227 }
228