From c63fb6366f640274768560f0964d18d97e456ef6 Mon Sep 17 00:00:00 2001 From: Sebastiano Barezzi Date: Tue, 15 Nov 2022 16:31:06 +0100 Subject: [PATCH] drivers: nfc: Import Xiaomi changes * From dagu-s-oss Change-Id: I47d46f534cd51f9a050c4af6875f58b1512e17a0 --- drivers/nfc/nq-nci.c | 79 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 66 insertions(+), 13 deletions(-) diff --git a/drivers/nfc/nq-nci.c b/drivers/nfc/nq-nci.c index 247df3492835..38e98ec1aa1e 100644 --- a/drivers/nfc/nq-nci.c +++ b/drivers/nfc/nq-nci.c @@ -21,7 +21,9 @@ #ifdef CONFIG_COMPAT #include #endif +#ifdef NQ_READ_INT #include +#endif #include struct nqx_platform_data { @@ -1069,6 +1071,7 @@ static const struct file_operations nfc_dev_fops = { * Return: error codes in case of any failure, * number of bytes read otherwise */ +#if 0 static int get_nfcc_hw_info(struct i2c_client *client, struct nqx_dev *nqx_dev, char nci_reset_rsp_payload_len) { @@ -1178,6 +1181,7 @@ static int get_nfcc_hw_info(struct i2c_client *client, return ret; } +#endif /* Check for availability of NQ_ NFC controller hardware */ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) @@ -1185,9 +1189,13 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) int ret = 0; + int gpio_retry_count = 0; + int send_retry_count = 0; + unsigned char reset_ntf_len = 0; unsigned int enable_gpio = nqx_dev->en_gpio; char *nci_reset_cmd = NULL; char *nci_reset_rsp = NULL; + char *nci_reset_ntf = NULL; char *nci_get_version_cmd = NULL; char *nci_get_version_rsp = NULL; @@ -1203,6 +1211,13 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) ret = -ENOMEM; goto done; } + + nci_reset_ntf = kzalloc(NCI_RESET_NTF_LEN + 1, GFP_DMA | GFP_KERNEL); + if (!nci_reset_ntf) { + ret = -ENOMEM; + goto done; + } + nci_get_version_cmd = kzalloc(NCI_GET_VERSION_CMD_LEN + 1, GFP_DMA | GFP_KERNEL); if (!nci_get_version_cmd) { @@ -1217,10 +1232,13 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) goto done; } +reset_enable_gpio: /* making sure that the NFCC starts in a clean state. */ +#ifdef NQ_READ_INT gpio_set_value(enable_gpio, 1);/* HPD : Enable*/ /* hardware dependent delay */ usleep_range(10000, 10100); +#endif gpio_set_value(enable_gpio, 0);/* ULPM: Disable */ /* hardware dependent delay */ usleep_range(10000, 10100); @@ -1238,6 +1256,17 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) dev_err(&client->dev, "%s: - i2c_master_send core reset Error\n", __func__); + if (send_retry_count < MAX_RETRY_COUNT) { + send_retry_count += 1; + goto reset_enable_gpio; + } else { + nqx_dev->nqx_info.info.chip_type = NFCC_SN100_A; + nqx_dev->nqx_info.info.rom_version = 0; + nqx_dev->nqx_info.info.fw_minor = 0; + nqx_dev->nqx_info.info.fw_major = 0; + goto err_nfcc_reset_failed; + } + if (gpio_is_valid(nqx_dev->firm_gpio)) { gpio_set_value(nqx_dev->firm_gpio, 1); usleep_range(10000, 10100); @@ -1287,37 +1316,60 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) goto err_nfcc_reset_failed; } + /* hardware dependent delay */ + msleep(60); + +#ifdef NQ_READ_INT ret = is_data_available_for_read(nqx_dev); if (ret <= 0) { nqx_disable_irq(nqx_dev); goto err_nfcc_hw_check; } +#endif - /* Read Header of RESET command */ - ret = i2c_master_recv(client, nci_reset_rsp, NCI_HEADER_LEN); - if (ret != NCI_HEADER_LEN) { + /* Read Response of RESET command */ + ret = i2c_master_recv(client, nci_reset_rsp, NCI_RESET_RSP_LEN); + if (ret < 0) { dev_dbg(&client->dev, "%s: - i2c_master_recv get RESET rsp header Error\n", __func__); - goto err_nfcc_hw_check; - } - ret = i2c_master_recv(client, &nci_reset_rsp[NCI_PAYLOAD_START_INDEX], - nci_reset_rsp[NCI_PAYLOAD_LENGTH_INDEX]); - if (ret != nci_reset_rsp[NCI_PAYLOAD_LENGTH_INDEX]) { - dev_dbg(&client->dev, - "%s: - i2c_master_recv get RESET rsp data 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; } - /* Retrieve NFCC HW info */ - ret = get_nfcc_hw_info(client, nqx_dev, - nci_reset_rsp[NCI_PAYLOAD_LENGTH_INDEX]); + /* hardware dependent delay */ + msleep(30); + +#ifdef NQ_READ_INT + ret = is_data_available_for_read(nqx_dev); + if (ret <= 0) { + nqx_disable_irq(nqx_dev); + goto err_nfcc_hw_check; + } +#endif + + /* Read Notification of RESET command */ + ret = i2c_master_recv(client, nci_reset_ntf, NCI_RESET_NTF_LEN); if (ret < 0) { dev_dbg(&client->dev, "%s: - Error in getting NFCC HW info\n", __func__); goto err_nfcc_hw_check; } + 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_reset_ntf[reset_ntf_len - 3]; + nqx_dev->nqx_info.info.rom_version = + nci_reset_ntf[reset_ntf_len - 2]; + nqx_dev->nqx_info.info.fw_major = + nci_reset_ntf[reset_ntf_len - 1]; + nqx_dev->nqx_info.info.fw_minor = + nci_reset_ntf[reset_ntf_len]; + } + dev_dbg(&client->dev, "%s: - nq - reset cmd answer : NfcNciRx %x %x %x\n", @@ -1367,6 +1419,7 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) done: kfree(nci_reset_rsp); + kfree(nci_reset_ntf); kfree(nci_reset_cmd); kfree(nci_get_version_cmd); kfree(nci_get_version_rsp);