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

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

Merge "NFC: NFCC wake up check by register read." into msm-3.10

parents 5409476b e0b3a05a
Loading
Loading
Loading
Loading
+94 −56
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ MODULE_DEVICE_TABLE(of, msm_match_table);
#define	CORE_RESET_RSP_GID		(0x60)
#define	CORE_RESET_OID			(0x00)
#define CORE_RST_NTF_LENGTH		(0x02)
#define WAKE_TIMEOUT			(10000)

static void clk_req_update(struct work_struct *work);

@@ -342,10 +343,10 @@ static ssize_t nfc_read(struct file *filp, char __user *buf,
	/* Read the header */
	ret = i2c_master_recv(qca199x_dev->client, len, PAYLOAD_HEADER_LENGTH);
	/*
		We ignore all packets of length PAYLOAD_HEADER_LENGTH
		or less (i.e <=3). In this case return a total length
		of ZERO. So ALL PACKETS MUST HAVE A PAYLOAD.
		If ret < 0 then this is an error code.
	 * We ignore all packets of length PAYLOAD_HEADER_LENGTH
	 * or less (i.e <=3). In this case return a total length
	 * of ZERO. So ALL PACKETS MUST HAVE A PAYLOAD.
	 * If ret < 0 then this is an error code.
	 */
	if (ret != PAYLOAD_HEADER_LENGTH) {
		if (ret < 0)
@@ -385,13 +386,13 @@ done:
}

/*
	Local routine to read from nfcc buffer. This is called to clear any
	pending receive messages in the nfcc's read buffer, which may be there
	following a POR. In this way, the upper layers (Device Transport) will
	associate the next rsp/ntf nci message with the next nci command to the
	nfcc. Otherwise, the DT may interpret a ntf from the nfcc as being from
	the nci core reset command when in fact it was already present in the
	nfcc read buffer following a POR.
 * Local routine to read from nfcc buffer. This is called to clear any
 * pending receive messages in the nfcc's read buffer, which may be there
 * following a POR. In this way, the upper layers (Device Transport) will
 * associate the next rsp/ntf nci message with the next nci command to the
 * nfcc. Otherwise, the DT may interpret a ntf from the nfcc as being from
 * the nci core reset command when in fact it was already present in the
 * nfcc read buffer following a POR.
 */

int nfcc_read_buff_svc(struct qca199x_dev *qca199x_dev)
@@ -448,10 +449,10 @@ static ssize_t nfc_write(struct file *filp, const char __user *buf,
		return -EFAULT;
	}
	/*
		A catch for when the DT is sending the initial NCI write
		following a hardware POR. In this case we should clear any
		pending messages in nfcc buffer and open the interrupt gate
		for new messages coming from the nfcc.
	 * A catch for when the DT is sending the initial NCI write
	 * following a hardware POR. In this case we should clear any
	 * pending messages in nfcc buffer and open the interrupt gate
	 * for new messages coming from the nfcc.
	 */
	if ((qca199x_dev->sent_first_nci_write == false) &&
		 (qca199x_dev->irq_enabled == false)) {
@@ -614,9 +615,9 @@ int nfc_ioctl_power_states(struct file *filp, unsigned int cmd,
		msleep(20);
	} else if (arg == 1) {
		/*
			We are attempting a hardware reset so let us disable
			interrupts to avoid spurious notifications to upper
			layers.
		 * We are attempting a hardware reset so let us disable
		 * interrupts to avoid spurious notifications to upper
		 * layers.
		 */
		qca199x_disable_irq(qca199x_dev);
		/* Deselection of clock */
@@ -624,10 +625,10 @@ int nfc_ioctl_power_states(struct file *filp, unsigned int cmd,
		if (r < 0)
			goto err_req;
		/*
			Also, set flag for initial NCI write following reset as
			may wish to do some house keeping. Ensure no pending
			messages in NFCC buffers which may be wrongly
			construed as response to initial message
		 * Also, set flag for initial NCI write following resetas
		 * may wish to do some house keeping. Ensure no pending
		 * messages in NFCC buffers which may be wrongly
		 * construed as response to initial message
		 */
		qca199x_dev->sent_first_nci_write = false;
		gpio_set_value(qca199x_dev->dis_gpio, 0);
@@ -734,9 +735,11 @@ int nfc_ioctl_nfcc_version(struct file *filp, unsigned int cmd,
				unsigned long arg)
{
	int r = 0;
	int	time_taken	= 0;
	unsigned short	slave_addr	=	0xE;
	unsigned short	curr_addr;
	unsigned char	raw_nci_wake[]			= {0x10, 0x0F};
	unsigned char	raw_nci_read;
	unsigned char raw_chip_version_addr		= 0x00;
	unsigned char raw_chip_rev_id_addr		= 0x9C;
	unsigned char raw_chip_version			= 0xFF;
@@ -754,39 +757,73 @@ int nfc_ioctl_nfcc_version(struct file *filp, unsigned int cmd,
	qca199x_dev->client->addr = slave_addr;
	r = nfc_i2c_write(qca199x_dev->client, &raw_nci_wake[0],
						sizeof(raw_nci_wake));
	r = sizeof(raw_nci_wake);

	if (r != sizeof(raw_nci_wake))
		goto invalid_wake_up;
		dev_err(&qca199x_dev->client->dev,
		"nfc_ioctl_nfcc_version : failed to send wake command\n");

	/*
	 * After placing the NFCC to sleep by a PROP
	 * SLEEP NCI msg (2F 03) and we need to wake
	 * it back up to obtain some information (by
	 * setting the wake bit).We need to determine
	 * when it has in actual fact woken before we
	 * can read the required data. We do that by
	 * reading back & testing if that wake bit has
	 * been cleared.
	 */
	do {
		r = i2c_master_recv(qca199x_dev->client, &raw_nci_read,
						sizeof(raw_nci_read));
		udelay(1);
		time_taken++;
	} while ((r == 1) && (raw_nci_read & NCI_WAKE)
			&& (time_taken < WAKE_TIMEOUT));

	if (time_taken < WAKE_TIMEOUT)
		qca199x_dev->state = NFCC_STATE_NORMAL_WAKE;
	else
		dev_err(&qca199x_dev->client->dev,
		"nfc_ioctl_nfcc_version : TIMED OUT to get WAKEUP bit\n");


	if (r != 1) {
		/*
		 * r < 0 indicates an error, maybe chip isn't
		 * up yet.What should we do??? r = 0 indicates
		 * nothing read, maybe chip isn't up yet. (should
		 * not happen) r > 1 indicates too many bytes read,
		 * maybe ?(should not happen)
		 */
		dev_err(&qca199x_dev->client->dev,
		"nfc_ioctl_nfcc_version : i2c error %d\n", r);
	}

	/* sleep to ensure the NFCC has time to wake up */
	usleep(100);
	if (arg == 0) {
		r = nfc_i2c_write(qca199x_dev->client,
				&raw_chip_version_addr, 1);
		if (r < 0)
			goto invalid_wr;
		usleep(10);
		r = i2c_master_recv(qca199x_dev->client, &raw_chip_version, 1);
		/* Restore original NFCC slave I2C address */
		qca199x_dev->client->addr = curr_addr;
	} else if (arg == 1) {
		r = nfc_i2c_write(qca199x_dev->client,
				&raw_chip_rev_id_addr, 1);
		if (r < 0)
			goto invalid_wr;
		usleep(20);
		r = i2c_master_recv(qca199x_dev->client, &raw_chip_version, 1);
	} else {
		/* Restore original NFCC slave I2C address */
		qca199x_dev->client->addr = curr_addr;
		return -EINVAL;
	}
	return raw_chip_version;
invalid_wake_up:
	raw_chip_version = 0xFE;
invalid_wr:
	raw_chip_version = 0xFF;

	if (r < 0) {
		/* Restore original NFCC slave I2C address */
		qca199x_dev->client->addr = curr_addr;
		dev_err(&qca199x_dev->client->dev,
			"\nNFCC_INVALID_CHIP_VERSION = %d\n", raw_chip_version);
			"NFCC_INVALID_CHIP_VERSION : i2c write fail\n");
		return -EIO;
	}

	usleep(10);
	r = i2c_master_recv(qca199x_dev->client, &raw_chip_version, 1);

	/* Restore original NFCC slave I2C address */
	qca199x_dev->client->addr = curr_addr;
	return raw_chip_version;
}

@@ -1050,9 +1087,9 @@ static int nfcc_initialise(struct i2c_client *client, unsigned short curr_addr)
	client->addr = NCI_I2C_SLAVE;

	/*
		Start with small delay and then we will poll until we
		get a core reset notification - This is time for chip
		& NFCC controller to come-up.
	 * Start with small delay and then we will poll until we
	 * get a core reset notification - This is time for chip
	 * & NFCC controller to come-up.
	 */
	usleep(1000); /* 1 ms */

@@ -1438,7 +1475,8 @@ static int qca199x_probe(struct i2c_client *client,
	}

	logging_level = 0;
	/* request irq.  The irq is set whenever the chip has data available
	/*
	 * request irq.  The irq is set whenever the chip has data available
	 * for reading.  It is cleared when all data has been read.
	 */
	device_mode.handle_flavour = UNSOLICITED_MODE;