]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/nfc/trf7970a.c
Merge tag 'qcom-dt-for-3.18-3' of git://git.kernel.org/pub/scm/linux/kernel/git/galak...
[karo-tx-linux.git] / drivers / nfc / trf7970a.c
index 0f09278ec37a0a26db878108c3906414ff4cab1b..d2ccd289064739a17c9463e4698eab84ce716b64 100644 (file)
@@ -62,7 +62,7 @@
  * way to abort a command that's already been sent to the tag is so turn
  * off power to the tag.  If we do that, though, we'd have to go through
  * the entire anticollision procedure again but the digital layer doesn't
- * support that.  So, if an abort is received before trf7970a_in_send_cmd()
+ * support that.  So, if an abort is received before trf7970a_send_cmd()
  * has sent the command to the tag, it simply returns -ECANCELED.  If the
  * command has already been sent to the tag, then the driver continues
  * normally and recieves the response data (or error) but just before
 #define TRF7970A_SUPPORTED_PROTOCOLS \
                (NFC_PROTO_MIFARE_MASK | NFC_PROTO_ISO14443_MASK |      \
                 NFC_PROTO_ISO14443_B_MASK | NFC_PROTO_FELICA_MASK | \
-                NFC_PROTO_ISO15693_MASK)
+                NFC_PROTO_ISO15693_MASK | NFC_PROTO_NFC_DEP_MASK)
 
 #define TRF7970A_AUTOSUSPEND_DELAY             30000 /* 30 seconds */
 
 /* TX length is 3 nibbles long ==> 4KB - 1 bytes max */
 #define TRF7970A_TX_MAX                                (4096 - 1)
 
+#define TRF7970A_WAIT_FOR_TX_IRQ               20
 #define TRF7970A_WAIT_FOR_RX_DATA_TIMEOUT      20
 #define TRF7970A_WAIT_FOR_FIFO_DRAIN_TIMEOUT   20
 #define TRF7970A_WAIT_TO_ISSUE_ISO15693_EOF    40
 #define TRF7970A_ISO_CTRL_14443B_848           0x0f
 #define TRF7970A_ISO_CTRL_FELICA_212           0x1a
 #define TRF7970A_ISO_CTRL_FELICA_424           0x1b
+#define TRF7970A_ISO_CTRL_NFC_NFCA_106         0x01
+#define TRF7970A_ISO_CTRL_NFC_NFCF_212         0x02
+#define TRF7970A_ISO_CTRL_NFC_NFCF_424         0x03
+#define TRF7970A_ISO_CTRL_NFC_CE_14443A                0x00
+#define TRF7970A_ISO_CTRL_NFC_CE_14443B                0x01
+#define TRF7970A_ISO_CTRL_NFC_CE               BIT(2)
+#define TRF7970A_ISO_CTRL_NFC_ACTIVE           BIT(3)
+#define TRF7970A_ISO_CTRL_NFC_INITIATOR                BIT(4)
+#define TRF7970A_ISO_CTRL_NFC_NFC_CE_MODE      BIT(5)
 #define TRF7970A_ISO_CTRL_RFID                 BIT(5)
 #define TRF7970A_ISO_CTRL_DIR_MODE             BIT(6)
 #define TRF7970A_ISO_CTRL_RX_CRC_N             BIT(7)  /* true == No CRC */
 #define TRF7970A_MODULATOR_EN_OOK              BIT(6)
 #define TRF7970A_MODULATOR_27MHZ               BIT(7)
 
+#define TRF7970A_RX_SPECIAL_SETTINGS_NO_LIM    BIT(0)
+#define TRF7970A_RX_SPECIAL_SETTINGS_AGCR      BIT(1)
+#define TRF7970A_RX_SPECIAL_SETTINGS_GD_0DB    (0x0 << 2)
+#define TRF7970A_RX_SPECIAL_SETTINGS_GD_5DB    (0x1 << 2)
+#define TRF7970A_RX_SPECIAL_SETTINGS_GD_10DB   (0x2 << 2)
+#define TRF7970A_RX_SPECIAL_SETTINGS_GD_15DB   (0x3 << 2)
+#define TRF7970A_RX_SPECIAL_SETTINGS_HBT       BIT(4)
+#define TRF7970A_RX_SPECIAL_SETTINGS_M848      BIT(5)
+#define TRF7970A_RX_SPECIAL_SETTINGS_C424      BIT(6)
+#define TRF7970A_RX_SPECIAL_SETTINGS_C212      BIT(7)
+
+#define TRF7970A_REG_IO_CTRL_VRS(v)            ((v) & 0x07)
+#define TRF7970A_REG_IO_CTRL_IO_LOW            BIT(5)
+#define TRF7970A_REG_IO_CTRL_EN_EXT_PA         BIT(6)
+#define TRF7970A_REG_IO_CTRL_AUTO_REG          BIT(7)
+
 /* IRQ Status Register Bits */
 #define TRF7970A_IRQ_STATUS_NORESP             BIT(0) /* ISO15693 only */
