Loading drivers/nfc/nq-nci.c +148 −39 Original line number Diff line number Diff line Loading @@ -1050,17 +1050,145 @@ static const struct file_operations nfc_dev_fops = { #endif }; /* * function: get_nfcc_hw_info() * * @client: pointer to i2c_client * @nqx_dev: pointer to nqx_dev structure * @nci_reset_rsp_payload_len: payload length of NCI reset cmd * * Retrieves NFCC HW information based on the type of NFC chip * used on the device. Depending on the nci_reset_rsp_payload_len * value, core INIT command will be sent. * * NFC HW NCI version Send Core INIT cmd * NQ3xx or old 1.0 Yes * NQ4xx 2.0 No * Sn1x0x 2.0 No * * Return: error codes in case of any failure, * number of bytes read otherwise */ static int get_nfcc_hw_info(struct i2c_client *client, struct nqx_dev *nqx_dev, char nci_reset_rsp_payload_len) { int ret = 0; char *nci_init_cmd = NULL; char *nci_init_rsp = NULL; char *nci_reset_ntf = NULL; char *nfcc_hw_info = NULL; unsigned char nfcc_hw_info_len = 0; nci_init_cmd = kzalloc(NCI_INIT_CMD_LEN + 1, GFP_DMA | GFP_KERNEL); if (!nci_init_cmd) { ret = -ENOMEM; goto err_nfcc_hw_info; } nci_init_rsp = kzalloc(NCI_INIT_RSP_LEN + 1, GFP_DMA | GFP_KERNEL); if (!nci_init_rsp) { ret = -ENOMEM; goto err_nfcc_hw_info; } nci_reset_ntf = kzalloc(NCI_RESET_NTF_LEN + 1, GFP_DMA | GFP_KERNEL); if (!nci_reset_ntf) { ret = -ENOMEM; goto err_nfcc_hw_info; } if (nci_reset_rsp_payload_len == NCI_1_0_RESET_RSP_PAYLOAD_LEN) { /* * Chipset is NQ330 or older. * Send core INIT command to get HW info. */ 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_dbg(&client->dev, "%s: - i2c_master_send failed for Core INIT\n", __func__); goto err_nfcc_hw_info; } ret = is_data_available_for_read(nqx_dev); if (ret <= 0) { nqx_disable_irq(nqx_dev); goto err_nfcc_hw_info; } /* Read Response of INIT command */ ret = i2c_master_recv(client, nci_init_rsp, NCI_INIT_RSP_LEN); if (ret < 0) { dev_dbg(&client->dev, "%s: - i2c_master_recv get INIT rsp Error\n", __func__); goto err_nfcc_hw_info; } nfcc_hw_info = nci_init_rsp; } else { /* * Chipset is NQ4xx or later. * Retrieve NTF data from wait queue. */ ret = is_data_available_for_read(nqx_dev); if (ret <= 0) { nqx_disable_irq(nqx_dev); goto err_nfcc_hw_info; } /* 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: - i2c_master_recv get RESET ntf Error\n", __func__); goto err_nfcc_hw_info; } nfcc_hw_info = nci_reset_ntf; } /* Save NFCC HW info */ nfcc_hw_info_len = NCI_HEADER_LEN + nfcc_hw_info[NCI_PAYLOAD_LENGTH_INDEX]; if (nfcc_hw_info_len > PAYLOAD_HEADER_LENGTH) { nqx_dev->nqx_info.info.chip_type = nfcc_hw_info[nfcc_hw_info_len - NFCC_HW_CHIP_ID_OFFSET]; nqx_dev->nqx_info.info.rom_version = nfcc_hw_info[nfcc_hw_info_len - NFCC_HW_ROM_VER_OFFSET]; nqx_dev->nqx_info.info.fw_major = nfcc_hw_info[nfcc_hw_info_len - NFCC_HW_MAJOR_NO_OFFSET]; nqx_dev->nqx_info.info.fw_minor = nfcc_hw_info[nfcc_hw_info_len - NFCC_HW_MINOR_NO_OFFSET]; } err_nfcc_hw_info: kfree(nci_reset_ntf); kfree(nci_init_rsp); kfree(nci_init_cmd); return ret; } /* Check for availability of NQ_ NFC controller hardware */ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) { int ret = 0; int gpio_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; Loading @@ -1075,13 +1203,6 @@ 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) { Loading @@ -1096,7 +1217,6 @@ 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. */ gpio_set_value(enable_gpio, 1);/* HPD : Enable*/ /* hardware dependent delay */ Loading Loading @@ -1173,42 +1293,32 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) goto err_nfcc_hw_check; } /* Read Response of RESET command */ ret = i2c_master_recv(client, nci_reset_rsp, NCI_RESET_RSP_LEN); 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; /* Read Header of RESET command */ ret = i2c_master_recv(client, nci_reset_rsp, NCI_HEADER_LEN); if (ret != NCI_HEADER_LEN) { dev_dbg(&client->dev, "%s: - i2c_master_recv get RESET rsp header Error\n", __func__); goto err_nfcc_hw_check; } ret = is_data_available_for_read(nqx_dev); if (ret <= 0) { nqx_disable_irq(nqx_dev); 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__); goto err_nfcc_hw_check; } /* Read Notification of RESET command */ ret = i2c_master_recv(client, nci_reset_ntf, NCI_RESET_NTF_LEN); /* Retrieve NFCC HW info */ ret = get_nfcc_hw_info(client, nqx_dev, nci_reset_rsp[NCI_PAYLOAD_LENGTH_INDEX]); if (ret < 0) { dev_err(&client->dev, "%s: - i2c_master_recv Error\n", __func__); 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", __func__, nci_reset_rsp[0], Loading Loading @@ -1257,7 +1367,6 @@ 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); Loading drivers/nfc/nq-nci.h +9 −0 Original line number Diff line number Diff line Loading @@ -40,8 +40,17 @@ #define NCI_RESET_CMD_LEN 4 #define NCI_RESET_RSP_LEN 4 #define NCI_RESET_NTF_LEN 13 #define NCI_INIT_CMD_LEN 3 #define NCI_INIT_RSP_LEN 28 #define NCI_GET_VERSION_CMD_LEN 8 #define NCI_GET_VERSION_RSP_LEN 12 #define NCI_1_0_RESET_RSP_PAYLOAD_LEN 3 #define NCI_PAYLOAD_START_INDEX 3 #define NCI_PAYLOAD_LENGTH_INDEX (NCI_PAYLOAD_START_INDEX - 1) #define NFCC_HW_CHIP_ID_OFFSET 4 #define NFCC_HW_ROM_VER_OFFSET 3 #define NFCC_HW_MAJOR_NO_OFFSET 2 #define NFCC_HW_MINOR_NO_OFFSET 1 #define MAX_IRQ_WAIT_TIME (90) //in ms #define COLD_RESET_CMD_LEN 3 #define COLD_RESET_RSP_LEN 4 Loading Loading
drivers/nfc/nq-nci.c +148 −39 Original line number Diff line number Diff line Loading @@ -1050,17 +1050,145 @@ static const struct file_operations nfc_dev_fops = { #endif }; /* * function: get_nfcc_hw_info() * * @client: pointer to i2c_client * @nqx_dev: pointer to nqx_dev structure * @nci_reset_rsp_payload_len: payload length of NCI reset cmd * * Retrieves NFCC HW information based on the type of NFC chip * used on the device. Depending on the nci_reset_rsp_payload_len * value, core INIT command will be sent. * * NFC HW NCI version Send Core INIT cmd * NQ3xx or old 1.0 Yes * NQ4xx 2.0 No * Sn1x0x 2.0 No * * Return: error codes in case of any failure, * number of bytes read otherwise */ static int get_nfcc_hw_info(struct i2c_client *client, struct nqx_dev *nqx_dev, char nci_reset_rsp_payload_len) { int ret = 0; char *nci_init_cmd = NULL; char *nci_init_rsp = NULL; char *nci_reset_ntf = NULL; char *nfcc_hw_info = NULL; unsigned char nfcc_hw_info_len = 0; nci_init_cmd = kzalloc(NCI_INIT_CMD_LEN + 1, GFP_DMA | GFP_KERNEL); if (!nci_init_cmd) { ret = -ENOMEM; goto err_nfcc_hw_info; } nci_init_rsp = kzalloc(NCI_INIT_RSP_LEN + 1, GFP_DMA | GFP_KERNEL); if (!nci_init_rsp) { ret = -ENOMEM; goto err_nfcc_hw_info; } nci_reset_ntf = kzalloc(NCI_RESET_NTF_LEN + 1, GFP_DMA | GFP_KERNEL); if (!nci_reset_ntf) { ret = -ENOMEM; goto err_nfcc_hw_info; } if (nci_reset_rsp_payload_len == NCI_1_0_RESET_RSP_PAYLOAD_LEN) { /* * Chipset is NQ330 or older. * Send core INIT command to get HW info. */ 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_dbg(&client->dev, "%s: - i2c_master_send failed for Core INIT\n", __func__); goto err_nfcc_hw_info; } ret = is_data_available_for_read(nqx_dev); if (ret <= 0) { nqx_disable_irq(nqx_dev); goto err_nfcc_hw_info; } /* Read Response of INIT command */ ret = i2c_master_recv(client, nci_init_rsp, NCI_INIT_RSP_LEN); if (ret < 0) { dev_dbg(&client->dev, "%s: - i2c_master_recv get INIT rsp Error\n", __func__); goto err_nfcc_hw_info; } nfcc_hw_info = nci_init_rsp; } else { /* * Chipset is NQ4xx or later. * Retrieve NTF data from wait queue. */ ret = is_data_available_for_read(nqx_dev); if (ret <= 0) { nqx_disable_irq(nqx_dev); goto err_nfcc_hw_info; } /* 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: - i2c_master_recv get RESET ntf Error\n", __func__); goto err_nfcc_hw_info; } nfcc_hw_info = nci_reset_ntf; } /* Save NFCC HW info */ nfcc_hw_info_len = NCI_HEADER_LEN + nfcc_hw_info[NCI_PAYLOAD_LENGTH_INDEX]; if (nfcc_hw_info_len > PAYLOAD_HEADER_LENGTH) { nqx_dev->nqx_info.info.chip_type = nfcc_hw_info[nfcc_hw_info_len - NFCC_HW_CHIP_ID_OFFSET]; nqx_dev->nqx_info.info.rom_version = nfcc_hw_info[nfcc_hw_info_len - NFCC_HW_ROM_VER_OFFSET]; nqx_dev->nqx_info.info.fw_major = nfcc_hw_info[nfcc_hw_info_len - NFCC_HW_MAJOR_NO_OFFSET]; nqx_dev->nqx_info.info.fw_minor = nfcc_hw_info[nfcc_hw_info_len - NFCC_HW_MINOR_NO_OFFSET]; } err_nfcc_hw_info: kfree(nci_reset_ntf); kfree(nci_init_rsp); kfree(nci_init_cmd); return ret; } /* Check for availability of NQ_ NFC controller hardware */ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) { int ret = 0; int gpio_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; Loading @@ -1075,13 +1203,6 @@ 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) { Loading @@ -1096,7 +1217,6 @@ 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. */ gpio_set_value(enable_gpio, 1);/* HPD : Enable*/ /* hardware dependent delay */ Loading Loading @@ -1173,42 +1293,32 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) goto err_nfcc_hw_check; } /* Read Response of RESET command */ ret = i2c_master_recv(client, nci_reset_rsp, NCI_RESET_RSP_LEN); 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; /* Read Header of RESET command */ ret = i2c_master_recv(client, nci_reset_rsp, NCI_HEADER_LEN); if (ret != NCI_HEADER_LEN) { dev_dbg(&client->dev, "%s: - i2c_master_recv get RESET rsp header Error\n", __func__); goto err_nfcc_hw_check; } ret = is_data_available_for_read(nqx_dev); if (ret <= 0) { nqx_disable_irq(nqx_dev); 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__); goto err_nfcc_hw_check; } /* Read Notification of RESET command */ ret = i2c_master_recv(client, nci_reset_ntf, NCI_RESET_NTF_LEN); /* Retrieve NFCC HW info */ ret = get_nfcc_hw_info(client, nqx_dev, nci_reset_rsp[NCI_PAYLOAD_LENGTH_INDEX]); if (ret < 0) { dev_err(&client->dev, "%s: - i2c_master_recv Error\n", __func__); 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", __func__, nci_reset_rsp[0], Loading Loading @@ -1257,7 +1367,6 @@ 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); Loading
drivers/nfc/nq-nci.h +9 −0 Original line number Diff line number Diff line Loading @@ -40,8 +40,17 @@ #define NCI_RESET_CMD_LEN 4 #define NCI_RESET_RSP_LEN 4 #define NCI_RESET_NTF_LEN 13 #define NCI_INIT_CMD_LEN 3 #define NCI_INIT_RSP_LEN 28 #define NCI_GET_VERSION_CMD_LEN 8 #define NCI_GET_VERSION_RSP_LEN 12 #define NCI_1_0_RESET_RSP_PAYLOAD_LEN 3 #define NCI_PAYLOAD_START_INDEX 3 #define NCI_PAYLOAD_LENGTH_INDEX (NCI_PAYLOAD_START_INDEX - 1) #define NFCC_HW_CHIP_ID_OFFSET 4 #define NFCC_HW_ROM_VER_OFFSET 3 #define NFCC_HW_MAJOR_NO_OFFSET 2 #define NFCC_HW_MINOR_NO_OFFSET 1 #define MAX_IRQ_WAIT_TIME (90) //in ms #define COLD_RESET_CMD_LEN 3 #define COLD_RESET_RSP_LEN 4 Loading