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

Commit 962362a3 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "NFC: Inform CLF whenever eSE is powered off"

parents 9848a9d8 05e6affb
Loading
Loading
Loading
Loading
+110 −25
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ MODULE_DEVICE_TABLE(of, msm_match_table);

#define MAX_BUFFER_SIZE			(320)
#define WAKEUP_SRC_TIMEOUT		(2000)
#define MAX_RETRY_COUNT			3

struct nqx_dev {
	wait_queue_head_t	read_wq;
@@ -264,6 +265,35 @@ out:
	return ret;
}

/**
 * nqx_standby_write()
 * @buf:       pointer to data buffer
 * @len:       # of bytes need to transfer
 *
 * write data buffer over I2C and retry
 * if NFCC is in stand by mode
 *
 * Return: # of bytes written or -ve value in case of error
 */
static int nqx_standby_write(struct nqx_dev *nqx_dev,
				const unsigned char *buf, size_t len)
{
	int ret = -EINVAL;
	int retry_cnt;

	for (retry_cnt = 1; retry_cnt <= MAX_RETRY_COUNT; retry_cnt++) {
		ret = i2c_master_send(nqx_dev->client, buf, len);
		if (ret < 0) {
			dev_err(&nqx_dev->client->dev,
				"%s: write failed, Maybe in Standby Mode - Retry(%d)\n",
				 __func__, retry_cnt);
			usleep_range(1000, 1100);
		} else if (ret == len)
			break;
	}
	return ret;
}

/*
	Power management of the eSE
	NFC & eSE ON : NFC_EN high and eSE_pwr_req high.
@@ -273,38 +303,94 @@ out:
static int nqx_ese_pwr(struct nqx_dev *nqx_dev, unsigned long int arg)
{
	int r = -1;
	const unsigned char svdd_off_cmd_warn[] =  {0x2F, 0x31, 0x01, 0x01};
	const unsigned char svdd_off_cmd_done[] =  {0x2F, 0x31, 0x01, 0x00};

	if (!gpio_is_valid(nqx_dev->ese_gpio)) {
		dev_err(&nqx_dev->client->dev,
			"%s: ese_gpio is not valid\n", __func__);
		return -EINVAL;
	}

	/* Let's store the NFC_EN pin state*/
	if (arg == 0) {
		/* We want to power on the eSE and to do so we need the
		 * eSE_pwr_req pin and the NFC_EN pin to be high
		 */
		nqx_dev->nfc_ven_enabled = gpio_get_value(nqx_dev->en_gpio);
		if (gpio_get_value(nqx_dev->ese_gpio)) {
			dev_dbg(&nqx_dev->client->dev, "ese_gpio is already high\n");
			r = 0;
		} else {
			/**
			 * Let's store the NFC_EN pin state
			 * only if the eSE is not yet on
			 */
			nqx_dev->nfc_ven_enabled =
					gpio_get_value(nqx_dev->en_gpio);
			if (!nqx_dev->nfc_ven_enabled) {
				gpio_set_value(nqx_dev->en_gpio, 1);
				/* hardware dependent delay */
				usleep_range(1000, 1100);
			}
		if (gpio_is_valid(nqx_dev->ese_gpio)) {
			if (gpio_get_value(nqx_dev->ese_gpio)) {
				dev_dbg(&nqx_dev->client->dev, "ese_gpio is already high\n");
				r = 0;
			} else {
			gpio_set_value(nqx_dev->ese_gpio, 1);
			if (gpio_get_value(nqx_dev->ese_gpio)) {
				dev_dbg(&nqx_dev->client->dev, "ese_gpio is enabled\n");
				r = 0;
			}
		}
		}
	} else if (arg == 1) {
		if (gpio_is_valid(nqx_dev->ese_gpio)) {
		if (nqx_dev->nfc_ven_enabled &&
			((nqx_dev->nqx_info.info.chip_type == NFCC_NQ_220) ||
			(nqx_dev->nqx_info.info.chip_type == NFCC_PN66T))) {
			/**
			 * Let's inform the CLF we're
			 * powering off the eSE
			 */
			r = nqx_standby_write(nqx_dev, svdd_off_cmd_warn,
						sizeof(svdd_off_cmd_warn));
			if (r < 0) {
				dev_err(&nqx_dev->client->dev,
					"%s: write failed after max retry\n",
					 __func__);
				return -ENXIO;
			}
			dev_dbg(&nqx_dev->client->dev,
				"%s: svdd_off_cmd_warn sent\n", __func__);

			/* let's power down the eSE */
			gpio_set_value(nqx_dev->ese_gpio, 0);
			dev_dbg(&nqx_dev->client->dev,
				"%s: nqx_dev->ese_gpio set to 0\n", __func__);

			/**
			 * Time needed for the SVDD capacitor
			 * to get discharged
			 */
			usleep_range(8000, 8100);

			/* Let's inform the CLF the eSE is now off */
			r = nqx_standby_write(nqx_dev, svdd_off_cmd_done,
						sizeof(svdd_off_cmd_done));
			if (r < 0) {
				dev_err(&nqx_dev->client->dev,
					"%s: write failed after max retry\n",
					 __func__);
				return -ENXIO;
			}
			dev_dbg(&nqx_dev->client->dev,
				"%s: svdd_off_cmd_done sent\n", __func__);
		} else {
			/**
			 * In case the NFC is off,
			 * there's no need to send the i2c commands
			 */
			gpio_set_value(nqx_dev->ese_gpio, 0);
		}

		if (!gpio_get_value(nqx_dev->ese_gpio)) {
			dev_dbg(&nqx_dev->client->dev, "ese_gpio is disabled\n");
			r = 0;
		}
		}

		if (!nqx_dev->nfc_ven_enabled) {
			/* hardware dependent delay */
			usleep_range(1000, 1100);
@@ -312,13 +398,8 @@ static int nqx_ese_pwr(struct nqx_dev *nqx_dev, unsigned long int arg)
			gpio_set_value(nqx_dev->en_gpio, 0);
		}
	} else if (arg == 3) {
		if (!nqx_dev->nfc_ven_enabled)
			r = 0;
		else {
			if (gpio_is_valid(nqx_dev->ese_gpio))
		r = gpio_get_value(nqx_dev->ese_gpio);
	}
	}
	return r;
}

@@ -621,6 +702,10 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev)
		dev_dbg(&client->dev,
		"%s: ## NFCC == NQ330 ##\n", __func__);
		break;
	case NFCC_PN66T:
		dev_dbg(&client->dev,
		"%s: ## NFCC == PN66T ##\n", __func__);
		break;
	default:
		dev_err(&client->dev,
		"%s: - NFCC HW not Supported\n", __func__);
+1 −0
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ enum nfcc_chip_variant {
	NFCC_NQ_220		= 0x58,	/**< NFCC NQ220 */
	NFCC_NQ_310		= 0x40,	/**< NFCC NQ310 */
	NFCC_NQ_330		= 0x51,	/**< NFCC NQ330 */
	NFCC_PN66T		= 0x18,	/**< NFCC PN66T */
	NFCC_NOT_SUPPORTED	= 0xFF	/**< NFCC is not supported */
};
#endif