+#define TRF7970A_IRQ_STATUS_NFC_COL_ERROR      BIT(0)
 #define TRF7970A_IRQ_STATUS_COL                        BIT(1)
 #define TRF7970A_IRQ_STATUS_FRAMING_EOF_ERROR  BIT(2)
+#define TRF7970A_IRQ_STATUS_NFC_RF             BIT(2)
 #define TRF7970A_IRQ_STATUS_PARITY_ERROR       BIT(3)
+#define TRF7970A_IRQ_STATUS_NFC_SDD            BIT(3)
 #define TRF7970A_IRQ_STATUS_CRC_ERROR          BIT(4)
+#define TRF7970A_IRQ_STATUS_NFC_PROTO_ERROR    BIT(4)
 #define TRF7970A_IRQ_STATUS_FIFO               BIT(5)
 #define TRF7970A_IRQ_STATUS_SRX                        BIT(6)
 #define TRF7970A_IRQ_STATUS_TX                 BIT(7)
 #define TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLL_16      0x2
 #define TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLL_32      0x3
 
+#define TRF7970A_NFC_LOW_FIELD_LEVEL_RFDET(v)  ((v) & 0x07)
+#define TRF7970A_NFC_LOW_FIELD_LEVEL_CLEX_DIS  BIT(7)
+
+#define TRF7970A_NFC_TARGET_LEVEL_RFDET(v)     ((v) & 0x07)
+#define TRF7970A_NFC_TARGET_LEVEL_HI_RF                BIT(3)
+#define TRF7970A_NFC_TARGET_LEVEL_SDD_EN       BIT(3)
+#define TRF7970A_NFC_TARGET_LEVEL_LD_S_4BYTES  (0x0 << 6)
+#define TRF7970A_NFC_TARGET_LEVEL_LD_S_7BYTES  (0x1 << 6)
+#define TRF7970A_NFC_TARGET_LEVEL_LD_S_10BYTES (0x2 << 6)
+
+#define TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_106                BIT(0)
+#define TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_212                BIT(1)
+#define TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_424                (BIT(0) | BIT(1))
+#define TRF79070A_NFC_TARGET_PROTOCOL_PAS_14443B       BIT(2)
+#define TRF79070A_NFC_TARGET_PROTOCOL_PAS_106          BIT(3)
+#define TRF79070A_NFC_TARGET_PROTOCOL_FELICA           BIT(4)
+#define TRF79070A_NFC_TARGET_PROTOCOL_RF_L             BIT(6)
+#define TRF79070A_NFC_TARGET_PROTOCOL_RF_H             BIT(7)
+
+#define TRF79070A_NFC_TARGET_PROTOCOL_106A             \
+        (TRF79070A_NFC_TARGET_PROTOCOL_RF_H |          \
+         TRF79070A_NFC_TARGET_PROTOCOL_RF_L |          \
+         TRF79070A_NFC_TARGET_PROTOCOL_PAS_106 |       \
+         TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_106)
+
+#define TRF79070A_NFC_TARGET_PROTOCOL_106B             \
+        (TRF79070A_NFC_TARGET_PROTOCOL_RF_H |          \
+         TRF79070A_NFC_TARGET_PROTOCOL_RF_L |          \
+         TRF79070A_NFC_TARGET_PROTOCOL_PAS_14443B |    \
+         TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_106)
+
+#define TRF79070A_NFC_TARGET_PROTOCOL_212F             \
+        (TRF79070A_NFC_TARGET_PROTOCOL_RF_H |          \
+         TRF79070A_NFC_TARGET_PROTOCOL_RF_L |          \
+         TRF79070A_NFC_TARGET_PROTOCOL_FELICA |        \
+         TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_212)
+
+#define TRF79070A_NFC_TARGET_PROTOCOL_424F             \
+        (TRF79070A_NFC_TARGET_PROTOCOL_RF_H |          \
+         TRF79070A_NFC_TARGET_PROTOCOL_RF_L |          \
+         TRF79070A_NFC_TARGET_PROTOCOL_FELICA |        \
+         TRF79070A_NFC_TARGET_PROTOCOL_NFCBR_424)
+
 #define TRF7970A_FIFO_STATUS_OVERFLOW          BIT(7)
 
 /* NFC (ISO/IEC 14443A) Type 2 Tag commands */
@@ -344,6 +417,8 @@ enum trf7970a_state {
        TRF7970A_ST_WAIT_FOR_RX_DATA,
        TRF7970A_ST_WAIT_FOR_RX_DATA_CONT,
        TRF7970A_ST_WAIT_TO_ISSUE_EOF,
+       TRF7970A_ST_LISTENING,
+       TRF7970A_ST_LISTENING_MD,
        TRF7970A_ST_MAX
 };
 
