diff options
author | Gao Pan <pandy.gao@nxp.com> | 2018-06-04 15:47:21 +0800 |
---|---|---|
committer | Leonard Crestez <leonard.crestez@nxp.com> | 2018-08-24 12:41:33 +0300 |
commit | 2c56043eaee88af49edd9538e1e4da1d9f39ef78 (patch) | |
tree | f2c4df901c659c25c0b407de1a93a6a8e828715c | |
parent | c496939c95338044278d0cb8234a7ad38c460142 (diff) |
MLK-18485 emvsim: enable CWT for ATR
Enable CWT for ATR, and switch to RX_DATA_IM to detect receiving data
in fifo.
Signed-off-by: Gao Pan <pandy.gao@nxp.com>
Acked-by: Fugang Duan <fugang.duan@nxp.com>
-rw-r--r-- | drivers/mxc/sim/imx_emvsim.c | 124 |
1 files changed, 61 insertions, 63 deletions
diff --git a/drivers/mxc/sim/imx_emvsim.c b/drivers/mxc/sim/imx_emvsim.c index 774711548a5f..59f54dcd533e 100644 --- a/drivers/mxc/sim/imx_emvsim.c +++ b/drivers/mxc/sim/imx_emvsim.c @@ -72,6 +72,7 @@ #define SIM_STATE_RECEIVE_ERROR 9 #define SIM_STATE_RESET_SEQUENCY 10 +#define SIM_CNTL_GPCNT_RESET 0 #define SIM_CNTL_GPCNT_CARD_CLK 1 #define SIM_CNTL_GPCNT_RCV_CLK 2 #define SIM_CNTL_GPCNT_ETU_CLK 3 @@ -137,6 +138,7 @@ #define SIM_XMT_THRESHOLD_XTH(x) ((x & 0x0f) << 8) /* EMV_SIM_RX_STATUS */ +#define RX_DATA (1 << 4) #define RDTF (1 << 5) #define CWT_ERR (1 << 8) #define RTE (1 << 9) @@ -298,7 +300,7 @@ static void emvsim_mask_timer1_int(struct emvsim_t *emvsim) __raw_writel(reg_data, emvsim->ioaddr + EMV_SIM_TX_STATUS); } -static void emvsim_start_timer0(struct emvsim_t *emvsim, u8 clk_source) +static void emvsim_set_gpctimer0_clk(struct emvsim_t *emvsim, u8 clk_source) { u32 reg_data; @@ -308,7 +310,7 @@ static void emvsim_start_timer0(struct emvsim_t *emvsim, u8 clk_source) writel(reg_data, emvsim->ioaddr + EMV_SIM_CLKCFG); } -static void emvsim_start_timer1(struct emvsim_t *emvsim, u8 clk_source) +static void emvsim_set_gpctimer1_clk(struct emvsim_t *emvsim, u8 clk_source) { u32 reg_data; @@ -318,6 +320,17 @@ static void emvsim_start_timer1(struct emvsim_t *emvsim, u8 clk_source) writel(reg_data, emvsim->ioaddr + EMV_SIM_CLKCFG); } +static void emvsim_reset_gpctimer(struct emvsim_t *emvsim) +{ + emvsim_set_gpctimer0_clk(emvsim, SIM_CNTL_GPCNT_RESET); + emvsim_set_gpctimer1_clk(emvsim, SIM_CNTL_GPCNT_RESET); + + /* need a tx_en posedge to update gpctimer0 clk */ + emvsim_set_tx(emvsim, 0); + emvsim_set_tx(emvsim, 1); + emvsim_set_tx(emvsim, 0); +} + static int emvsim_reset_low_timing(struct emvsim_t *emvsim, u32 clock_cycle) { int errval = 0; @@ -329,7 +342,7 @@ static int emvsim_reset_low_timing(struct emvsim_t *emvsim, u32 clock_cycle) emvsim_mask_timer0_int(emvsim); __raw_writel(clock_cycle, emvsim->ioaddr + EMV_SIM_GPCNT0_VAL); - emvsim_start_timer0(emvsim, SIM_CNTL_GPCNT_CARD_CLK); + emvsim_set_gpctimer0_clk(emvsim, SIM_CNTL_GPCNT_CARD_CLK); emvsim_set_tx(emvsim, 1); reg_data = __raw_readl(emvsim->ioaddr + EMV_SIM_INT_MASK); @@ -344,10 +357,6 @@ static int emvsim_reset_low_timing(struct emvsim_t *emvsim, u32 clock_cycle) errval = -SIM_E_TIMEOUT; } - reg_data = __raw_readl(emvsim->ioaddr + EMV_SIM_INT_MASK); - reg_data |= GPCNT0_IM; - __raw_writel(reg_data, emvsim->ioaddr + EMV_SIM_INT_MASK); - return errval; } @@ -393,14 +402,17 @@ static void emvsim_receive_atr_set(struct emvsim_t *emvsim) { u32 reg_data; - emvsim_mask_timer0_int(emvsim); - emvsim_mask_timer1_int(emvsim); - __raw_writel(ATR_MAX_DELAY_CLK, emvsim->ioaddr + EMV_SIM_GPCNT0_VAL); - __raw_writel(0xFFFF, emvsim->ioaddr + EMV_SIM_GPCNT1_VAL); - emvsim_start_timer0(emvsim, SIM_CNTL_GPCNT_CARD_CLK); - emvsim_start_timer1(emvsim, SIM_CNTL_GPCNT_ETU_CLK); + __raw_writel(0x0, emvsim->ioaddr + EMV_SIM_GPCNT1_VAL); + emvsim_set_gpctimer1_clk(emvsim, SIM_CNTL_GPCNT_ETU_CLK); emvsim_set_rx(emvsim, 1); + /*Set the cwt timer.Refer the setting of ATR on EMV4.3 book*/ + __raw_writel(ATR_MAX_CWT, emvsim->ioaddr + EMV_SIM_CWT_VAL); + + reg_data = __raw_readl(emvsim->ioaddr + EMV_SIM_CTRL); + reg_data |= CWT_EN; + __raw_writel(reg_data, emvsim->ioaddr + EMV_SIM_CTRL); + emvsim_set_nack(emvsim, 0); emvsim->errval = 0; emvsim->rcv_count = 0; @@ -408,7 +420,8 @@ static void emvsim_receive_atr_set(struct emvsim_t *emvsim) emvsim->state = SIM_STATE_ATR_RECEIVING; reg_data = __raw_readl(emvsim->ioaddr + EMV_SIM_INT_MASK); - reg_data &= ~(RDT_IM | GPCNT0_IM); + reg_data |= CWT_ERR_IM; + reg_data &= ~(RX_DATA_IM | GPCNT0_IM); __raw_writel(reg_data, emvsim->ioaddr + EMV_SIM_INT_MASK); } @@ -492,7 +505,7 @@ static void emvsim_tx_irq_enable(struct emvsim_t *emvsim) __raw_writel(reg_val, emvsim->ioaddr + EMV_SIM_RX_STATUS); reg_val = __raw_readl(emvsim->ioaddr + EMV_SIM_INT_MASK); - reg_val |= CWT_ERR_IM | BWT_ERR_IM | RX_DATA_IM | RDT_IM; + reg_val |= CWT_ERR_IM | BWT_ERR_IM | RX_DATA_IM | RX_DATA_IM; if (emvsim->xmt_remaining != 0) { reg_val &= ~TDT_IM; @@ -529,7 +542,7 @@ static void emvsim_rx_irq_enable(struct emvsim_t *emvsim) reg_data = __raw_readl(emvsim->ioaddr + EMV_SIM_INT_MASK); reg_data |= (TC_IM | TDT_IM | TNACK_IM); - reg_data &= ~(RDT_IM | CWT_ERR_IM | BWT_ERR_IM); + reg_data &= ~(RX_DATA_IM | CWT_ERR_IM | BWT_ERR_IM); if (emvsim->protocol_type == SIM_PROTOCOL_T0 || emvsim->nack_enable != 0) @@ -545,7 +558,7 @@ static void emvsim_rx_irq_disable(struct emvsim_t *emvsim) u32 reg_val; reg_val = __raw_readl(emvsim->ioaddr + EMV_SIM_INT_MASK); - reg_val |= (RDT_IM | CWT_ERR_IM | BWT_ERR_IM | RNACK_IM); + reg_val |= (RX_DATA_IM | CWT_ERR_IM | BWT_ERR_IM | RNACK_IM); __raw_writel(reg_val, emvsim->ioaddr + EMV_SIM_INT_MASK); } @@ -562,39 +575,37 @@ static irqreturn_t emvsim_irq_handler(int irq, void *dev_id) if (emvsim->state == SIM_STATE_ATR_RECEIVING && emvsim->checking_ts_timing == 1) { - if ((tx_status & GPCNT0_TO) && !(rx_status & RDTF)) { + if ((tx_status & GPCNT0_TO) && !(rx_status & RX_DATA)) { reg_data = __raw_readl(emvsim->ioaddr + EMV_SIM_CTRL); reg_data &= ~CWT_EN; __raw_writel(reg_data, emvsim->ioaddr + EMV_SIM_CTRL); - reg_data = __raw_readl(emvsim->ioaddr + - EMV_SIM_INT_MASK); - reg_data |= (GPCNT0_IM | CWT_ERR_IM | RDT_IM); - __raw_writel(reg_data, - emvsim->ioaddr + EMV_SIM_INT_MASK); + reg_data = __raw_readl(emvsim->ioaddr + EMV_SIM_INT_MASK); + reg_data |= (GPCNT0_IM | CWT_ERR_IM | RX_DATA_IM); + __raw_writel(reg_data, emvsim->ioaddr + EMV_SIM_INT_MASK); emvsim->errval = SIM_ERROR_ATR_DELAY; complete(&emvsim->xfer_done); emvsim->checking_ts_timing = 0; - } else if (rx_status & RDTF) { - u8 rdt = SIM_RX_FIFO_DEPTH >> 1; + } else if (rx_status & RX_DATA) { + u8 rdt = 1; emvsim_mask_timer0_int(emvsim); - emvsim_rcv_read_fifo(emvsim); /* ATR each received byte will cost 12 ETU */ reg_data = ATR_MAX_DURATION - emvsim->rcv_count * 12; - __raw_writel(reg_data, - emvsim->ioaddr + EMV_SIM_GPCNT1_VAL); + __raw_writel(reg_data, emvsim->ioaddr + EMV_SIM_GPCNT1_VAL); - reg_data = __raw_readl(emvsim->ioaddr + - EMV_SIM_INT_MASK); - reg_data &= ~(GPCNT1_IM | CWT_ERR_IM | RDT_IM); - __raw_writel(reg_data, - emvsim->ioaddr + EMV_SIM_INT_MASK); + reg_data = __raw_readl(emvsim->ioaddr + EMV_SIM_INT_MASK); + reg_data &= ~(GPCNT1_IM | CWT_ERR_IM | RX_DATA_IM); + __raw_writel(reg_data, emvsim->ioaddr + EMV_SIM_INT_MASK); + emvsim_rcv_read_fifo(emvsim); + + reg_data = __raw_readl(emvsim->ioaddr + EMV_SIM_TX_STATUS); + reg_data |= GPCNT1_TO; + __raw_writel(reg_data, emvsim->ioaddr + EMV_SIM_TX_STATUS); - reg_data = SIM_RCV_THRESHOLD_RTH(0) | - SIM_RCV_THRESHOLD_RDT(rdt); + reg_data = SIM_RCV_THRESHOLD_RTH(0) | SIM_RCV_THRESHOLD_RDT(rdt); __raw_writel(reg_data, emvsim->ioaddr + EMV_SIM_RX_THD); /* ATR has arrived as EMV demands */ @@ -615,9 +626,9 @@ static irqreturn_t emvsim_irq_handler(int irq, void *dev_id) reg_data = __raw_readl(emvsim->ioaddr + EMV_SIM_INT_MASK); - reg_data |= (GPCNT1_IM | CWT_ERR_IM | RDT_IM); - __raw_writel(reg_data, - emvsim->ioaddr + EMV_SIM_INT_MASK); + reg_data |= (GPCNT1_IM | CWT_ERR_IM | RX_DATA_IM | GPCNT0_IM); + __raw_writel(reg_data, emvsim->ioaddr + + EMV_SIM_INT_MASK); if (tx_status & GPCNT1_TO) emvsim->errval |= SIM_ERROR_ATR_TIMEROUT; @@ -629,8 +640,7 @@ static irqreturn_t emvsim_irq_handler(int irq, void *dev_id) emvsim->state = SIM_STATE_ATR_RECEIVED; complete(&emvsim->xfer_done); - } else if (rx_status & RDTF) { - /* Receive Data Threshold Interrupt */ + } else if (rx_status & RX_DATA) { emvsim_rcv_read_fifo(emvsim); } } @@ -696,7 +706,7 @@ static irqreturn_t emvsim_irq_handler(int irq, void *dev_id) complete(&emvsim->xfer_done); } - if (rx_status & RDTF) { + if (rx_status & RX_DATA) { emvsim_rcv_read_fifo(emvsim); if (emvsim->is_fixed_len_rec && emvsim->rcv_count >= emvsim->expected_rcv_cnt) { @@ -734,7 +744,7 @@ static irqreturn_t emvsim_irq_handler(int irq, void *dev_id) (tx_status & GPCNT0_TO)) { complete(&emvsim->xfer_done); emvsim_mask_timer0_int(emvsim); - } else if (rx_status & RDTF) { + } else if (rx_status & RX_DATA) { dev_err(emvsim_dev.parent, "unexpected status %d\n", emvsim->state); emvsim_rcv_read_fifo(emvsim); @@ -789,6 +799,10 @@ static void emvsim_cold_reset_sequency(struct emvsim_t *emvsim) reg_data = __raw_readl(emvsim->ioaddr + EMV_SIM_PCSR); reg_data |= SRST; __raw_writel(reg_data, emvsim->ioaddr + EMV_SIM_PCSR); + + emvsim_mask_timer0_int(emvsim); + __raw_writel(ATR_MAX_DELAY_CLK, emvsim->ioaddr + + EMV_SIM_GPCNT0_VAL); }; static void emvsim_deactivate(struct emvsim_t *emvsim) @@ -843,12 +857,16 @@ static void emvsim_warm_reset_sequency(struct emvsim_t *emvsim) reg_data = __raw_readl(emvsim->ioaddr + EMV_SIM_PCSR); reg_data |= SRST; __raw_writel(reg_data, emvsim->ioaddr + EMV_SIM_PCSR); + + emvsim_mask_timer0_int(emvsim); + __raw_writel(ATR_MAX_DELAY_CLK, emvsim->ioaddr + EMV_SIM_GPCNT0_VAL); } static void emvsim_warm_reset(struct emvsim_t *emvsim) { if (emvsim->present != SIM_PRESENT_REMOVED) { emvsim_data_reset(emvsim); + emvsim_reset_gpctimer(emvsim); emvsim_warm_reset_sequency(emvsim); emvsim_receive_atr_set(emvsim); } else { @@ -982,8 +1000,6 @@ static int emvsim_xmt_start(struct emvsim_t *emvsim) { u32 reg_val; - emvsim->state = SIM_STATE_XMTING; - emvsim_set_baud_rate(emvsim); if (emvsim->protocol_type == SIM_PROTOCOL_T0) { emvsim_set_nack(emvsim, 1); @@ -1009,6 +1025,7 @@ static int emvsim_xmt_start(struct emvsim_t *emvsim) emvsim_set_tx(emvsim, 1); emvsim_xmt_fill_fifo(emvsim); emvsim_tx_irq_enable(emvsim); + emvsim->state = SIM_STATE_XMTING; return 0; } @@ -1026,22 +1043,6 @@ static void emvsim_flush_fifo(struct emvsim_t *emvsim, u8 flush_tx, u8 flush_rx) __raw_writel(reg_val, emvsim->ioaddr + EMV_SIM_CTRL); } -static void emvsim_change_rcv_threshold(struct emvsim_t *emvsim) -{ - u32 rx_threshold = 0; - u32 reg_val = 0; - - if (emvsim->is_fixed_len_rec) { - rx_threshold = emvsim->expected_rcv_cnt - emvsim->rcv_count; - if (rx_threshold > (SIM_RX_FIFO_DEPTH >> 1)) - rx_threshold = (SIM_RX_FIFO_DEPTH >> 1); - reg_val = __raw_readl(emvsim->ioaddr + EMV_SIM_RX_THD); - reg_val &= ~(SIM_RCV_THRESHOLD_RDT_MASK); - reg_val |= SIM_RCV_THRESHOLD_RDT(rx_threshold); - __raw_writel(reg_val, emvsim->ioaddr + EMV_SIM_RX_THD); - } -} - static void emvsim_start_rcv(struct emvsim_t *emvsim) { int rdt = 1; @@ -1305,9 +1306,6 @@ static long emvsim_ioctl(struct file *file, emvsim_start_rcv(emvsim); spin_lock_irqsave(&emvsim->lock, flags); - if (emvsim->is_fixed_len_rec && - emvsim->rcv_count < emvsim->expected_rcv_cnt) - emvsim_change_rcv_threshold(emvsim); spin_unlock_irqrestore(&emvsim->lock, flags); emvsim->timeout = RX_TIMEOUT * HZ; timeout = wait_for_completion_interruptible_timeout( |