478 lines
19 KiB
C
478 lines
19 KiB
C
/*
|
|
* The Clear BSD License
|
|
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
|
* Copyright 2016-2017 NXP
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
* are permitted (subject to the limitations in the disclaimer below) provided
|
|
* that the following conditions are met:
|
|
*
|
|
* o Redistributions of source code must retain the above copyright notice, this list
|
|
* of conditions and the following disclaimer.
|
|
*
|
|
* o Redistributions in binary form must reproduce the above copyright notice, this
|
|
* list of conditions and the following disclaimer in the documentation and/or
|
|
* other materials provided with the distribution.
|
|
*
|
|
* o Neither the name of the copyright holder nor the names of its
|
|
* contributors may be used to endorse or promote products derived from this
|
|
* software without specific prior written permission.
|
|
*
|
|
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "fsl_smartcard_phy.h"
|
|
#include "fsl_port.h"
|
|
#include "fsl_smartcard_uart.h"
|
|
/*******************************************************************************
|
|
* Definitions
|
|
******************************************************************************/
|
|
|
|
/* Component ID definition, used by tools. */
|
|
#ifndef FSL_COMPONENT_ID
|
|
#define FSL_COMPONENT_ID "platform.drivers.smartcard_phy_gpio"
|
|
#endif
|
|
|
|
/*******************************************************************************
|
|
* Prototypes
|
|
******************************************************************************/
|
|
static uint32_t smartcard_phy_gpio_InterfaceClockInit(smartcard_interface_config_t const *config, uint32_t srcClock_Hz);
|
|
static void smartcard_phy_gpio_InterfaceClockDeinit(smartcard_interface_config_t const *config);
|
|
static void smartcard_phy_gpio_ClockStart(smartcard_interface_config_t const *config);
|
|
static void smartcard_phy_gpio_ClockStop(smartcard_interface_config_t const *config);
|
|
|
|
/*******************************************************************************
|
|
* Variables
|
|
******************************************************************************/
|
|
|
|
/*******************************************************************************
|
|
* Code
|
|
******************************************************************************/
|
|
/*!
|
|
* @brief This function initializes clock module used for card clock generation
|
|
*/
|
|
static uint32_t smartcard_phy_gpio_InterfaceClockInit(smartcard_interface_config_t const *config, uint32_t srcClock_Hz)
|
|
{
|
|
assert((NULL != config));
|
|
|
|
#if defined(FSL_FEATURE_SOC_FTM_COUNT) && (FSL_FEATURE_SOC_FTM_COUNT)
|
|
assert(config->clockModule < FSL_FEATURE_SOC_FTM_COUNT);
|
|
|
|
uint32_t periph_clk_mhz = 0u;
|
|
uint16_t ftmModValue;
|
|
uint32_t ftm_base[] = FTM_BASE_ADDRS;
|
|
FTM_Type *base = (FTM_Type *)ftm_base[config->clockModule];
|
|
|
|
/* Retrieve FTM system clock */
|
|
periph_clk_mhz = srcClock_Hz / 1000000u;
|
|
/* Calculate MOD value */
|
|
ftmModValue = ((periph_clk_mhz * 1000u / 2u) / (config->smartCardClock / 1000u)) - 1u;
|
|
/* un-gate FTM peripheral clock */
|
|
switch (config->clockModule)
|
|
{
|
|
case 0u:
|
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
|
CLOCK_EnableClock(kCLOCK_Ftm0);
|
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
|
break;
|
|
#if FSL_FEATURE_SOC_FTM_COUNT > 1u
|
|
case 1u:
|
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
|
CLOCK_EnableClock(kCLOCK_Ftm1);
|
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
|
break;
|
|
#endif
|
|
#if FSL_FEATURE_SOC_FTM_COUNT > 2u
|
|
case 2u:
|
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
|
CLOCK_EnableClock(kCLOCK_Ftm2);
|
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
|
break;
|
|
#endif
|
|
#if FSL_FEATURE_SOC_FTM_COUNT > 3u
|
|
case 3u:
|
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
|
CLOCK_EnableClock(kCLOCK_Ftm3);
|
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
|
break;
|
|
#endif
|
|
default:
|
|
return 0;
|
|
break;
|
|
}
|
|
/* Initialize FTM driver */
|
|
/* Reset FTM prescaler to 'Divide by 1' to be same clock as peripheral clock */
|
|
base->SC &= ~FTM_SC_PS_MASK;
|
|
/* Disable FTM counter firstly */
|
|
base->SC &= ~FTM_SC_CLKS_MASK;
|
|
/* Set initial counter value */
|
|
base->CNTIN = 0u;
|
|
/* Set MOD value */
|
|
base->MOD = ftmModValue;
|
|
/* Set counter to operates in Up-counting mode */
|
|
base->SC &= ~FTM_SC_CPWMS_MASK;
|
|
/* Configure mode to output compare, toggle output on match */
|
|
base->CONTROLS[config->clockModuleChannel].CnSC |= FTM_CnSC_ELSA_MASK;
|
|
base->CONTROLS[config->clockModuleChannel].CnSC &= ~FTM_CnSC_ELSB_MASK;
|
|
base->CONTROLS[config->clockModuleChannel].CnSC |= FTM_CnSC_MSA_MASK;
|
|
base->CONTROLS[config->clockModuleChannel].CnSC &= ~FTM_CnSC_MSB_MASK;
|
|
/* Configure a match value to toggle output at */
|
|
base->CONTROLS[config->clockModuleChannel].CnV = 1u;
|
|
/* Re-calculate the actually configured SMARTCARD clock and return to caller */
|
|
return (uint32_t)(((periph_clk_mhz * 1000u / 2u) / (base->MOD + 1u)) * 1000u);
|
|
|
|
#elif defined(FSL_FEATURE_SOC_TPM_COUNT) && (FSL_FEATURE_SOC_TPM_COUNT)
|
|
assert(config->clockModule < FSL_FEATURE_SOC_TPM_COUNT);
|
|
|
|
uint32_t periph_clk_mhz = 0u;
|
|
uint16_t tpmModValue;
|
|
uint32_t tpm_base[] = TPM_BASE_ADDRS;
|
|
TPM_Type *base = (TPM_Type *)tpm_base[config->clockModule];
|
|
|
|
/* Retrieve TPM system clock */
|
|
periph_clk_mhz = srcClock_Hz / 1000000u;
|
|
/* Calculate MOD value */
|
|
tpmModValue = ((periph_clk_mhz * 1000u / 2u) / (config->smartCardClock / 1000u)) - 1u;
|
|
/* un-gate TPM peripheral clock */
|
|
switch (config->clockModule)
|
|
{
|
|
case 0u:
|
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
|
CLOCK_EnableClock(kCLOCK_Tpm0);
|
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
|
break;
|
|
#if FSL_FEATURE_SOC_TPM_COUNT > 1u
|
|
case 1u:
|
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
|
CLOCK_EnableClock(kCLOCK_Tpm1);
|
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
|
break;
|
|
#endif
|
|
#if FSL_FEATURE_SOC_TPM_COUNT > 2u
|
|
case 2u:
|
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
|
CLOCK_EnableClock(kCLOCK_Tpm2);
|
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
|
break;
|
|
#endif
|
|
#if FSL_FEATURE_SOC_TPM_COUNT > 3u
|
|
case 3u:
|
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
|
CLOCK_EnableClock(kCLOCK_Tpm3);
|
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
|
break;
|
|
#endif
|
|
default:
|
|
break;
|
|
}
|
|
/* Initialize TPM driver */
|
|
/* Reset TPM prescaler to 'Divide by 1' to be same clock as peripheral clock */
|
|
base->SC &= ~TPM_SC_PS_MASK;
|
|
/* Disable TPM counter firstly */
|
|
base->SC &= ~TPM_SC_CMOD_MASK;
|
|
/* Set MOD value */
|
|
base->MOD = tpmModValue;
|
|
/* Set counter to operates in Up-counting mode */
|
|
base->SC &= ~TPM_SC_CPWMS_MASK;
|
|
/* Configure mode to output compare, toggle output on match */
|
|
base->CONTROLS[config->clockModuleChannel].CnSC |= TPM_CnSC_ELSA_MASK | TPM_CnSC_MSA_MASK;
|
|
/* Configure a match value to toggle output at */
|
|
base->CONTROLS[config->clockModuleChannel].CnV = 1u;
|
|
/* Re-calculate the actually configured smartcard clock and return to caller */
|
|
return (uint32_t)(((periph_clk_mhz * 1000u / 2u) / (base->MOD + 1u)) * 1000u);
|
|
#else
|
|
return 0u;
|
|
#endif
|
|
}
|
|
|
|
/*!
|
|
* @brief This function de-initialize clock module used for card clock generation
|
|
*/
|
|
static void smartcard_phy_gpio_InterfaceClockDeinit(smartcard_interface_config_t const *config)
|
|
{
|
|
#if defined(FSL_FEATURE_SOC_FTM_COUNT) && (FSL_FEATURE_SOC_FTM_COUNT)
|
|
assert(config->clockModule < FSL_FEATURE_SOC_FTM_COUNT);
|
|
/* gate FTM peripheral clock */
|
|
switch (config->clockModule)
|
|
{
|
|
case 0u:
|
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
|
CLOCK_DisableClock(kCLOCK_Ftm0);
|
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
|
break;
|
|
#if FSL_FEATURE_SOC_FTM_COUNT > 1
|
|
case 1u:
|
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
|
CLOCK_DisableClock(kCLOCK_Ftm1);
|
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
|
break;
|
|
#endif
|
|
#if FSL_FEATURE_SOC_FTM_COUNT > 2
|
|
case 2u:
|
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
|
CLOCK_DisableClock(kCLOCK_Ftm2);
|
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
|
break;
|
|
#endif
|
|
#if FSL_FEATURE_SOC_FTM_COUNT > 3
|
|
case 3u:
|
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
|
CLOCK_DisableClock(kCLOCK_Ftm3);
|
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
|
break;
|
|
#endif
|
|
default:
|
|
break;
|
|
}
|
|
#elif defined(FSL_FEATURE_SOC_TPM_COUNT) && (FSL_FEATURE_SOC_TPM_COUNT)
|
|
assert(config->clockModule < FSL_FEATURE_SOC_TPM_COUNT);
|
|
/* gate TPM peripheral clock */
|
|
switch (config->clockModule)
|
|
{
|
|
case 0u:
|
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
|
CLOCK_DisableClock(kCLOCK_Tpm0);
|
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
|
break;
|
|
#if FSL_FEATURE_SOC_TPM_COUNT > 1
|
|
case 1u:
|
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
|
CLOCK_DisableClock(kCLOCK_Tpm1);
|
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
|
break;
|
|
#endif
|
|
#if FSL_FEATURE_SOC_TPM_COUNT > 2
|
|
case 2u:
|
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
|
CLOCK_DisableClock(kCLOCK_Tpm2);
|
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
|
break;
|
|
#endif
|
|
#if FSL_FEATURE_SOC_TPM_COUNT > 3
|
|
case 3u:
|
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
|
CLOCK_DisableClock(kCLOCK_Tpm3);
|
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
|
break;
|
|
#endif
|
|
default:
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*!
|
|
* @brief This function enables generation of SMARTCARD clock.
|
|
*/
|
|
static void smartcard_phy_gpio_ClockStart(smartcard_interface_config_t const *config)
|
|
{
|
|
#if defined(FSL_FEATURE_SOC_FTM_COUNT) && (FSL_FEATURE_SOC_FTM_COUNT)
|
|
assert(config->clockModule < FSL_FEATURE_SOC_FTM_COUNT);
|
|
|
|
uint32_t ftm_base[] = FTM_BASE_ADDRS;
|
|
FTM_Type *base = (FTM_Type *)ftm_base[config->clockModule];
|
|
|
|
/* Set clock source to start the counter : System clock */
|
|
base->SC |= FTM_SC_CLKS(1u);
|
|
#elif defined(FSL_FEATURE_SOC_TPM_COUNT) && (FSL_FEATURE_SOC_TPM_COUNT)
|
|
assert(config->clockModule < FSL_FEATURE_SOC_TPM_COUNT);
|
|
|
|
uint32_t tpm_base[] = TPM_BASE_ADDRS;
|
|
TPM_Type *base = (TPM_Type *)tpm_base[config->clockModule];
|
|
|
|
/* Activate counter by selection of incrementing TPm counter on every clock */
|
|
base->SC |= TPM_SC_CMOD(1u);
|
|
#endif
|
|
}
|
|
|
|
/*!
|
|
* @brief This function stops generation of SMARTCARD clock.
|
|
*/
|
|
static void smartcard_phy_gpio_ClockStop(smartcard_interface_config_t const *config)
|
|
{
|
|
#if defined(FSL_FEATURE_SOC_FTM_COUNT) && (FSL_FEATURE_SOC_FTM_COUNT)
|
|
assert(config->clockModule < FSL_FEATURE_SOC_FTM_COUNT);
|
|
|
|
uint32_t ftm_base[] = FTM_BASE_ADDRS;
|
|
FTM_Type *base = (FTM_Type *)ftm_base[config->clockModule];
|
|
|
|
/* Set clock source to start the counter : System clock */
|
|
base->SC &= ~FTM_SC_CLKS_MASK;
|
|
#elif defined(FSL_FEATURE_SOC_TPM_COUNT) && (FSL_FEATURE_SOC_TPM_COUNT)
|
|
assert(config->clockModule < FSL_FEATURE_SOC_TPM_COUNT);
|
|
|
|
uint32_t tpm_base[] = TPM_BASE_ADDRS;
|
|
TPM_Type *base = (TPM_Type *)tpm_base[config->clockModule];
|
|
|
|
/* Set clock source to start the counter : System clock */
|
|
base->SC &= ~TPM_SC_CMOD_MASK;
|
|
#endif
|
|
}
|
|
|
|
void SMARTCARD_PHY_GetDefaultConfig(smartcard_interface_config_t *config)
|
|
{
|
|
assert((NULL != config));
|
|
|
|
config->clockToResetDelay = SMARTCARD_INIT_DELAY_CLOCK_CYCLES;
|
|
config->vcc = kSMARTCARD_VoltageClassB3_3V;
|
|
}
|
|
|
|
status_t SMARTCARD_PHY_Init(void *base, smartcard_interface_config_t const *config, uint32_t srcClock_Hz)
|
|
{
|
|
if ((NULL == config) || (0u == srcClock_Hz))
|
|
{
|
|
return kStatus_SMARTCARD_InvalidInput;
|
|
}
|
|
|
|
/* Configure GPIO(CMDVCC, RST, INT, VSEL0, VSEL1) pins */
|
|
uint32_t gpio_base[] = GPIO_BASE_ADDRS;
|
|
|
|
/* Set RST pin to zero context and CMDVCC to high */
|
|
((GPIO_Type *)gpio_base[config->resetPort])->PCOR |= (1u << config->resetPin);
|
|
((GPIO_Type *)gpio_base[config->controlPort])->PSOR |= (1u << config->controlPin);
|
|
/* Set CMDVCC, RESET pins as output pins */
|
|
((GPIO_Type *)gpio_base[config->resetPort])->PDDR |= (1u << config->resetPin);
|
|
((GPIO_Type *)gpio_base[config->controlPort])->PDDR |= (1u << config->controlPin);
|
|
|
|
/* SMARTCARD clock initialization */
|
|
if (config->smartCardClock != smartcard_phy_gpio_InterfaceClockInit(config, srcClock_Hz))
|
|
{
|
|
return kStatus_SMARTCARD_OtherError;
|
|
}
|
|
|
|
return kStatus_SMARTCARD_Success;
|
|
}
|
|
|
|
void SMARTCARD_PHY_Deinit(void *base, smartcard_interface_config_t const *config)
|
|
{
|
|
assert((NULL != config));
|
|
|
|
/* Stop SMARTCARD clock */
|
|
smartcard_phy_gpio_InterfaceClockDeinit(config);
|
|
}
|
|
|
|
status_t SMARTCARD_PHY_Activate(void *base, smartcard_context_t *context, smartcard_reset_type_t resetType)
|
|
{
|
|
if ((NULL == context) || (NULL == context->timeDelay))
|
|
{
|
|
return kStatus_SMARTCARD_InvalidInput;
|
|
}
|
|
|
|
context->timersState.initCharTimerExpired = false;
|
|
context->resetType = resetType;
|
|
uint32_t gpio_base[] = GPIO_BASE_ADDRS;
|
|
uint32_t port_base[] = PORT_BASE_ADDRS;
|
|
|
|
if (resetType == kSMARTCARD_ColdReset)
|
|
{ /* Ensure that RST is LOW and CMD is low here so that PHY goes in normal mode */
|
|
((GPIO_Type *)gpio_base[context->interfaceConfig.resetPort])->PCOR |= (1u << context->interfaceConfig.resetPin);
|
|
((GPIO_Type *)gpio_base[context->interfaceConfig.controlPort])->PCOR |=
|
|
(1u << context->interfaceConfig.controlPin);
|
|
/* Start generation of SMARTCARD clock */
|
|
smartcard_phy_gpio_ClockStart(&context->interfaceConfig);
|
|
/* Set DATA pin from 0 to idle state */
|
|
PORT_SetPinMux((PORT_Type *)port_base[context->interfaceConfig.dataPort], context->interfaceConfig.dataPin,
|
|
(port_mux_t)context->interfaceConfig.dataPinMux);
|
|
}
|
|
else if (resetType == kSMARTCARD_WarmReset)
|
|
{ /* Ensure that card is already active */
|
|
if (!context->cardParams.active)
|
|
{ /* Card is not active;hence return */
|
|
return kStatus_SMARTCARD_CardNotActivated;
|
|
}
|
|
/* Pull RESET low to start warm Activation sequence */
|
|
((GPIO_Type *)gpio_base[context->interfaceConfig.resetPort])->PCOR |= (1u << context->interfaceConfig.resetPin);
|
|
}
|
|
else
|
|
{
|
|
return kStatus_SMARTCARD_InvalidInput;
|
|
}
|
|
/* Wait for sometime as specified by EMV before pulling RST High
|
|
* As per EMV delay <= 42000 Clock cycles
|
|
* as per PHY delay >= 1us */
|
|
uint32_t temp = (uint32_t)((float)(1 + (float)(((float)(1000u * context->interfaceConfig.clockToResetDelay)) /
|
|
((float)context->interfaceConfig.smartCardClock))));
|
|
context->timeDelay(temp);
|
|
|
|
/* Pull reset HIGH Now to mark the end of Activation sequence */
|
|
((GPIO_Type *)gpio_base[context->interfaceConfig.resetPort])->PSOR |= (1u << context->interfaceConfig.resetPin);
|
|
|
|
/* Enable external timer for TS detection time-out */
|
|
smartcard_uart_TimerStart(context->interfaceConfig.tsTimerId,
|
|
(SMARTCARD_INIT_DELAY_CLOCK_CYCLES + SMARTCARD_INIT_DELAY_CLOCK_CYCLES_ADJUSTMENT) *
|
|
(CLOCK_GetFreq(kCLOCK_CoreSysClk) / context->interfaceConfig.smartCardClock));
|
|
/* Here the card was activated */
|
|
context->cardParams.active = true;
|
|
|
|
return kStatus_SMARTCARD_Success;
|
|
}
|
|
|
|
status_t SMARTCARD_PHY_Deactivate(void *base, smartcard_context_t *context)
|
|
{
|
|
if ((NULL == context) || (NULL == context->timeDelay))
|
|
{
|
|
return kStatus_SMARTCARD_InvalidInput;
|
|
}
|
|
|
|
uint32_t gpio_base[] = GPIO_BASE_ADDRS;
|
|
uint32_t port_base[] = PORT_BASE_ADDRS;
|
|
/* Put RST low to start Deactivation sequence */
|
|
((GPIO_Type *)gpio_base[context->interfaceConfig.resetPort])->PCOR |= (1u << context->interfaceConfig.resetPin);
|
|
/* Stop SMARTCARD clock */
|
|
smartcard_phy_gpio_ClockStop(&context->interfaceConfig);
|
|
/* Put IO line down */
|
|
/* Set IO pin as GPIO & Pull it low */
|
|
((GPIO_Type *)gpio_base[context->interfaceConfig.dataPort])->PCOR |= (1u << context->interfaceConfig.dataPin);
|
|
PORT_SetPinMux((PORT_Type *)port_base[context->interfaceConfig.dataPort], context->interfaceConfig.dataPin,
|
|
kPORT_MuxAsGpio);
|
|
/* Turn off SMARTCARD Vcc */
|
|
((GPIO_Type *)gpio_base[context->interfaceConfig.controlPort])->PSOR |= (1u << context->interfaceConfig.controlPin);
|
|
/* According EMV 4.3 specification deactivation sequence should be done within 100ms.
|
|
* The period is measured from the time that RST is set to state L to the time that Vcc
|
|
* reaches 0.4 V or less.
|
|
*/
|
|
context->timeDelay(100);
|
|
/* Here the card was deactivated */
|
|
context->cardParams.active = false;
|
|
|
|
return kStatus_SMARTCARD_Success;
|
|
}
|
|
|
|
status_t SMARTCARD_PHY_Control(void *base,
|
|
smartcard_context_t *context,
|
|
smartcard_interface_control_t control,
|
|
uint32_t param)
|
|
{
|
|
if ((NULL == context))
|
|
{
|
|
return kStatus_SMARTCARD_InvalidInput;
|
|
}
|
|
|
|
switch (control)
|
|
{
|
|
case kSMARTCARD_InterfaceSetVcc:
|
|
/* Set card parameter to VCC level set by caller */
|
|
context->interfaceConfig.vcc = (smartcard_card_voltage_class_t)param;
|
|
break;
|
|
case kSMARTCARD_InterfaceSetClockToResetDelay:
|
|
/* Set interface clock to Reset delay set by caller */
|
|
context->interfaceConfig.clockToResetDelay = param;
|
|
break;
|
|
default:
|
|
return kStatus_SMARTCARD_InvalidInput;
|
|
}
|
|
|
|
return kStatus_SMARTCARD_Success;
|
|
}
|