Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ec02502f authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "NFC: Add support for core init command"

parents af183c6b 020bfa88
Loading
Loading
Loading
Loading
+148 −39
Original line number Diff line number Diff line
@@ -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;

@@ -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) {
@@ -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 */
@@ -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],
@@ -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);
+9 −0
Original line number Diff line number Diff line
@@ -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