MLK-18485 emvsim: enable CWT for ATR
authorGao Pan <pandy.gao@nxp.com>
Mon, 4 Jun 2018 07:47:21 +0000 (15:47 +0800)
committerJoakim Zhang <qiangqing.zhang@nxp.com>
Thu, 18 Apr 2019 09:41:33 +0000 (17:41 +0800)
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>
(cherry pick from: d6807ed26c531ef50c23fb8575ff07dd778de2df)
Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
drivers/mxc/sim/imx_emvsim.c

index ee8dde9..a9f86d0 100644 (file)
@@ -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
 #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(