Loading drivers/nfc/nq-nci.c +73 −52 Original line number Diff line number Diff line Loading @@ -54,15 +54,15 @@ MODULE_DEVICE_TABLE(of, msm_match_table); #define WAKEUP_SRC_TIMEOUT (2000) #define MAX_RETRY_COUNT 3 #define NCI_RESET_CMD_LEN 4 #define NCI_INIT_CMD_LEN 3 #define NCI_RESET_RSP_LEN 6 #define NCI_INIT_RSP_LEN 28 #define NCI_RESET_RSP_LEN 4 #define NCI_RESET_NTF_LEN 13 #define NCI_GET_VERSION_CMD_LEN 8 #define NCI_GET_VERSION_RSP_LEN 12 struct nqx_dev { wait_queue_head_t read_wq; struct mutex read_mutex; struct mutex dev_ref_mutex; struct i2c_client *client; dev_t devno; struct class *nqx_class; Loading @@ -83,6 +83,8 @@ struct nqx_dev { bool irq_wake_up; spinlock_t irq_enabled_lock; unsigned int count_irq; /* NFC_IRQ Count */ unsigned int dev_ref_count; /* Initial CORE RESET notification */ unsigned int core_reset_ntf; /* CLK control */ Loading Loading @@ -489,16 +491,56 @@ static int nqx_ese_pwr(struct nqx_dev *nqx_dev, unsigned long int arg) static int nfc_open(struct inode *inode, struct file *filp) { int ret = 0; struct nqx_dev *nqx_dev = container_of(inode->i_cdev, struct nqx_dev, c_dev); filp->private_data = nqx_dev; nqx_init_stat(nqx_dev); mutex_lock(&nqx_dev->dev_ref_mutex); if (nqx_dev->dev_ref_count == 0) { nqx_enable_irq(nqx_dev); if (gpio_is_valid(nqx_dev->firm_gpio)) { gpio_set_value(nqx_dev->firm_gpio, 0); usleep_range(10000, 10100); } } nqx_dev->dev_ref_count = nqx_dev->dev_ref_count + 1; mutex_unlock(&nqx_dev->dev_ref_mutex); dev_dbg(&nqx_dev->client->dev, "%s: %d,%d\n", __func__, imajor(inode), iminor(inode)); return ret; return 0; } static int nfc_close(struct inode *inode, struct file *filp) { struct nqx_dev *nqx_dev = container_of(inode->i_cdev, struct nqx_dev, c_dev); mutex_lock(&nqx_dev->dev_ref_mutex); if (nqx_dev->dev_ref_count == 1) { nqx_disable_irq(nqx_dev); if (gpio_is_valid(nqx_dev->firm_gpio)) { gpio_set_value(nqx_dev->firm_gpio, 0); usleep_range(10000, 10100); } } if (nqx_dev->dev_ref_count > 0) nqx_dev->dev_ref_count = nqx_dev->dev_ref_count - 1; mutex_unlock(&nqx_dev->dev_ref_mutex); filp->private_data = NULL; return 0; } /* Loading Loading @@ -744,6 +786,7 @@ static const struct file_operations nfc_dev_fops = { .read = nfc_read, .write = nfc_write, .open = nfc_open, .release = nfc_close, .unlocked_ioctl = nfc_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = nfc_compat_ioctl Loading @@ -756,12 +799,11 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) int ret = 0; int gpio_retry_count = 0; unsigned char init_rsp_len = 0; unsigned char reset_ntf_len = 0; unsigned int enable_gpio = nqx_dev->en_gpio; char *nci_reset_cmd = NULL; char *nci_init_cmd = NULL; char *nci_init_rsp = NULL; char *nci_reset_rsp = NULL; char *nci_reset_ntf = NULL; char *nci_get_version_cmd = NULL; char *nci_get_version_rsp = NULL; Loading @@ -777,14 +819,8 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) goto done; } nci_init_cmd = kzalloc(NCI_INIT_CMD_LEN + 1, GFP_DMA | GFP_KERNEL); if (!nci_init_cmd) { ret = -ENOMEM; goto done; } nci_init_rsp = kzalloc(NCI_INIT_RSP_LEN + 1, GFP_DMA | GFP_KERNEL); if (!nci_init_rsp) { nci_reset_ntf = kzalloc(NCI_RESET_NTF_LEN + 1, GFP_DMA | GFP_KERNEL); if (!nci_reset_ntf) { ret = -ENOMEM; goto done; } Loading Loading @@ -883,34 +919,28 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) goto reset_enable_gpio; goto err_nfcc_hw_check; } nci_init_cmd[0] = 0x20; nci_init_cmd[1] = 0x01; nci_init_cmd[2] = 0x00; ret = nqx_standby_write(nqx_dev, nci_init_cmd, NCI_INIT_CMD_LEN); if (ret < 0) { dev_err(&client->dev, "%s: - i2c_master_send failed for Core INIT\n", __func__); goto err_nfcc_core_init_fail; } /* hardware dependent delay */ msleep(30); /* Read Response of INIT command */ ret = i2c_master_recv(client, nci_init_rsp, NCI_INIT_RSP_LEN); /* Read Notification of RESET command */ ret = i2c_master_recv(client, nci_reset_ntf, NCI_RESET_NTF_LEN); if (ret < 0) { dev_err(&client->dev, "%s: - i2c_master_recv Error\n", __func__); goto err_nfcc_core_init_fail; goto err_nfcc_hw_check; } init_rsp_len = 2 + nci_init_rsp[2]; /*payload + len*/ if (init_rsp_len > PAYLOAD_HEADER_LENGTH) { 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_init_rsp[init_rsp_len - 3]; nci_reset_ntf[reset_ntf_len - 3]; nqx_dev->nqx_info.info.rom_version = nci_init_rsp[init_rsp_len - 2]; nci_reset_ntf[reset_ntf_len - 2]; nqx_dev->nqx_info.info.fw_major = nci_init_rsp[init_rsp_len - 1]; nci_reset_ntf[reset_ntf_len - 1]; nqx_dev->nqx_info.info.fw_minor = nci_init_rsp[init_rsp_len]; nci_reset_ntf[reset_ntf_len]; } dev_dbg(&client->dev, "%s: - nq - reset cmd answer : NfcNciRx %x %x %x\n", Loading @@ -926,14 +956,6 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) nqx_dev->nqx_info.info.fw_minor); switch (nqx_dev->nqx_info.info.chip_type) { case NFCC_NQ_210: dev_dbg(&client->dev, "%s: ## NFCC == NQ210 ##\n", __func__); break; case NFCC_NQ_220: dev_dbg(&client->dev, "%s: ## NFCC == NQ220 ##\n", __func__); break; case NFCC_NQ_310: dev_dbg(&client->dev, "%s: ## NFCC == NQ310 ##\n", __func__); Loading @@ -946,23 +968,21 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) 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__); break; } /*Disable NFC by default to save power on boot*/ gpio_set_value(enable_gpio, 0);/* ULPM: Disable */ ret = 0; nqx_dev->nfc_ven_enabled = true; goto done; err_nfcc_core_init_fail: dev_err(&client->dev, "%s: - nq - reset cmd answer : NfcNciRx %x %x %x\n", __func__, nci_reset_rsp[0], nci_reset_rsp[1], nci_reset_rsp[2]); err_nfcc_hw_check: ret = -ENXIO; dev_err(&client->dev, Loading @@ -970,8 +990,7 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) done: kfree(nci_reset_rsp); kfree(nci_init_rsp); kfree(nci_init_cmd); kfree(nci_reset_ntf); kfree(nci_reset_cmd); kfree(nci_get_version_cmd); kfree(nci_get_version_rsp); Loading Loading @@ -1262,6 +1281,7 @@ static int nqx_probe(struct i2c_client *client, /* init mutex and queues */ init_waitqueue_head(&nqx_dev->read_wq); mutex_init(&nqx_dev->read_mutex); mutex_init(&nqx_dev->dev_ref_mutex); spin_lock_init(&nqx_dev->irq_enabled_lock); r = alloc_chrdev_region(&nqx_dev->devno, 0, DEV_COUNT, DEVICE_NAME); Loading Loading @@ -1410,6 +1430,7 @@ static int nqx_remove(struct i2c_client *client) class_destroy(nqx_dev->nqx_class); unregister_chrdev_region(nqx_dev->devno, DEV_COUNT); mutex_destroy(&nqx_dev->read_mutex); mutex_destroy(&nqx_dev->dev_ref_mutex); gpio_free(nqx_dev->clkreq_gpio); /* optional gpio, not sure was configured in probe */ if (nqx_dev->ese_gpio > 0) Loading Loading
drivers/nfc/nq-nci.c +73 −52 Original line number Diff line number Diff line Loading @@ -54,15 +54,15 @@ MODULE_DEVICE_TABLE(of, msm_match_table); #define WAKEUP_SRC_TIMEOUT (2000) #define MAX_RETRY_COUNT 3 #define NCI_RESET_CMD_LEN 4 #define NCI_INIT_CMD_LEN 3 #define NCI_RESET_RSP_LEN 6 #define NCI_INIT_RSP_LEN 28 #define NCI_RESET_RSP_LEN 4 #define NCI_RESET_NTF_LEN 13 #define NCI_GET_VERSION_CMD_LEN 8 #define NCI_GET_VERSION_RSP_LEN 12 struct nqx_dev { wait_queue_head_t read_wq; struct mutex read_mutex; struct mutex dev_ref_mutex; struct i2c_client *client; dev_t devno; struct class *nqx_class; Loading @@ -83,6 +83,8 @@ struct nqx_dev { bool irq_wake_up; spinlock_t irq_enabled_lock; unsigned int count_irq; /* NFC_IRQ Count */ unsigned int dev_ref_count; /* Initial CORE RESET notification */ unsigned int core_reset_ntf; /* CLK control */ Loading Loading @@ -489,16 +491,56 @@ static int nqx_ese_pwr(struct nqx_dev *nqx_dev, unsigned long int arg) static int nfc_open(struct inode *inode, struct file *filp) { int ret = 0; struct nqx_dev *nqx_dev = container_of(inode->i_cdev, struct nqx_dev, c_dev); filp->private_data = nqx_dev; nqx_init_stat(nqx_dev); mutex_lock(&nqx_dev->dev_ref_mutex); if (nqx_dev->dev_ref_count == 0) { nqx_enable_irq(nqx_dev); if (gpio_is_valid(nqx_dev->firm_gpio)) { gpio_set_value(nqx_dev->firm_gpio, 0); usleep_range(10000, 10100); } } nqx_dev->dev_ref_count = nqx_dev->dev_ref_count + 1; mutex_unlock(&nqx_dev->dev_ref_mutex); dev_dbg(&nqx_dev->client->dev, "%s: %d,%d\n", __func__, imajor(inode), iminor(inode)); return ret; return 0; } static int nfc_close(struct inode *inode, struct file *filp) { struct nqx_dev *nqx_dev = container_of(inode->i_cdev, struct nqx_dev, c_dev); mutex_lock(&nqx_dev->dev_ref_mutex); if (nqx_dev->dev_ref_count == 1) { nqx_disable_irq(nqx_dev); if (gpio_is_valid(nqx_dev->firm_gpio)) { gpio_set_value(nqx_dev->firm_gpio, 0); usleep_range(10000, 10100); } } if (nqx_dev->dev_ref_count > 0) nqx_dev->dev_ref_count = nqx_dev->dev_ref_count - 1; mutex_unlock(&nqx_dev->dev_ref_mutex); filp->private_data = NULL; return 0; } /* Loading Loading @@ -744,6 +786,7 @@ static const struct file_operations nfc_dev_fops = { .read = nfc_read, .write = nfc_write, .open = nfc_open, .release = nfc_close, .unlocked_ioctl = nfc_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = nfc_compat_ioctl Loading @@ -756,12 +799,11 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) int ret = 0; int gpio_retry_count = 0; unsigned char init_rsp_len = 0; unsigned char reset_ntf_len = 0; unsigned int enable_gpio = nqx_dev->en_gpio; char *nci_reset_cmd = NULL; char *nci_init_cmd = NULL; char *nci_init_rsp = NULL; char *nci_reset_rsp = NULL; char *nci_reset_ntf = NULL; char *nci_get_version_cmd = NULL; char *nci_get_version_rsp = NULL; Loading @@ -777,14 +819,8 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) goto done; } nci_init_cmd = kzalloc(NCI_INIT_CMD_LEN + 1, GFP_DMA | GFP_KERNEL); if (!nci_init_cmd) { ret = -ENOMEM; goto done; } nci_init_rsp = kzalloc(NCI_INIT_RSP_LEN + 1, GFP_DMA | GFP_KERNEL); if (!nci_init_rsp) { nci_reset_ntf = kzalloc(NCI_RESET_NTF_LEN + 1, GFP_DMA | GFP_KERNEL); if (!nci_reset_ntf) { ret = -ENOMEM; goto done; } Loading Loading @@ -883,34 +919,28 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) goto reset_enable_gpio; goto err_nfcc_hw_check; } nci_init_cmd[0] = 0x20; nci_init_cmd[1] = 0x01; nci_init_cmd[2] = 0x00; ret = nqx_standby_write(nqx_dev, nci_init_cmd, NCI_INIT_CMD_LEN); if (ret < 0) { dev_err(&client->dev, "%s: - i2c_master_send failed for Core INIT\n", __func__); goto err_nfcc_core_init_fail; } /* hardware dependent delay */ msleep(30); /* Read Response of INIT command */ ret = i2c_master_recv(client, nci_init_rsp, NCI_INIT_RSP_LEN); /* Read Notification of RESET command */ ret = i2c_master_recv(client, nci_reset_ntf, NCI_RESET_NTF_LEN); if (ret < 0) { dev_err(&client->dev, "%s: - i2c_master_recv Error\n", __func__); goto err_nfcc_core_init_fail; goto err_nfcc_hw_check; } init_rsp_len = 2 + nci_init_rsp[2]; /*payload + len*/ if (init_rsp_len > PAYLOAD_HEADER_LENGTH) { 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_init_rsp[init_rsp_len - 3]; nci_reset_ntf[reset_ntf_len - 3]; nqx_dev->nqx_info.info.rom_version = nci_init_rsp[init_rsp_len - 2]; nci_reset_ntf[reset_ntf_len - 2]; nqx_dev->nqx_info.info.fw_major = nci_init_rsp[init_rsp_len - 1]; nci_reset_ntf[reset_ntf_len - 1]; nqx_dev->nqx_info.info.fw_minor = nci_init_rsp[init_rsp_len]; nci_reset_ntf[reset_ntf_len]; } dev_dbg(&client->dev, "%s: - nq - reset cmd answer : NfcNciRx %x %x %x\n", Loading @@ -926,14 +956,6 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) nqx_dev->nqx_info.info.fw_minor); switch (nqx_dev->nqx_info.info.chip_type) { case NFCC_NQ_210: dev_dbg(&client->dev, "%s: ## NFCC == NQ210 ##\n", __func__); break; case NFCC_NQ_220: dev_dbg(&client->dev, "%s: ## NFCC == NQ220 ##\n", __func__); break; case NFCC_NQ_310: dev_dbg(&client->dev, "%s: ## NFCC == NQ310 ##\n", __func__); Loading @@ -946,23 +968,21 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) 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__); break; } /*Disable NFC by default to save power on boot*/ gpio_set_value(enable_gpio, 0);/* ULPM: Disable */ ret = 0; nqx_dev->nfc_ven_enabled = true; goto done; err_nfcc_core_init_fail: dev_err(&client->dev, "%s: - nq - reset cmd answer : NfcNciRx %x %x %x\n", __func__, nci_reset_rsp[0], nci_reset_rsp[1], nci_reset_rsp[2]); err_nfcc_hw_check: ret = -ENXIO; dev_err(&client->dev, Loading @@ -970,8 +990,7 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) done: kfree(nci_reset_rsp); kfree(nci_init_rsp); kfree(nci_init_cmd); kfree(nci_reset_ntf); kfree(nci_reset_cmd); kfree(nci_get_version_cmd); kfree(nci_get_version_rsp); Loading Loading @@ -1262,6 +1281,7 @@ static int nqx_probe(struct i2c_client *client, /* init mutex and queues */ init_waitqueue_head(&nqx_dev->read_wq); mutex_init(&nqx_dev->read_mutex); mutex_init(&nqx_dev->dev_ref_mutex); spin_lock_init(&nqx_dev->irq_enabled_lock); r = alloc_chrdev_region(&nqx_dev->devno, 0, DEV_COUNT, DEVICE_NAME); Loading Loading @@ -1410,6 +1430,7 @@ static int nqx_remove(struct i2c_client *client) class_destroy(nqx_dev->nqx_class); unregister_chrdev_region(nqx_dev->devno, DEV_COUNT); mutex_destroy(&nqx_dev->read_mutex); mutex_destroy(&nqx_dev->dev_ref_mutex); gpio_free(nqx_dev->clkreq_gpio); /* optional gpio, not sure was configured in probe */ if (nqx_dev->ese_gpio > 0) Loading