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

Commit 31df1f5c authored by Bhuvan Varshney's avatar Bhuvan Varshney
Browse files

NFC: Keep VEN gpio always high from boot



VEN will be toggled from NFC driver only once during boot
and it will remain high on successful driver probe exit,
after that MW shouldn't modify it's state
as eSE is also powered using VEN gpio in SN100 NFC HW.

VEN toggle will reset eSE power and cause failure if
any communication is in progress.

Change-Id: Id18d0f6177c16c7c99f91a75dd126c138352755c
Signed-off-by: default avatarBhuvan Varshney <bvarshne@codeaurora.org>
parent f1684bb6
Loading
Loading
Loading
Loading
+72 −50
Original line number Diff line number Diff line
@@ -47,15 +47,15 @@ MODULE_DEVICE_TABLE(of, msm_match_table);
#define WAKEUP_SRC_TIMEOUT		(2000)
#define MAX_RETRY_COUNT			3
#define NCI_RESET_CMD_LEN		4
#define NCI_INIT_CMD_LEN		3
#define NCI_RESET_RSP_LEN		6
#define NCI_INIT_RSP_LEN		28
#define NCI_RESET_RSP_LEN		4
#define NCI_RESET_NTF_LEN		13
#define NCI_GET_VERSION_CMD_LEN		8
#define NCI_GET_VERSION_RSP_LEN		12

struct nqx_dev {
	wait_queue_head_t	read_wq;
	struct	mutex		read_mutex;
	struct	mutex		dev_ref_mutex;
	struct	i2c_client	*client;
	dev_t			devno;
	struct class		*nqx_class;
@@ -76,6 +76,8 @@ struct nqx_dev {
	bool			irq_wake_up;
	spinlock_t		irq_enabled_lock;
	unsigned int		count_irq;
	/* NFC_IRQ Count */
	unsigned int		dev_ref_count;
	/* Initial CORE RESET notification */
	unsigned int		core_reset_ntf;
	/* CLK control */
@@ -488,11 +490,52 @@ static int nfc_open(struct inode *inode, struct file *filp)
	filp->private_data = nqx_dev;
	nqx_init_stat(nqx_dev);

	mutex_lock(&nqx_dev->dev_ref_mutex);

	if (nqx_dev->dev_ref_count == 0) {
		nqx_enable_irq(nqx_dev);

		if (gpio_is_valid(nqx_dev->firm_gpio)) {
			gpio_set_value(nqx_dev->firm_gpio, 0);
			usleep_range(10000, 10100);
		}
	}

	nqx_dev->dev_ref_count = nqx_dev->dev_ref_count + 1;

	mutex_unlock(&nqx_dev->dev_ref_mutex);

	dev_dbg(&nqx_dev->client->dev,
			"%s: %d,%d\n", __func__, imajor(inode), iminor(inode));
	return 0;
}

static int nfc_close(struct inode *inode, struct file *filp)
{
	struct nqx_dev *nqx_dev = container_of(inode->i_cdev,
				struct nqx_dev, c_dev);

	mutex_lock(&nqx_dev->dev_ref_mutex);

	if (nqx_dev->dev_ref_count == 1) {
		nqx_disable_irq(nqx_dev);

		if (gpio_is_valid(nqx_dev->firm_gpio)) {
			gpio_set_value(nqx_dev->firm_gpio, 0);
			usleep_range(10000, 10100);
		}
	}

	if (nqx_dev->dev_ref_count > 0)
		nqx_dev->dev_ref_count = nqx_dev->dev_ref_count - 1;

	mutex_unlock(&nqx_dev->dev_ref_mutex);

	filp->private_data = NULL;

	return 0;
}

/*
 * nfc_ioctl_power_states() - power control
 * @filp:	pointer to the file descriptor
@@ -729,6 +772,7 @@ static const struct file_operations nfc_dev_fops = {
	.read  = nfc_read,
	.write = nfc_write,
	.open = nfc_open,
	.release = nfc_close,
	.unlocked_ioctl = nfc_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl = nfc_compat_ioctl
@@ -741,12 +785,11 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev)
	int ret = 0;

	int gpio_retry_count = 0;
	unsigned char init_rsp_len = 0;
	unsigned char reset_ntf_len = 0;
	unsigned int enable_gpio = nqx_dev->en_gpio;
	char *nci_reset_cmd = NULL;
	char *nci_init_cmd = NULL;
	char *nci_init_rsp = NULL;
	char *nci_reset_rsp = NULL;
	char *nci_reset_ntf = NULL;
	char *nci_get_version_cmd = NULL;
	char *nci_get_version_rsp = NULL;

@@ -762,14 +805,8 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev)
		goto done;
	}

	nci_init_cmd = kzalloc(NCI_INIT_CMD_LEN + 1,  GFP_DMA | GFP_KERNEL);
	if (!nci_init_cmd) {
		ret = -ENOMEM;
		goto done;
	}

	nci_init_rsp = kzalloc(NCI_INIT_RSP_LEN + 1,  GFP_DMA | GFP_KERNEL);
	if (!nci_init_rsp) {
	nci_reset_ntf = kzalloc(NCI_RESET_NTF_LEN + 1,  GFP_DMA | GFP_KERNEL);
	if (!nci_reset_rsp) {
		ret = -ENOMEM;
		goto done;
	}
@@ -868,34 +905,28 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev)
			goto reset_enable_gpio;
		goto err_nfcc_hw_check;
	}
	nci_init_cmd[0] = 0x20;
	nci_init_cmd[1] = 0x01;
	nci_init_cmd[2] = 0x00;
	ret = nqx_standby_write(nqx_dev, nci_init_cmd, NCI_INIT_CMD_LEN);
	if (ret < 0) {
		dev_err(&client->dev,
		"%s: - i2c_master_send failed for Core INIT\n", __func__);
		goto err_nfcc_core_init_fail;
	}

	/* hardware dependent delay */
	msleep(30);
	/* Read Response of INIT command */
	ret = i2c_master_recv(client, nci_init_rsp, NCI_INIT_RSP_LEN);

