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

Commit 851ee3cb authored by Mark A. Greer's avatar Mark A. Greer Committed by Samuel Ortiz
Browse files

NFC: trf7970a: Don't turn on RF if there is already an RF field



Currently, the trf7970a driver blindly turns on its
RF field when configuring its framing.  This isn't
a good idea if there is already a device generating
an RF field.  Instead, check if there is already an
RF field present before turning on this device's RF
field and, if there is, return EBUSY.

Signed-off-by: default avatarMark A. Greer <mgreer@animalcreek.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent 7149d6bf
Loading
Loading
Loading
Loading
+49 −2
Original line number Diff line number Diff line
@@ -164,8 +164,8 @@
#define TRF7970A_CMD_CLOSE_SLOT			0x15
#define TRF7970A_CMD_BLOCK_RX			0x16
#define TRF7970A_CMD_ENABLE_RX			0x17
#define TRF7970A_CMD_TEST_EXT_RF		0x18
#define TRF7970A_CMD_TEST_INT_RF		0x19
#define TRF7970A_CMD_TEST_INT_RF		0x18
#define TRF7970A_CMD_TEST_EXT_RF		0x19
#define TRF7970A_CMD_RX_GAIN_ADJUST		0x1a

/* Bits determining whether its a direct command or register R/W,
@@ -280,6 +280,10 @@
		 TRF7970A_IRQ_STATUS_PARITY_ERROR |		\
		 TRF7970A_IRQ_STATUS_CRC_ERROR)

#define TRF7970A_RSSI_OSC_STATUS_RSSI_MASK	(BIT(2) | BIT(1) | BIT(0))
#define TRF7970A_RSSI_OSC_STATUS_RSSI_X_MASK	(BIT(5) | BIT(4) | BIT(3))
#define TRF7970A_RSSI_OSC_STATUS_RSSI_OSC_OK	BIT(6)

#define TRF7970A_SPECIAL_FCN_REG1_COL_7_6		BIT(0)
#define TRF7970A_SPECIAL_FCN_REG1_14_ANTICOLL		BIT(1)
#define TRF7970A_SPECIAL_FCN_REG1_4_BIT_RX		BIT(2)
@@ -989,9 +993,43 @@ static int trf7970a_in_config_rf_tech(struct trf7970a *trf, int tech)
	return ret;
}

static int trf7970a_is_rf_field(struct trf7970a *trf, bool *is_rf_field)
{
	int ret;
	u8 rssi;

	ret = trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL,
			trf->chip_status_ctrl | TRF7970A_CHIP_STATUS_REC_ON);
	if (ret)
		return ret;

	ret = trf7970a_cmd(trf, TRF7970A_CMD_TEST_EXT_RF);
	if (ret)
		return ret;

	usleep_range(50, 60);

	ret = trf7970a_read(trf, TRF7970A_RSSI_OSC_STATUS, &rssi);
	if (ret)
		return ret;

	ret = trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL,
			trf->chip_status_ctrl);
	if (ret)
		return ret;

	if (rssi & TRF7970A_RSSI_OSC_STATUS_RSSI_MASK)
		*is_rf_field = true;
	else
		*is_rf_field = false;

	return 0;
}

static int trf7970a_in_config_framing(struct trf7970a *trf, int framing)
{
	u8 iso_ctrl = trf->iso_ctrl_tech;
	bool is_rf_field = false;
	int ret;

	dev_dbg(trf->dev, "framing: %d\n", framing);
@@ -1024,6 +1062,15 @@ static int trf7970a_in_config_framing(struct trf7970a *trf, int framing)

	trf->framing = framing;

	if (!(trf->chip_status_ctrl & TRF7970A_CHIP_STATUS_RF_ON)) {
		ret = trf7970a_is_rf_field(trf, &is_rf_field);
		if (ret)
			return ret;

		if (is_rf_field)
			return -EBUSY;
	}

	if (iso_ctrl != trf->iso_ctrl) {
		ret = trf7970a_write(trf, TRF7970A_ISO_CTRL, iso_ctrl);
		if (ret)