@@ -354,6 +429,7 @@ struct trf7970a {
        struct regulator                *regulator;
        struct nfc_digital_dev          *ddev;
        u32                             quirks;
+       bool                            is_initiator;
        bool                            aborting;
        struct sk_buff                  *tx_skb;
        struct sk_buff                  *rx_skb;
@@ -367,6 +443,7 @@ struct trf7970a {
        unsigned int                    guard_time;
        int                             technology;
        int                             framing;
+       u8                              md_rf_tech;
        u8                              tx_cmd;
        bool                            issue_eof;
        int                             en2_gpio;
@@ -474,6 +551,58 @@ static int trf7970a_read_irqstatus(struct trf7970a *trf, u8 *status)
        return ret;
 }
 
+static int trf7970a_read_target_proto(struct trf7970a *trf, u8 *target_proto)
+{
+       int ret;
+       u8 buf[2];
+       u8 addr;
+
+       addr = TRF79070A_NFC_TARGET_PROTOCOL | TRF7970A_CMD_BIT_RW |
+               TRF7970A_CMD_BIT_CONTINUOUS;
+
+       ret = spi_write_then_read(trf->spi, &addr, 1, buf, 2);
+       if (ret)
+               dev_err(trf->dev, "%s - target_proto: Read failed: %d\n",
+                               __func__, ret);
+       else
+               *target_proto = buf[0];
+
+       return ret;
+}
+
+static int trf7970a_mode_detect(struct trf7970a *trf, u8 *rf_tech)
+{
+       int ret;
+       u8 target_proto, tech;
+
+       ret = trf7970a_read_target_proto(trf, &target_proto);
+       if (ret)
+               return ret;
+
+       switch (target_proto) {
+       case TRF79070A_NFC_TARGET_PROTOCOL_106A:
+               tech = NFC_DIGITAL_RF_TECH_106A;
+               break;
+       case TRF79070A_NFC_TARGET_PROTOCOL_106B:
+               tech = NFC_DIGITAL_RF_TECH_106B;
+               break;
+       case TRF79070A_NFC_TARGET_PROTOCOL_212F:
+               tech = NFC_DIGITAL_RF_TECH_212F;
+               break;
+       case TRF79070A_NFC_TARGET_PROTOCOL_424F:
+               tech = NFC_DIGITAL_RF_TECH_424F;
+               break;
+       default:
+               dev_dbg(trf->dev, "%s - mode_detect: target_proto: 0x%x\n",
+                               __func__, target_proto);
+               return -EIO;
+       }
+
+       *rf_tech = tech;
+
+       return ret;
+}
+
 static void trf7970a_send_upstream(struct trf7970a *trf)
 {
        dev_kfree_skb_any(trf->tx_skb);
@@ -506,6 +635,8 @@ static void trf7970a_send_err_upstream(struct trf7970a *trf, int errno)
 {
        dev_dbg(trf->dev, "Error - state: %d, errno: %d\n", trf->state, errno);
 
+       cancel_delayed_work(&trf->timeout_work);
+
        kfree_skb(trf->rx_skb);
        trf->rx_skb = ERR_PTR(errno);
 
@@ -553,7 +684,11 @@ static int trf7970a_transmit(struct trf7970a *trf, struct sk_buff *skb,
                        timeout = TRF7970A_WAIT_TO_ISSUE_ISO15693_EOF;
                } else {
                        trf->state = TRF7970A_ST_WAIT_FOR_RX_DATA;
-                       timeout = trf->timeout;
+
+                       if (!trf->timeout)
+                               timeout = TRF7970A_WAIT_FOR_TX_IRQ;
+                       else
+                               timeout = trf->timeout;
                }
        }
 
@@ -687,7 +822,7 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id)
 {
        struct trf7970a *trf = dev_id;
        int ret;
-       u8 status, fifo_bytes;
+       u8 status, fifo_bytes, iso_ctrl;
 
        mutex_lock(&trf->lock);
 
@@ -713,12 +848,12 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id)
        switch (trf->state) {
        case TRF7970A_ST_IDLE:
        case TRF7970A_ST_IDLE_RX_BLOCKED:
-               /* If getting interrupts caused by RF noise, turn off the
-                * receiver to avoid unnecessary interrupts.  It will be
-                * turned back on in trf7970a_in_send_cmd() when the next
-                * command is issued.
+               /* If initiator and getting interrupts caused by RF noise,
+                * turn off the receiver to avoid unnecessary interrupts.
+                * It will be turned back on in trf7970a_send_cmd() when
+                * the next command is issued.
                 */
-               if (status & TRF7970A_IRQ_STATUS_ERROR) {
+               if (trf->is_initiator && (status & TRF7970A_IRQ_STATUS_ERROR)) {
                        trf7970a_cmd(trf, TRF7970A_CMD_BLOCK_RX);
                        trf->state = TRF7970A_ST_IDLE_RX_BLOCKED;
                }
@@ -750,8 +885,58 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id)
                                trf7970a_send_err_upstream(trf, ret);
                        else if (!fifo_bytes)
                                trf7970a_cmd(trf, TRF7970A_CMD_FIFO_RESET);
-               } else if (status == TRF7970A_IRQ_STATUS_TX) {
+               } else if ((status == TRF7970A_IRQ_STATUS_TX) ||
+                               (!trf->is_initiator &&
+                                (status == (TRF7970A_IRQ_STATUS_TX |
+                                            TRF7970A_IRQ_STATUS_NFC_RF)))) {
                        trf7970a_cmd(trf, TRF7970A_CMD_FIFO_RESET);
+
+                       if (!trf->timeout) {
+                               trf->ignore_timeout = !cancel_delayed_work(
+                                               &trf->timeout_work);
+                               trf->rx_skb = ERR_PTR(0);
+                               trf7970a_send_upstream(trf);
+                               break;
+                       }
+
+                       if (trf->is_initiator)
+                               break;
+
+                       iso_ctrl = trf->iso_ctrl;
+
+                       switch (trf->framing) {
+                       case NFC_DIGITAL_FRAMING_NFCA_STANDARD:
+                               trf->tx_cmd = TRF7970A_CMD_TRANSMIT_NO_CRC;
+                               iso_ctrl |= TRF7970A_ISO_CTRL_RX_CRC_N;
+                               trf->iso_ctrl = 0xff; /* Force ISO_CTRL write */
+                               break;
+                       case NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A:
+                               trf->tx_cmd = TRF7970A_CMD_TRANSMIT;
+                               iso_ctrl &= ~TRF7970A_ISO_CTRL_RX_CRC_N;
+                               trf->iso_ctrl = 0xff; /* Force ISO_CTRL write */
+                               break;
+                       case NFC_DIGITAL_FRAMING_NFCA_ANTICOL_COMPLETE:
+                               ret = trf7970a_write(trf,
+                                       TRF7970A_SPECIAL_FCN_REG1,
+                                       TRF7970A_SPECIAL_FCN_REG1_14_ANTICOLL);
+                               if (ret)
+                                       goto err_unlock_exit;
+
+                               trf->special_fcn_reg1 =
+                                       TRF7970A_SPECIAL_FCN_REG1_14_ANTICOLL;
+                               break;
+                       default:
+                               break;
+                       }
+
+                       if (iso_ctrl != trf->iso_ctrl) {
+                               ret = trf7970a_write(trf, TRF7970A_ISO_CTRL,
+                                               iso_ctrl);
+                               if (ret)
+                                       goto err_unlock_exit;
+
+                               trf->iso_ctrl = iso_ctrl;
+                       }
                } else {
                        trf7970a_send_err_upstream(trf, -EIO);
                }
@@ -760,11 +945,37 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id)
                if (status != TRF7970A_IRQ_STATUS_TX)
                        trf7970a_send_err_upstream(trf, -EIO);
                break;