	/* Read Notification of RESET command */
	ret = i2c_master_recv(client, nci_reset_ntf, NCI_RESET_NTF_LEN);
	if (ret < 0) {
		dev_err(&client->dev,
		"%s: - i2c_master_recv Error\n", __func__);
		goto err_nfcc_core_init_fail;
		goto err_nfcc_hw_check;
	}
	init_rsp_len = 2 + nci_init_rsp[2]; /*payload + len*/
	if (init_rsp_len > PAYLOAD_HEADER_LENGTH) {

	reset_ntf_len = 2 + nci_reset_ntf[2]; /*payload + len*/
	if (reset_ntf_len > PAYLOAD_HEADER_LENGTH) {
		nqx_dev->nqx_info.info.chip_type =
				nci_init_rsp[init_rsp_len - 3];
				nci_reset_ntf[reset_ntf_len - 3];
		nqx_dev->nqx_info.info.rom_version =
				nci_init_rsp[init_rsp_len - 2];
				nci_reset_ntf[reset_ntf_len - 2];
		nqx_dev->nqx_info.info.fw_major =
				nci_init_rsp[init_rsp_len - 1];
				nci_reset_ntf[reset_ntf_len - 1];
		nqx_dev->nqx_info.info.fw_minor =
				nci_init_rsp[init_rsp_len];
				nci_reset_ntf[reset_ntf_len];
	}
	dev_dbg(&client->dev,
		"%s: - nq - reset cmd answer : NfcNciRx %x %x %x\n",
@@ -911,14 +942,6 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev)
		nqx_dev->nqx_info.info.fw_minor);

	switch (nqx_dev->nqx_info.info.chip_type) {
	case NFCC_NQ_210:
		dev_dbg(&client->dev,
		"%s: ## NFCC == NQ210 ##\n", __func__);
		break;
	case NFCC_NQ_220:
		dev_dbg(&client->dev,
		"%s: ## NFCC == NQ220 ##\n", __func__);
		break;
	case NFCC_NQ_310:
		dev_dbg(&client->dev,
		"%s: ## NFCC == NQ310 ##\n", __func__);
@@ -931,23 +954,21 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev)
		dev_dbg(&client->dev,
		"%s: ## NFCC == PN66T ##\n", __func__);
		break;
	case NFCC_SN100_A:
	case NFCC_SN100_B:
		dev_dbg(&client->dev,
		"%s: ## NFCC == SN100x ##\n", __func__);
		break;
	default:
		dev_err(&client->dev,
		"%s: - NFCC HW not Supported\n", __func__);
		break;
	}

	/*Disable NFC by default to save power on boot*/
	gpio_set_value(enable_gpio, 0);/* ULPM: Disable */
	ret = 0;
	nqx_dev->nfc_ven_enabled = true;
	goto done;

err_nfcc_core_init_fail:
	dev_err(&client->dev,
	"%s: - nq - reset cmd answer : NfcNciRx %x %x %x\n",
	__func__, nci_reset_rsp[0],
	nci_reset_rsp[1], nci_reset_rsp[2]);

err_nfcc_hw_check:
	ret = -ENXIO;
	dev_err(&client->dev,
@@ -955,8 +976,7 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev)

done:
	kfree(nci_reset_rsp);
	kfree(nci_init_rsp);
	kfree(nci_init_cmd);
	kfree(nci_reset_ntf);
	kfree(nci_reset_cmd);
	kfree(nci_get_version_cmd);
	kfree(nci_get_version_rsp);
@@ -1247,6 +1267,7 @@ static int nqx_probe(struct i2c_client *client,
	/* init mutex and queues */
	init_waitqueue_head(&nqx_dev->read_wq);
	mutex_init(&nqx_dev->read_mutex);
	mutex_init(&nqx_dev->dev_ref_mutex);
	spin_lock_init(&nqx_dev->irq_enabled_lock);

	r = alloc_chrdev_region(&nqx_dev->devno, 0, DEV_COUNT, DEVICE_NAME);
@@ -1395,6 +1416,7 @@ static int nqx_remove(struct i2c_client *client)
	class_destroy(nqx_dev->nqx_class);
	unregister_chrdev_region(nqx_dev->devno, DEV_COUNT);
	mutex_destroy(&nqx_dev->read_mutex);
	mutex_destroy(&nqx_dev->dev_ref_mutex);
	gpio_free(nqx_dev->clkreq_gpio);
	/* optional gpio, not sure was configured in probe */
	if (nqx_dev->ese_gpio > 0)