From 8e2ca882108921d7aae27af8c650adfd46ecc126 Mon Sep 17 00:00:00 2001 From: Bhuvan Varshney Date: Mon, 9 Sep 2019 19:20:37 +0530 Subject: [PATCH] NFC: Fix device node probing issue Probing fails after retrying maximum times to receive response for NCI core reset command. Changed method of receiving response from poll mode to interrupt mode to receive response of the NCI commands sent. Change-Id: I41b0fc8e99fc31fd8b573549a21087737f540ed8 Signed-off-by: Bhuvan Varshney --- drivers/nfc/nq-nci.c | 36 +++++++++++++++++++++++++++--------- drivers/nfc/nq-nci.h | 4 +++- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/drivers/nfc/nq-nci.c b/drivers/nfc/nq-nci.c index 0d9b6f0e49b0..e7a3946f6881 100644 --- a/drivers/nfc/nq-nci.c +++ b/drivers/nfc/nq-nci.c @@ -150,6 +150,15 @@ static irqreturn_t nqx_dev_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } +static int is_data_available_for_read(struct nqx_dev *nqx_dev) +{ + int ret; + + nqx_enable_irq(nqx_dev); + ret = wait_event_interruptible(nqx_dev->read_wq, !nqx_dev->irq_enabled); + return ret; +} + static ssize_t nfc_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) { @@ -679,7 +688,6 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) { int ret = 0; - int gpio_retry_count = 0; unsigned char raw_nci_reset_cmd[] = {0x20, 0x00, 0x01, 0x00}; unsigned char raw_nci_init_cmd[] = {0x20, 0x01, 0x00}; unsigned char nci_get_version_cmd[] = {0x00, 0x04, 0xF1, @@ -690,7 +698,6 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) unsigned char init_rsp_len = 0; unsigned int enable_gpio = nqx_dev->en_gpio; -reset_enable_gpio: /* making sure that the NFCC starts in a clean state. */ gpio_set_value(enable_gpio, 0);/* ULPM: Disable */ /* hardware dependent delay */ @@ -746,8 +753,11 @@ reset_enable_gpio: } goto err_nfcc_reset_failed; } - /* hardware dependent delay */ - msleep(30); + ret = is_data_available_for_read(nqx_dev); + if (ret < 0) { + nqx_disable_irq(nqx_dev); + goto err_nfcc_hw_check; + } /* Read Response of RESET command */ ret = i2c_master_recv(client, nci_reset_rsp, @@ -755,11 +765,10 @@ reset_enable_gpio: if (ret < 0) { dev_err(&client->dev, "%s: - i2c_master_recv Error\n", __func__); - gpio_retry_count = gpio_retry_count + 1; - if (gpio_retry_count < MAX_RETRY_COUNT) - goto reset_enable_gpio; goto err_nfcc_hw_check; } + + /* send NCI CORE INIT CMD */ ret = nqx_standby_write(nqx_dev, raw_nci_init_cmd, sizeof(raw_nci_init_cmd)); if (ret < 0) { @@ -767,8 +776,12 @@ reset_enable_gpio: "%s: - i2c_master_send failed for Core INIT\n", __func__); goto err_nfcc_core_init_fail; } - /* hardware dependent delay */ - msleep(30); + ret = is_data_available_for_read(nqx_dev); + if (ret < 0) { + nqx_disable_irq(nqx_dev); + goto err_nfcc_hw_check; + } + /* Read Response of INIT command */ ret = i2c_master_recv(client, nci_init_rsp, sizeof(nci_init_rsp)); @@ -822,6 +835,11 @@ err_nfcc_reset_failed: 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__); diff --git a/drivers/nfc/nq-nci.h b/drivers/nfc/nq-nci.h index 87715c2e6237..d17897db7bab 100644 --- a/drivers/nfc/nq-nci.h +++ b/drivers/nfc/nq-nci.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, 2019 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -48,6 +48,8 @@ enum nfcc_chip_variant { NFCC_NQ_220 = 0x58, /**< NFCC NQ220 */ NFCC_NQ_310 = 0x40, /**< NFCC NQ310 */ NFCC_NQ_330 = 0x51, /**< NFCC NQ330 */ + NFCC_SN100_A = 0xa3, /**< NFCC SN100_A */ + NFCC_SN100_B = 0xa4, /**< NFCC SN100_B */ NFCC_PN66T = 0x18, /**< NFCC PN66T */ NFCC_NOT_SUPPORTED = 0xFF /**< NFCC is not supported */ };