+       case TRF7970A_ST_LISTENING:
+               if (status & TRF7970A_IRQ_STATUS_SRX) {
+                       trf->ignore_timeout =
+                               !cancel_delayed_work(&trf->timeout_work);
+                       trf7970a_drain_fifo(trf, status);
+               } else if (!(status & TRF7970A_IRQ_STATUS_NFC_RF)) {
+                       trf7970a_send_err_upstream(trf, -EIO);
+               }
+               break;
+       case TRF7970A_ST_LISTENING_MD:
+               if (status & TRF7970A_IRQ_STATUS_SRX) {
+                       trf->ignore_timeout =
+                               !cancel_delayed_work(&trf->timeout_work);
+
+                       ret = trf7970a_mode_detect(trf, &trf->md_rf_tech);
+                       if (ret) {
+                               trf7970a_send_err_upstream(trf, ret);
+                       } else {
+                               trf->state = TRF7970A_ST_LISTENING;
+                               trf7970a_drain_fifo(trf, status);
+                       }
+               } else if (!(status & TRF7970A_IRQ_STATUS_NFC_RF)) {
+                       trf7970a_send_err_upstream(trf, -EIO);
+               }
+               break;
        default:
                dev_err(trf->dev, "%s - Driver in invalid state: %d\n",
                                __func__, trf->state);
        }
 
+err_unlock_exit:
        mutex_unlock(&trf->lock);
        return IRQ_HANDLED;
 }
@@ -838,11 +1049,6 @@ static int trf7970a_init(struct trf7970a *trf)
 
        trf->modulator_sys_clk_ctrl = 0;
 
