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)