From: Gao Pan Date: Mon, 4 Jun 2018 07:47:21 +0000 (+0800) Subject: MLK-18485 emvsim: enable CWT for ATR X-Git-Tag: rel_imx_4.19.35_1.1.0~752 X-Git-Url: https://git.somdevices.com/?a=commitdiff_plain;h=c5cf4fb6fa82ee3ac96d0164b3512a8f907f4511;p=linux.git 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 Acked-by: Fugang Duan (cherry pick from: d6807ed26c531ef50c23fb8575ff07dd778de2df) Signed-off-by: Joakim Zhang --- diff --git a/drivers/mxc/sim/imx_emvsim.c b/drivers/mxc/sim/imx_emvsim.c index ee8dde917537..a9f86d008504 100644 --- a/drivers/mxc/sim/imx_emvsim.c +++ b/drivers/mxc/sim/imx_emvsim.c @@ -73,6 +73,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 @@ -138,6 +139,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) @@ -299,7 +301,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; @@ -309,7 +311,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; @@ -319,6 +321,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; @@ -330,7 +343,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); @@ -345,10 +358,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; } @@ -394,14 +403,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; @@ -409,7 +421,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); } @@ -493,7 +506,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; @@ -530,7 +543,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) @@ -546,7 +559,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); } @@ -563,39 +576,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 */ @@ -616,9 +627,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; @@ -630,8 +641,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); } } @@ -697,7 +707,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) { @@ -735,7 +745,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); @@ -790,6 +800,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) @@ -844,12 +858,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 { @@ -983,8 +1001,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); @@ -1010,6 +1026,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; } @@ -1027,22 +1044,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; @@ -1306,9 +1307,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(