-       /* Must clear NFC Target Detection Level reg due to erratum */
-       ret = trf7970a_write(trf, TRF7970A_NFC_TARGET_LEVEL, 0);
-       if (ret)
-               goto err_out;
-
        ret = trf7970a_write(trf, TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS,
                        TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLH_96 |
                        TRF7970A_ADJUTABLE_FIFO_IRQ_LEVELS_WLL_32);
@@ -943,6 +1149,8 @@ static int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on)
                        /* FALLTHROUGH */
                case TRF7970A_ST_IDLE:
                case TRF7970A_ST_IDLE_RX_BLOCKED:
+               case TRF7970A_ST_WAIT_FOR_RX_DATA:
+               case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT:
                        trf7970a_switch_rf_off(trf);
                }
        }
@@ -990,6 +1198,14 @@ static int trf7970a_in_config_rf_tech(struct trf7970a *trf, int tech)
 
        trf->technology = tech;
 
+       /* If in initiator mode and not changing the RF tech due to a
+        * PSL sequence (indicated by 'trf->iso_ctrl == 0xff' from
+        * trf7970a_init()), clear the NFC Target Detection Level register
+        * due to erratum.
+        */
+       if (trf->iso_ctrl == 0xff)
+               ret = trf7970a_write(trf, TRF7970A_NFC_TARGET_LEVEL, 0);
+
        return ret;
 }
 
@@ -1048,6 +1264,8 @@ static int trf7970a_in_config_framing(struct trf7970a *trf, int framing)
        case NFC_DIGITAL_FRAMING_NFCF_T3T:
        case NFC_DIGITAL_FRAMING_ISO15693_INVENTORY:
        case NFC_DIGITAL_FRAMING_ISO15693_T5T:
+       case NFC_DIGITAL_FRAMING_NFCA_NFC_DEP:
+       case NFC_DIGITAL_FRAMING_NFCF_NFC_DEP:
                trf->tx_cmd = TRF7970A_CMD_TRANSMIT;
                iso_ctrl &= ~TRF7970A_ISO_CTRL_RX_CRC_N;
                break;
