summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/nfc/nq-nci.c104
-rw-r--r--drivers/nfc/nq-nci.h9
-rw-r--r--include/linux/nfcinfo.h6
-rw-r--r--include/uapi/linux/Kbuild1
-rw-r--r--include/uapi/linux/nfc/Kbuild2
-rw-r--r--include/uapi/linux/nfc/nfcinfo.h21
6 files changed, 132 insertions, 11 deletions
diff --git a/drivers/nfc/nq-nci.c b/drivers/nfc/nq-nci.c
index 154310020997..2dd18dd78677 100644
--- a/drivers/nfc/nq-nci.c
+++ b/drivers/nfc/nq-nci.c
@@ -53,6 +53,7 @@ struct nqx_dev {
struct mutex read_mutex;
struct i2c_client *client;
struct miscdevice nqx_device;
+ union nqx_uinfo nqx_info;
/* NFC GPIO variables */
unsigned int irq_gpio;
unsigned int en_gpio;
@@ -467,6 +468,25 @@ int nfc_ioctl_core_reset_ntf(struct file *filp)
return nqx_dev->core_reset_ntf;
}
+/*
+ * Inside nfc_ioctl_nfcc_info
+ *
+ * @brief nfc_ioctl_nfcc_info
+ *
+ * Check the NQ Chipset and firmware version details
+ */
+unsigned int nfc_ioctl_nfcc_info(struct file *filp, unsigned long arg)
+{
+ unsigned int r = 0;
+ struct nqx_dev *nqx_dev = filp->private_data;
+
+ r = nqx_dev->nqx_info.i;
+ dev_dbg(&nqx_dev->client->dev,
+ "nqx nfc : nfc_ioctl_nfcc_info r = %d\n", r);
+
+ return r;
+}
+
static long nfc_ioctl(struct file *pfile, unsigned int cmd,
unsigned long arg)
{
@@ -489,6 +509,9 @@ static long nfc_ioctl(struct file *pfile, unsigned int cmd,
case NFCC_INITIAL_CORE_RESET_NTF:
r = nfc_ioctl_core_reset_ntf(pfile);
break;
+ case NFCC_GET_INFO:
+ r = nfc_ioctl_nfcc_info(pfile, arg);
+ break;
default:
r = -ENOIOCTLCMD;
}
@@ -508,13 +531,16 @@ static const struct file_operations nfc_dev_fops = {
};
/* Check for availability of NQ_ NFC controller hardware */
-static int nfcc_hw_check(struct i2c_client *client, unsigned int enable_gpio)
+static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev)
{
int ret = 0;
unsigned char raw_nci_reset_cmd[] = {0x20, 0x00, 0x01, 0x00};
+ unsigned char raw_nci_init_cmd[] = {0x20, 0x01, 0x00};
+ unsigned char nci_init_rsp[28];
unsigned char nci_reset_rsp[6];
-
+ unsigned char init_rsp_len = 0;
+ unsigned int enable_gpio = nqx_dev->en_gpio;
/* making sure that the NFCC starts in a clean state. */
gpio_set_value(enable_gpio, 0);/* ULPM: Disable */
/* hardware dependent delay */
@@ -536,16 +562,75 @@ static int nfcc_hw_check(struct i2c_client *client, unsigned int enable_gpio)
/* Read Response of RESET command */
ret = i2c_master_recv(client, nci_reset_rsp,
- sizeof(nci_reset_rsp));
+ sizeof(nci_reset_rsp));
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]);
+ "%s: - nq - reset cmd answer : NfcNciRx %x %x %x\n",
+ __func__, nci_reset_rsp[0],
+ nci_reset_rsp[1], nci_reset_rsp[2]);
+ if (ret < 0) {
+ dev_err(&client->dev,
+ "%s: - i2c_master_recv Error\n", __func__);
+ goto err_nfcc_hw_check;
+ }
+ ret = i2c_master_send(client, raw_nci_init_cmd,
+ sizeof(raw_nci_init_cmd));
+ if (ret < 0) {
+ dev_err(&client->dev,
+ "%s: - i2c_master_send Error\n", __func__);
+ goto err_nfcc_hw_check;
+ }
+ /* hardware dependent delay */
+ msleep(30);
+ /* Read Response of INIT command */
+ ret = i2c_master_recv(client, nci_init_rsp,
+ sizeof(nci_init_rsp));
if (ret < 0) {
dev_err(&client->dev,
"%s: - i2c_master_recv Error\n", __func__);
goto err_nfcc_hw_check;
}
+ init_rsp_len = 2 + nci_init_rsp[2]; /*payload + len*/
+ if (init_rsp_len > PAYLOAD_HEADER_LENGTH) {
+ nqx_dev->nqx_info.info.chip_type =
+ nci_init_rsp[init_rsp_len - 3];
+ nqx_dev->nqx_info.info.rom_version =
+ nci_init_rsp[init_rsp_len - 2];
+ nqx_dev->nqx_info.info.fw_major =
+ nci_init_rsp[init_rsp_len - 1];
+ nqx_dev->nqx_info.info.fw_minor =
+ nci_init_rsp[init_rsp_len];
+ }
+ dev_dbg(&nqx_dev->client->dev, "NQ NFCC chip_type = %x\n",
+ nqx_dev->nqx_info.info.chip_type);
+ dev_dbg(&nqx_dev->client->dev, "NQ fw version = %x.%x.%x\n",
+ nqx_dev->nqx_info.info.rom_version,
+ nqx_dev->nqx_info.info.fw_major,
+ 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__);
+ break;
+ case NFCC_NQ_330:
+ dev_dbg(&client->dev,
+ "%s: ## NFCC == NQ330 ##\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;
goto done;
@@ -566,9 +651,7 @@ done:
static int nqx_clock_select(struct nqx_dev *nqx_dev)
{
int r = 0;
-
- nqx_dev->s_clk =
- clk_get(&nqx_dev->client->dev, "ref_clk");
+ nqx_dev->s_clk = clk_get(&nqx_dev->client->dev, "ref_clk");
if (nqx_dev->s_clk == NULL)
goto err_clk;
@@ -867,8 +950,7 @@ static int nqx_probe(struct i2c_client *client,
* present before attempting further hardware initialisation.
*
*/
-
- r = nfcc_hw_check(client, platform_data->en_gpio);
+ r = nfcc_hw_check(client, nqx_dev);
if (r) {
/* make sure NFCC is not enabled */
gpio_set_value(platform_data->en_gpio, 0);
diff --git a/drivers/nfc/nq-nci.h b/drivers/nfc/nq-nci.h
index d62100c2d15a..c635e818b1f3 100644
--- a/drivers/nfc/nq-nci.h
+++ b/drivers/nfc/nq-nci.h
@@ -22,6 +22,7 @@
#include <linux/ioctl.h>
#include <linux/miscdevice.h>
+#include <linux/nfcinfo.h>
#define NFC_SET_PWR _IOW(0xE9, 0x01, unsigned int)
#define ESE_SET_PWR _IOW(0xE9, 0x02, unsigned int)
@@ -42,4 +43,12 @@ enum nfcc_initial_core_reset_ntf {
DEFAULT_INITIAL_CORE_RESET_NTF, /*2*/
};
+enum nfcc_chip_variant {
+ NFCC_NQ_210 = 0x48, /**< NFCC NQ210 */
+ NFCC_NQ_220 = 0x58, /**< NFCC NQ220 */
+ NFCC_NQ_310 = 0x40, /**< NFCC NQ310 */
+ NFCC_NQ_330 = 0x51, /**< NFCC NQ330 */
+ NFCC_NOT_SUPPORTED = 0xFF /**< NFCC is not supported */
+};
+
#endif
diff --git a/include/linux/nfcinfo.h b/include/linux/nfcinfo.h
new file mode 100644
index 000000000000..595544f92a37
--- /dev/null
+++ b/include/linux/nfcinfo.h
@@ -0,0 +1,6 @@
+#ifndef _NFCINFO_H
+#define _NFCINFO_H
+
+#include <uapi/linux/nfc/nfcinfo.h>
+
+#endif
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index d6ff882ad6a7..14bd1e806ad7 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -23,6 +23,7 @@ header-y += netfilter_ipv6/
header-y += usb/
header-y += wimax/
header-y += mfd/
+header-y += nfc/
genhdr-y += version.h
diff --git a/include/uapi/linux/nfc/Kbuild b/include/uapi/linux/nfc/Kbuild
new file mode 100644
index 000000000000..90710153e462
--- /dev/null
+++ b/include/uapi/linux/nfc/Kbuild
@@ -0,0 +1,2 @@
+#UAPI export list
+header-y += nfcinfo.h
diff --git a/include/uapi/linux/nfc/nfcinfo.h b/include/uapi/linux/nfc/nfcinfo.h
new file mode 100644
index 000000000000..df178e2bbae6
--- /dev/null
+++ b/include/uapi/linux/nfc/nfcinfo.h
@@ -0,0 +1,21 @@
+#ifndef _UAPI_NFCINFO_H_
+#define _UAPI_NFCINFO_H_
+
+#include <linux/ioctl.h>
+
+#define NFCC_MAGIC 0xE9
+#define NFCC_GET_INFO _IOW(NFCC_MAGIC, 0x09, unsigned int)
+
+struct nqx_devinfo {
+ unsigned char chip_type;
+ unsigned char rom_version;
+ unsigned char fw_major;
+ unsigned char fw_minor;
+};
+
+union nqx_uinfo {
+ unsigned int i;
+ struct nqx_devinfo info;
+};
+
+#endif