Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 13b4272a authored by Mark A. Greer's avatar Mark A. Greer Committed by Samuel Ortiz
Browse files

NFC: trf7970a: Add Target Mode Support



Add target mode support to the trf7970a
NFC driver.  This effectively enables full
Peer-to-Peer support.

To handle changing framing between sending
a response frame and receiving the subsequent
request frame, most of the framing changes
take effect in the interrupt handler and not
in trf7970a_tg_config_framing().

Signed-off-by: default avatarMark A. Greer <mgreer@animalcreek.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent 1961843c
Loading
Loading
Loading
Loading
+339 −35
Original line number Diff line number Diff line
@@ -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
@@ -121,7 +121,7 @@
#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 */

@@ -240,6 +240,15 @@
#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 */
@@ -265,12 +274,32 @@
#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)
@@ -301,6 +330,16 @@
#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 TRF7970A_FIFO_STATUS_OVERFLOW		BIT(7)

/* NFC (ISO/IEC 14443A) Type 2 Tag commands */
@@ -345,6 +384,7 @@ 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_MAX
};

@@ -355,6 +395,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;
@@ -694,7 +735,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);

@@ -720,12 +761,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;
		}
@@ -757,7 +798,10 @@ 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) {
@@ -767,6 +811,45 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id)
				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)
					return ret;

				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)
					return ret;

				trf->iso_ctrl = iso_ctrl;
			}
		} else {
			trf7970a_send_err_upstream(trf, -EIO);
		}
@@ -775,6 +858,15 @@ 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;
	default:
		dev_err(trf->dev, "%s - Driver in invalid state: %d\n",
				__func__, trf->state);
@@ -853,11 +945,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);
@@ -958,6 +1045,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);
		}
	}
@@ -1005,6 +1094,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;
}

@@ -1063,6 +1160,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;
@@ -1124,6 +1223,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);
@@ -1233,7 +1334,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)
{
@@ -1284,9 +1385,11 @@ static int trf7970a_in_send_cmd(struct nfc_digital_dev *ddev,
		trf->state = TRF7970A_ST_IDLE;
	}

	if (trf->is_initiator) {
		ret = trf7970a_per_cmd_config(trf, skb);
		if (ret)
			goto out_err;
	}

	trf->ddev = ddev;
	trf->tx_skb = skb;
@@ -1335,35 +1438,229 @@ static int trf7970a_in_send_cmd(struct nfc_digital_dev *ddev,
	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)
{
	struct trf7970a *trf = nfc_digital_get_drvdata(ddev);
	int ret = 0;

	dev_dbg(trf->dev, "Unsupported interface\n");
	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;
	}

static int trf7970a_tg_send_cmd(struct nfc_digital_dev *ddev,
		struct sk_buff *skb, u16 timeout,
		nfc_digital_cmd_complete_t cb, void *arg)
	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)
{
	struct trf7970a *trf = nfc_digital_get_drvdata(ddev);
	u8 iso_ctrl = trf->iso_ctrl_tech;
	int ret;

	dev_dbg(trf->dev, "Unsupported interface\n");
	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;
	}

static int trf7970a_tg_listen(struct nfc_digital_dev *ddev,
		u16 timeout, nfc_digital_cmd_complete_t cb, void *arg)
	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, "Unsupported interface\n");
	dev_dbg(trf->dev, "Configure hw - type: %d, param: %d\n", type, param);

	return -EINVAL;
	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)
{
	struct trf7970a *trf = nfc_digital_get_drvdata(ddev);
	int ret;

	dev_dbg(trf->dev, "Listen - state: %d, timeout: %d ms\n",
			trf->state, timeout);

	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;
	}

	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)
		return ret;

	ret = trf7970a_write(trf, TRF7970A_REG_IO_CTRL,
			TRF7970A_REG_IO_CTRL_VRS(0x1));
	if (ret)
		return ret;

	ret = trf7970a_write(trf, TRF7970A_NFC_LOW_FIELD_LEVEL,
			TRF7970A_NFC_LOW_FIELD_LEVEL_RFDET(0x3));
	if (ret)
		return ret;

	ret = trf7970a_write(trf, TRF7970A_NFC_TARGET_LEVEL,
			TRF7970A_NFC_TARGET_LEVEL_RFDET(0x7));
	if (ret)
		return ret;

	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 = TRF7970A_ST_LISTENING;

	schedule_delayed_work(&trf->timeout_work, msecs_to_jiffies(timeout));

out_err:
	mutex_unlock(&trf->lock);
	return ret;
}

static void trf7970a_abort_cmd(struct nfc_digital_dev *ddev)
@@ -1381,6 +1678,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;
	}
@@ -1390,9 +1692,9 @@ 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,
	.switch_rf		= trf7970a_switch_rf,
	.abort_cmd		= trf7970a_abort_cmd,
@@ -1479,6 +1781,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:
@@ -1606,7 +1909,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;