@@ -1109,6 +1327,8 @@ static int trf7970a_in_configure_hw(struct nfc_digital_dev *ddev, int type,
 
        mutex_lock(&trf->lock);
 
+       trf->is_initiator = true;
+
        if ((trf->state == TRF7970A_ST_PWR_OFF) ||
                        (trf->state == TRF7970A_ST_RF_OFF)) {
                ret = trf7970a_switch_rf_on(trf);
@@ -1218,7 +1438,7 @@ static int trf7970a_per_cmd_config(struct trf7970a *trf, struct sk_buff *skb)
        return 0;
 }
 
-static int trf7970a_in_send_cmd(struct nfc_digital_dev *ddev,
+static int trf7970a_send_cmd(struct nfc_digital_dev *ddev,
                struct sk_buff *skb, u16 timeout,
                nfc_digital_cmd_complete_t cb, void *arg)
 {
@@ -1251,12 +1471,14 @@ static int trf7970a_in_send_cmd(struct nfc_digital_dev *ddev,
                goto out_err;
        }
 
-       trf->rx_skb = nfc_alloc_recv_skb(TRF7970A_RX_SKB_ALLOC_SIZE,
-                       GFP_KERNEL);
-       if (!trf->rx_skb) {
-               dev_dbg(trf->dev, "Can't alloc rx_skb\n");
-               ret = -ENOMEM;
-               goto out_err;
+       if (timeout) {
+               trf->rx_skb = nfc_alloc_recv_skb(TRF7970A_RX_SKB_ALLOC_SIZE,
+                               GFP_KERNEL);
+               if (!trf->rx_skb) {
+                       dev_dbg(trf->dev, "Can't alloc rx_skb\n");
+                       ret = -ENOMEM;
+                       goto out_err;
+               }
        }
 
        if (trf->state == TRF7970A_ST_IDLE_RX_BLOCKED) {
@@ -1267,9 +1489,11 @@ static int trf7970a_in_send_cmd(struct nfc_digital_dev *ddev,
                trf->state = TRF7970A_ST_IDLE;
        }
 
-       ret = trf7970a_per_cmd_config(trf, skb);
-       if (ret)
-               goto out_err;
+       if (trf->is_initiator) {
+               ret = trf7970a_per_cmd_config(trf, skb);
+               if (ret)
+                       goto out_err;
+       }
 
        trf->ddev = ddev;
        trf->tx_skb = skb;
@@ -1318,35 +1542,272 @@ out_err:
        return ret;
 }
 
-static int trf7970a_tg_configure_hw(struct nfc_digital_dev *ddev,
-               int type, int param)
+static int trf7970a_tg_config_rf_tech(struct trf7970a *trf, int tech)
+{
+       int ret = 0;
+
+       dev_dbg(trf->dev, "rf technology: %d\n", tech);
+
+       switch (tech) {
+       case NFC_DIGITAL_RF_TECH_106A:
+               trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_NFC_NFC_CE_MODE |
+                       TRF7970A_ISO_CTRL_NFC_CE |
+                       TRF7970A_ISO_CTRL_NFC_CE_14443A;
+               trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_OOK;
+               break;
+       case NFC_DIGITAL_RF_TECH_212F:
+               trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_NFC_NFC_CE_MODE |
+                       TRF7970A_ISO_CTRL_NFC_NFCF_212;
+               trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_ASK10;
+               break;
+       case NFC_DIGITAL_RF_TECH_424F:
+               trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_NFC_NFC_CE_MODE |
+                       TRF7970A_ISO_CTRL_NFC_NFCF_424;
+               trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_ASK10;
+               break;
+       default:
+               dev_dbg(trf->dev, "Unsupported rf technology: %d\n", tech);
+               return -EINVAL;
+       }
+
+       trf->technology = tech;
+
+       /* Normally we write the ISO_CTRL register in
+        * trf7970a_tg_config_framing() because the framing can change
+        * the value written.  However, when sending a PSL RES,
+        * digital_tg_send_psl_res_complete() doesn't call
+        * trf7970a_tg_config_framing() so we must write the register
+        * here.
+        */
+       if ((trf->framing == NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED) &&
+                       (trf->iso_ctrl_tech != trf->iso_ctrl)) {
+               ret = trf7970a_write(trf, TRF7970A_ISO_CTRL,
+                               trf->iso_ctrl_tech);
+
+               trf->iso_ctrl = trf->iso_ctrl_tech;
+       }
+
+       return ret;
+}
+
+/* Since this is a target routine, several of the framing calls are
+ * made between receiving the request and sending the response so they
+ * should take effect until after the response is sent.  This is accomplished
+ * by skipping the ISO_CTRL register write here and doing it in the interrupt
+ * handler.
+ */
+static int trf7970a_tg_config_framing(struct trf7970a *trf, int framing)
+{
+       u8 iso_ctrl = trf->iso_ctrl_tech;
+       int ret;
+
+       dev_dbg(trf->dev, "framing: %d\n", framing);
+
+       switch (framing) {
+       case NFC_DIGITAL_FRAMING_NFCA_NFC_DEP:
+               trf->tx_cmd = TRF7970A_CMD_TRANSMIT_NO_CRC;
+               iso_ctrl |= TRF7970A_ISO_CTRL_RX_CRC_N;
+               break;
+       case NFC_DIGITAL_FRAMING_NFCA_STANDARD:
+       case NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A:
+       case NFC_DIGITAL_FRAMING_NFCA_ANTICOL_COMPLETE:
+               /* These ones are applied in the interrupt handler */
+               iso_ctrl = trf->iso_ctrl; /* Don't write to ISO_CTRL yet */
+               break;
+       case NFC_DIGITAL_FRAMING_NFCF_NFC_DEP:
+               trf->tx_cmd = TRF7970A_CMD_TRANSMIT;
+               iso_ctrl &= ~TRF7970A_ISO_CTRL_RX_CRC_N;
+               break;
+       case NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED:
+               trf->tx_cmd = TRF7970A_CMD_TRANSMIT;
+               iso_ctrl &= ~TRF7970A_ISO_CTRL_RX_CRC_N;
+               break;
+       default:
+               dev_dbg(trf->dev, "Unsupported Framing: %d\n", framing);
+               return -EINVAL;
+       }
+
+       trf->framing = framing;
+
+       if (iso_ctrl != trf->iso_ctrl) {
+               ret = trf7970a_write(trf, TRF7970A_ISO_CTRL, iso_ctrl);
+               if (ret)
+                       return ret;
+
+               trf->iso_ctrl = iso_ctrl;
+
+               ret = trf7970a_write(trf, TRF7970A_MODULATOR_SYS_CLK_CTRL,
+                               trf->modulator_sys_clk_ctrl);
+               if (ret)
+                       return ret;
+       }
+
+       if (!(trf->chip_status_ctrl & TRF7970A_CHIP_STATUS_RF_ON)) {
+               ret = trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL,
+                               trf->chip_status_ctrl |
+                                       TRF7970A_CHIP_STATUS_RF_ON);
+               if (ret)
+                       return ret;
+
+               trf->chip_status_ctrl |= TRF7970A_CHIP_STATUS_RF_ON;
+       }
+
+       return 0;
+}
+
+static int trf7970a_tg_configure_hw(struct nfc_digital_dev *ddev, int type,
+               int param)
+{
+       struct trf7970a *trf = nfc_digital_get_drvdata(ddev);
+       int ret;
+
+       dev_dbg(trf->dev, "Configure hw - type: %d, param: %d\n", type, param);
+
+       mutex_lock(&trf->lock);
+
+       trf->is_initiator = false;
+
+       if ((trf->state == TRF7970A_ST_PWR_OFF) ||
+                       (trf->state == TRF7970A_ST_RF_OFF)) {
+               ret = trf7970a_switch_rf_on(trf);
+               if (ret)
+                       goto err_unlock;
+       }
+
+       switch (type) {
+       case NFC_DIGITAL_CONFIG_RF_TECH:
+               ret = trf7970a_tg_config_rf_tech(trf, param);
+               break;
+       case NFC_DIGITAL_CONFIG_FRAMING:
+               ret = trf7970a_tg_config_framing(trf, param);
+               break;
+       default:
+               dev_dbg(trf->dev, "Unknown type: %d\n", type);
+               ret = -EINVAL;
+       }
+
+err_unlock:
+       mutex_unlock(&trf->lock);
+       return ret;
+}
+
+static int _trf7970a_tg_listen(struct nfc_digital_dev *ddev, u16 timeout,
+               nfc_digital_cmd_complete_t cb, void *arg, bool mode_detect)
 {
        struct trf7970a *trf = nfc_digital_get_drvdata(ddev);
+       int ret;
+
+       mutex_lock(&trf->lock);
+
+       if ((trf->state != TRF7970A_ST_IDLE) &&
+                       (trf->state != TRF7970A_ST_IDLE_RX_BLOCKED)) {
+               dev_err(trf->dev, "%s - Bogus state: %d\n", __func__,
+                               trf->state);
+               ret = -EIO;
+               goto out_err;
+       }
 
-       dev_dbg(trf->dev, "Unsupported interface\n");
+       if (trf->aborting) {
+               dev_dbg(trf->dev, "Abort process complete\n");
+               trf->aborting = false;
+               ret = -ECANCELED;
+               goto out_err;
+       }
+
+       trf->rx_skb = nfc_alloc_recv_skb(TRF7970A_RX_SKB_ALLOC_SIZE,
+                       GFP_KERNEL);
+       if (!trf->rx_skb) {
+               dev_dbg(trf->dev, "Can't alloc rx_skb\n");
+               ret = -ENOMEM;
+               goto out_err;
+       }
+
+       ret = trf7970a_write(trf, TRF7970A_RX_SPECIAL_SETTINGS,
+                       TRF7970A_RX_SPECIAL_SETTINGS_HBT |
+                       TRF7970A_RX_SPECIAL_SETTINGS_M848 |
+                       TRF7970A_RX_SPECIAL_SETTINGS_C424 |
+                       TRF7970A_RX_SPECIAL_SETTINGS_C212);
+       if (ret)
+               goto out_err;
 
-       return -EINVAL;
+       ret = trf7970a_write(trf, TRF7970A_REG_IO_CTRL,
+                       TRF7970A_REG_IO_CTRL_VRS(0x1));
+       if (ret)
+               goto out_err;
+
+       ret = trf7970a_write(trf, TRF7970A_NFC_LOW_FIELD_LEVEL,
+                       TRF7970A_NFC_LOW_FIELD_LEVEL_RFDET(0x3));
+       if (ret)
+               goto out_err;
+
+       ret = trf7970a_write(trf, TRF7970A_NFC_TARGET_LEVEL,
+                       TRF7970A_NFC_TARGET_LEVEL_RFDET(0x7));
+       if (ret)
+               goto out_err;
+
+       trf->ddev = ddev;
+       trf->cb = cb;
+       trf->cb_arg = arg;
+       trf->timeout = timeout;
+       trf->ignore_timeout = false;
+
+       ret = trf7970a_cmd(trf, TRF7970A_CMD_ENABLE_RX);
+       if (ret)
+               goto out_err;
+
+       trf->state = mode_detect ? TRF7970A_ST_LISTENING_MD :
+                                  TRF7970A_ST_LISTENING;
+
+       schedule_delayed_work(&trf->timeout_work, msecs_to_jiffies(timeout));
+
+out_err:
+       mutex_unlock(&trf->lock);
+       return ret;
 }
 
-static int trf7970a_tg_send_cmd(struct nfc_digital_dev *ddev,
-               struct sk_buff *skb, u16 timeout,
+static int trf7970a_tg_listen(struct nfc_digital_dev *ddev, u16 timeout,
                nfc_digital_cmd_complete_t cb, void *arg)
 {
        struct trf7970a *trf = nfc_digital_get_drvdata(ddev);
 
-       dev_dbg(trf->dev, "Unsupported interface\n");
+       dev_dbg(trf->dev, "Listen - state: %d, timeout: %d ms\n",
+                       trf->state, timeout);
 
-       return -EINVAL;
+       return _trf7970a_tg_listen(ddev, timeout, cb, arg, false);
 }
 
-static int trf7970a_tg_listen(struct nfc_digital_dev *ddev,
+static int trf7970a_tg_listen_md(struct nfc_digital_dev *ddev,
                u16 timeout, nfc_digital_cmd_complete_t cb, void *arg)
+{
+       struct trf7970a *trf = nfc_digital_get_drvdata(ddev);
+       int ret;
+
+       dev_dbg(trf->dev, "Listen MD - state: %d, timeout: %d ms\n",
+                       trf->state, timeout);
+
+       ret = trf7970a_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH,
+                       NFC_DIGITAL_RF_TECH_106A);
+       if (ret)
+               return ret;
+
+       ret = trf7970a_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
+                       NFC_DIGITAL_FRAMING_NFCA_NFC_DEP);
+       if (ret)
+               return ret;
+
+       return _trf7970a_tg_listen(ddev, timeout, cb, arg, true);
+}
+
+static int trf7970a_tg_get_rf_tech(struct nfc_digital_dev *ddev, u8 *rf_tech)
 {
        struct trf7970a *trf = nfc_digital_get_drvdata(ddev);
 
-       dev_dbg(trf->dev, "Unsupported interface\n");
+       dev_dbg(trf->dev, "Get RF Tech - state: %d, rf_tech: %d\n",
+                       trf->state, trf->md_rf_tech);
 
-       return -EINVAL;
+       *rf_tech = trf->md_rf_tech;
+
+       return 0;
 }
 
 static void trf7970a_abort_cmd(struct nfc_digital_dev *ddev)
@@ -1364,6 +1825,11 @@ static void trf7970a_abort_cmd(struct nfc_digital_dev *ddev)
        case TRF7970A_ST_WAIT_TO_ISSUE_EOF:
                trf->aborting = true;
                break;
+       case TRF7970A_ST_LISTENING:
+               trf->ignore_timeout = !cancel_delayed_work(&trf->timeout_work);
+               trf7970a_send_err_upstream(trf, -ECANCELED);
+               dev_dbg(trf->dev, "Abort process complete\n");
+               break;
        default:
                break;
        }
@@ -1373,10 +1839,12 @@ static void trf7970a_abort_cmd(struct nfc_digital_dev *ddev)
 
 static struct nfc_digital_ops trf7970a_nfc_ops = {
        .in_configure_hw        = trf7970a_in_configure_hw,
-       .in_send_cmd            = trf7970a_in_send_cmd,
+       .in_send_cmd            = trf7970a_send_cmd,
        .tg_configure_hw        = trf7970a_tg_configure_hw,
-       .tg_send_cmd            = trf7970a_tg_send_cmd,
+       .tg_send_cmd            = trf7970a_send_cmd,
        .tg_listen              = trf7970a_tg_listen,
+       .tg_listen_md           = trf7970a_tg_listen_md,
+       .tg_get_rf_tech         = trf7970a_tg_get_rf_tech,
        .switch_rf              = trf7970a_switch_rf,
        .abort_cmd              = trf7970a_abort_cmd,
 };
@@ -1462,6 +1930,7 @@ static void trf7970a_shutdown(struct trf7970a *trf)
        case TRF7970A_ST_WAIT_FOR_RX_DATA:
        case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT:
        case TRF7970A_ST_WAIT_TO_ISSUE_EOF:
+       case TRF7970A_ST_LISTENING:
                trf7970a_send_err_upstream(trf, -ECANCELED);
                /* FALLTHROUGH */
        case TRF7970A_ST_IDLE:
@@ -1589,7 +2058,8 @@ static int trf7970a_probe(struct spi_device *spi)
 
        trf->ddev = nfc_digital_allocate_device(&trf7970a_nfc_ops,
                        TRF7970A_SUPPORTED_PROTOCOLS,
-                       NFC_DIGITAL_DRV_CAPS_IN_CRC, 0, 0);
+                       NFC_DIGITAL_DRV_CAPS_IN_CRC |
+                               NFC_DIGITAL_DRV_CAPS_TG_CRC, 0, 0);
        if (!trf->ddev) {
                dev_err(trf->dev, "Can't allocate NFC digital device\n");
                ret = -ENOMEM;
@@ -1654,7 +2124,6 @@ static int trf7970a_suspend(struct device *dev)
 {
        struct spi_device *spi = container_of(dev, struct spi_device, dev);
        struct trf7970a *trf = spi_get_drvdata(spi);
-       int ret = 0;
 
        dev_dbg(dev, "Suspend\n");
 
@@ -1664,14 +2133,14 @@ static int trf7970a_suspend(struct device *dev)
 
        mutex_unlock(&trf->lock);
 
-       return ret;
+       return 0;
 }
 
 static int trf7970a_resume(struct device *dev)
 {
        struct spi_device *spi = container_of(dev, struct spi_device, dev);
        struct trf7970a *trf = spi_get_drvdata(spi);
-       int ret = 0;
+       int ret;
 
        dev_dbg(dev, "Resume\n");