NFC: detect NFC wakeup complete

When waking up the nfcc, block for completion. NFC user space driver
needs to properly track the sleep/wake state of the NFCC for stability.
Poll on the i2c bus untill the wakeup bit or a timeout occurs.

CRs-Fixed: 665191
Change-Id: I65d07eef5a966e7c13c23f2e68d9babb08e1ae8e
Signed-off-by: Houston Hoffman <hhoffman@codeaurora.org>
diff --git a/drivers/nfc/nfc-nci.c b/drivers/nfc/nfc-nci.c
index a9c093b..3ce4766 100644
--- a/drivers/nfc/nfc-nci.c
+++ b/drivers/nfc/nfc-nci.c
@@ -61,6 +61,7 @@
 #define	CORE_RESET_OID			(0x00)
 #define CORE_RST_NTF_LENGTH		(0x02)
 #define WAKE_TIMEOUT			(10)
+#define WAKE_REG			(0x10)
 
 static void clk_req_update(struct work_struct *work);
 
@@ -539,11 +540,13 @@
 int nfcc_wake(int level, struct file *filp)
 {
 	int r = 0;
+	int time_taken = 0;
 	unsigned char raw_nci_sleep[] = {0x2F, 0x03, 0x00};
 	/* Change slave address to 0xE */
 	unsigned char raw_nci_wake[]  = {0x10, 0x0F};
 	unsigned short	slave_addr	=	0xE;
 	unsigned short	curr_addr;
+	unsigned char wake_status	= WAKE_REG;
 	struct qca199x_dev *qca199x_dev = filp->private_data;
 
 	dev_dbg(&qca199x_dev->client->dev, "nfcc_wake: %s: info: %p\n",
@@ -553,7 +556,6 @@
 		r = i2c_master_send(qca199x_dev->client, &raw_nci_sleep[0],
 						sizeof(raw_nci_sleep));
 
-		r = sizeof(raw_nci_sleep);
 		if (r != sizeof(raw_nci_sleep))
 			return -EMSGSIZE;
 		qca199x_dev->state = NFCC_STATE_NORMAL_SLEEP;
@@ -562,10 +564,31 @@
 		qca199x_dev->client->addr = slave_addr;
 		r = nfc_i2c_write(qca199x_dev->client, &raw_nci_wake[0],
 						sizeof(raw_nci_wake));
+		do {
+			wake_status = WAKE_REG;
+			r = nfc_i2c_write(qca199x_dev->client, &wake_status, 1);
+			/*
+			 * NFCC chip needs to be at least
+			 * 10usec high before make it low
+			 */
+			usleep_range(10, 15);
+			r = i2c_master_recv(qca199x_dev->client, &wake_status,
+						sizeof(wake_status));
+
+			time_taken++;
+			if ((wake_status & NCI_WAKE) != 0)
+				/* NFCC wakeup time is between 0.5 and .52 ms */
+				usleep_range(500, 520);
+
+		} while ((wake_status & NCI_WAKE)
+				&& (time_taken < WAKE_TIMEOUT));
 		/* Restore original NFCC slave I2C address */
+		if (time_taken >= WAKE_TIMEOUT)
+			dev_err(&qca199x_dev->client->dev,
+			"nfc_ioctl_nfcc_version : TIMED OUT to get WAKEUP bit\n");
+
 		qca199x_dev->client->addr = curr_addr;
-		r = sizeof(raw_nci_wake);
-		if (r != sizeof(raw_nci_wake))
+		if (r != sizeof(wake_status))
 			return -EMSGSIZE;
 		qca199x_dev->state = NFCC_STATE_NORMAL_WAKE;
 	}
@@ -764,13 +787,24 @@
 	 * been cleared.
 	 */
 	do {
+		raw_nci_read = 0x10;
+		r = nfc_i2c_write(qca199x_dev->client, &raw_nci_read, 1);
+		/*
+		 * NFCC chip needs to be at least
+		 * 10usec high before make it low
+		 */
+		usleep_range(10, 15);
+
 		r = i2c_master_recv(qca199x_dev->client, &raw_nci_read,
 						sizeof(raw_nci_read));
+
 		if ((raw_nci_read & NCI_WAKE) != 0)
-			usleep(1000);
+			/* NFCC wakeup time is between 0.5 and .52 ms */
+			usleep_range(500, 520);
 
 		time_taken++;
-	} while ((r == 1) && (raw_nci_read & NCI_WAKE)
+
+	} while ((raw_nci_read & NCI_WAKE)
 			&& (time_taken < WAKE_TIMEOUT));
 
 	if (time_taken < WAKE_TIMEOUT)