Loading drivers/nfc/nq-nci.c +172 −27 Original line number Diff line number Diff line Loading @@ -41,21 +41,9 @@ static const struct of_device_id msm_match_table[] = { MODULE_DEVICE_TABLE(of, msm_match_table); #define DEV_COUNT 1 #define DEVICE_NAME "nq-nci" #define CLASS_NAME "nqx" #define MAX_BUFFER_SIZE (320) #define WAKEUP_SRC_TIMEOUT (2000) #define MAX_RETRY_COUNT 3 #define NCI_RESET_CMD_LEN 4 #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 #define MAX_IRQ_WAIT_TIME (90) //in ms struct nqx_dev { wait_queue_head_t read_wq; wait_queue_head_t cold_reset_read_wq; struct mutex read_mutex; struct mutex dev_ref_mutex; struct i2c_client *client; Loading @@ -72,10 +60,14 @@ struct nqx_dev { unsigned int ese_gpio; /* NFC VEN pin state powered by Nfc */ bool nfc_ven_enabled; /* NFC state reflected from MW */ bool nfc_enabled; /* NFC_IRQ state */ bool irq_enabled; /* NFC_IRQ wake-up state */ bool irq_wake_up; bool cold_reset_rsp_pending; uint8_t cold_reset_status; spinlock_t irq_enabled_lock; unsigned int count_irq; /* NFC_IRQ Count */ Loading @@ -97,6 +89,9 @@ static int nfcc_reboot(struct notifier_block *notifier, unsigned long val, static int nqx_clock_select(struct nqx_dev *nqx_dev); /*clock disable function*/ static int nqx_clock_deselect(struct nqx_dev *nqx_dev); static int nqx_standby_write(struct nqx_dev *nqx_dev, const unsigned char *buf, size_t len); static struct notifier_block nfcc_notifier = { .notifier_call = nfcc_reboot, .next = NULL, Loading Loading @@ -159,6 +154,92 @@ static irqreturn_t nqx_dev_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } static int is_data_available_for_read(struct nqx_dev *nqx_dev) { int ret; nqx_enable_irq(nqx_dev); ret = wait_event_interruptible_timeout(nqx_dev->read_wq, !nqx_dev->irq_enabled, msecs_to_jiffies(MAX_IRQ_WAIT_TIME)); return ret; } static int send_cold_reset_cmd(struct nqx_dev *nqx_dev) { int ret; char *cold_reset_cmd = NULL; if (gpio_get_value(nqx_dev->firm_gpio)) { dev_err(&nqx_dev->client->dev, "FW download in-progress\n"); return -EBUSY; } if (!gpio_get_value(nqx_dev->en_gpio)) { dev_err(&nqx_dev->client->dev, "VEN LOW - NFCC powered off\n"); return -ENODEV; } cold_reset_cmd = kzalloc(COLD_RESET_CMD_LEN, GFP_DMA | GFP_KERNEL); if (!cold_reset_cmd) return -ENOMEM; cold_reset_cmd[0] = COLD_RESET_CMD_GID; cold_reset_cmd[1] = COLD_RESET_OID; cold_reset_cmd[2] = COLD_RESET_CMD_PAYLOAD_LEN; ret = nqx_standby_write(nqx_dev, cold_reset_cmd, COLD_RESET_CMD_LEN); if (ret < 0) { dev_err(&nqx_dev->client->dev, "%s: write failed after max retry\n", __func__); } kfree(cold_reset_cmd); return ret; } static void read_cold_reset_rsp(struct nqx_dev *nqx_dev, bool isNfcEnabled, char *header) { int ret = -1; char *cold_reset_rsp = NULL; cold_reset_rsp = kzalloc(COLD_RESET_RSP_LEN, GFP_DMA | GFP_KERNEL); if (!cold_reset_rsp) return; /* * read header also if NFC is disabled * for enable case, will be taken care by nfc_read thread */ if (!isNfcEnabled) { ret = i2c_master_recv(nqx_dev->client, cold_reset_rsp, NCI_HEADER_LEN); if (ret != NCI_HEADER_LEN) { dev_err(&nqx_dev->client->dev, "%s: failure to read cold reset rsp header\n", __func__); goto error; } } else { memcpy(cold_reset_rsp, header, NCI_HEADER_LEN); } if ((NCI_HEADER_LEN + cold_reset_rsp[2]) > COLD_RESET_RSP_LEN) { dev_err(&nqx_dev->client->dev, "%s: - invalid response for cold_reset\n", __func__); ret = -EINVAL; goto error; } ret = i2c_master_recv(nqx_dev->client, &cold_reset_rsp[NCI_PAYLOAD_IDX], cold_reset_rsp[2]); if (ret != cold_reset_rsp[2]) { dev_err(&nqx_dev->client->dev, "%s: failure to read cold reset rsp status\n", __func__); goto error; } nqx_dev->cold_reset_status = cold_reset_rsp[NCI_PAYLOAD_IDX]; error: kfree(cold_reset_rsp); } static ssize_t nfc_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) { Loading Loading @@ -232,6 +313,24 @@ static ssize_t nfc_read(struct file *filp, char __user *buf, ret = -EIO; goto err; } /* check if it's response of cold reset command * NFC HAL process shouldn't receive this data as * command was sent by eSE HAL */ if (nqx_dev->cold_reset_rsp_pending && (tmp[0] == COLD_RESET_RSP_GID) && (tmp[1] == COLD_RESET_OID)) { read_cold_reset_rsp(nqx_dev, true, tmp); nqx_dev->cold_reset_rsp_pending = false; wake_up_interruptible(&nqx_dev->cold_reset_read_wq); mutex_unlock(&nqx_dev->read_mutex); /* * NFC process doesn't know about cold reset command * being sent as it was initiated by eSE process * we shouldn't return any data to NFC process */ return 0; } #ifdef NFC_KERNEL_BU dev_dbg(&nqx_dev->client->dev, "%s : NfcNciRx %x %x %x\n", __func__, tmp[0], tmp[1], tmp[2]); Loading Loading @@ -326,17 +425,19 @@ static int nqx_standby_write(struct nqx_dev *nqx_dev, return ret; } /* * Power management of the SN100 eSE * eSE and NFCC both are powered using VEN gpio in SN100, * VEN HIGH - eSE and NFCC both are powered on * VEN LOW - eSE and NFCC both are power down */ static int sn100_ese_pwr(struct nqx_dev *nqx_dev, unsigned long arg) { int r = -1; if (arg == 0) { if (arg == ESE_POWER_ON) { /** * Let's store the NFC VEN pin state * will check stored value in case of eSE power off request, Loading @@ -355,7 +456,7 @@ static int sn100_ese_pwr(struct nqx_dev *nqx_dev, unsigned long arg) dev_dbg(&nqx_dev->client->dev, "en_gpio already HIGH\n"); } r = 0; } else if (arg == 1) { } else if (arg == ESE_POWER_OFF) { if (!nqx_dev->nfc_ven_enabled) { dev_dbg(&nqx_dev->client->dev, "NFC not enabled, disabling en_gpio\n"); gpio_set_value(nqx_dev->en_gpio, 0); Loading @@ -365,7 +466,40 @@ static int sn100_ese_pwr(struct nqx_dev *nqx_dev, unsigned long arg) dev_dbg(&nqx_dev->client->dev, "keep en_gpio high as NFC is enabled\n"); } r = 0; } else if (arg == 3) { } else if (arg == ESE_COLD_RESET) { // set default value for status as failure nqx_dev->cold_reset_status = EIO; r = send_cold_reset_cmd(nqx_dev); if (r <= 0) { dev_err(&nqx_dev->client->dev, "failed to send cold reset command\n"); return nqx_dev->cold_reset_status; } nqx_dev->cold_reset_rsp_pending = true; // check if NFC is enabled if (nqx_dev->nfc_enabled) { /* * nfc_read thread will initiate cold reset response * and it will signal for data available */ wait_event_interruptible(nqx_dev->cold_reset_read_wq, !nqx_dev->cold_reset_rsp_pending); } else { /* * Read data as NFC thread is not active */ r = is_data_available_for_read(nqx_dev); if (r <= 0) { nqx_disable_irq(nqx_dev); nqx_dev->cold_reset_rsp_pending = false; return nqx_dev->cold_reset_status; } read_cold_reset_rsp(nqx_dev, false, NULL); nqx_dev->cold_reset_rsp_pending = false; } r = nqx_dev->cold_reset_status; } else if (arg == ESE_POWER_STATE) { // eSE power state r = gpio_get_value(nqx_dev->en_gpio); } Loading Loading @@ -556,7 +690,7 @@ int nfc_ioctl_power_states(struct file *filp, unsigned long arg) int r = 0; struct nqx_dev *nqx_dev = filp->private_data; if (arg == 0) { if (arg == NFC_POWER_OFF) { /* * We are attempting a hardware reset so let us disable * interrupts to avoid spurious notifications to upper Loading Loading @@ -590,7 +724,7 @@ int nfc_ioctl_power_states(struct file *filp, unsigned long arg) dev_err(&nqx_dev->client->dev, "unable to disable clock\n"); } nqx_dev->nfc_ven_enabled = false; } else if (arg == 1) { } else if (arg == NFC_POWER_ON) { nqx_enable_irq(nqx_dev); dev_dbg(&nqx_dev->client->dev, "gpio_set_value enable: %s: info: %p\n", Loading @@ -607,7 +741,7 @@ int nfc_ioctl_power_states(struct file *filp, unsigned long arg) dev_err(&nqx_dev->client->dev, "unable to enable clock\n"); } nqx_dev->nfc_ven_enabled = true; } else if (arg == 2) { } else if (arg == NFC_FW_DWL_VEN_TOGGLE) { /* * We are switching to Dowload Mode, toggle the enable pin * in order to set the NFCC in the new mode Loading @@ -629,7 +763,7 @@ int nfc_ioctl_power_states(struct file *filp, unsigned long arg) usleep_range(10000, 10100); gpio_set_value(nqx_dev->en_gpio, 1); usleep_range(10000, 10100); } else if (arg == 4) { } else if (arg == NFC_FW_DWL_HIGH) { /* * Setting firmware download gpio to HIGH for SN100U * before FW download start Loading @@ -641,7 +775,7 @@ int nfc_ioctl_power_states(struct file *filp, unsigned long arg) } else dev_err(&nqx_dev->client->dev, "firm_gpio is invalid\n"); } else if (arg == 6) { } else if (arg == NFC_FW_DWL_LOW) { /* * Setting firmware download gpio to LOW for SN100U * FW download finished Loading @@ -654,6 +788,16 @@ int nfc_ioctl_power_states(struct file *filp, unsigned long arg) dev_err(&nqx_dev->client->dev, "firm_gpio is invalid\n"); } } else if (arg == NFC_ENABLE) { /* * Setting flag true when NFC is enabled */ nqx_dev->nfc_enabled = true; } else if (arg == NFC_DISABLE) { /* * Setting flag false when NFC is disabled */ nqx_dev->nfc_enabled = false; } else { r = -ENOIOCTLCMD; } Loading Loading @@ -897,9 +1041,8 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) } goto err_nfcc_reset_failed; } nqx_enable_irq(nqx_dev); ret = wait_event_interruptible_timeout(nqx_dev->read_wq, !nqx_dev->irq_enabled, msecs_to_jiffies(MAX_IRQ_WAIT_TIME)); ret = is_data_available_for_read(nqx_dev); if (ret <= 0) { nqx_disable_irq(nqx_dev); goto err_nfcc_hw_check; Loading @@ -915,9 +1058,8 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) goto reset_enable_gpio; goto err_nfcc_hw_check; } nqx_enable_irq(nqx_dev); ret = wait_event_interruptible_timeout(nqx_dev->read_wq, !nqx_dev->irq_enabled, msecs_to_jiffies(MAX_IRQ_WAIT_TIME)); ret = is_data_available_for_read(nqx_dev); if (ret <= 0) { nqx_disable_irq(nqx_dev); goto err_nfcc_hw_check; Loading Loading @@ -1280,6 +1422,7 @@ static int nqx_probe(struct i2c_client *client, /* init mutex and queues */ init_waitqueue_head(&nqx_dev->read_wq); init_waitqueue_head(&nqx_dev->cold_reset_read_wq); mutex_init(&nqx_dev->read_mutex); mutex_init(&nqx_dev->dev_ref_mutex); spin_lock_init(&nqx_dev->irq_enabled_lock); Loading Loading @@ -1362,6 +1505,8 @@ static int nqx_probe(struct i2c_client *client, device_set_wakeup_capable(&client->dev, true); i2c_set_clientdata(client, nqx_dev); nqx_dev->irq_wake_up = false; nqx_dev->cold_reset_rsp_pending = false; nqx_dev->nfc_enabled = false; dev_err(&client->dev, "%s: probing NFCC NQxxx exited successfully\n", Loading drivers/nfc/nq-nci.h +53 −0 Original line number Diff line number Diff line Loading @@ -24,12 +24,65 @@ #define SET_EMULATOR_TEST_POINT _IOW(0xE9, 0x05, unsigned int) #define NFCC_INITIAL_CORE_RESET_NTF _IOW(0xE9, 0x10, unsigned int) #define DEV_COUNT 1 #define DEVICE_NAME "nq-nci" #define CLASS_NAME "nqx" #define MAX_BUFFER_SIZE (320) #define WAKEUP_SRC_TIMEOUT (2000) #define NCI_HEADER_LEN 3 #define NCI_PAYLOAD_IDX 3 #define MAX_RETRY_COUNT 3 #define NCI_RESET_CMD_LEN 4 #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 #define MAX_IRQ_WAIT_TIME (90) //in ms #define COLD_RESET_CMD_LEN 3 #define COLD_RESET_RSP_LEN 4 #define COLD_RESET_CMD_GID 0x2F #define COLD_RESET_CMD_PAYLOAD_LEN 0x00 #define COLD_RESET_RSP_GID 0x4F #define COLD_RESET_OID 0x1E #define NFC_RX_BUFFER_CNT_START (0x0) #define PAYLOAD_HEADER_LENGTH (0x3) #define PAYLOAD_LENGTH_MAX (256) #define BYTE (0x8) #define NCI_IDENTIFIER (0x10) enum ese_ioctl_request { /* eSE POWER ON */ ESE_POWER_ON = 0, /* eSE POWER OFF */ ESE_POWER_OFF, /* eSE COLD RESET */ ESE_COLD_RESET, /* eSE POWER STATE */ ESE_POWER_STATE }; enum nfcc_ioctl_request { /* NFC disable request with VEN LOW */ NFC_POWER_OFF = 0, /* NFC enable request with VEN Toggle */ NFC_POWER_ON, /* firmware download request with VEN Toggle */ NFC_FW_DWL_VEN_TOGGLE, /* ISO reset request */ NFC_ISO_RESET, /* request for firmware download gpio HIGH */ NFC_FW_DWL_HIGH, /* hard reset request */ NFC_HARD_RESET, /* request for firmware download gpio LOW */ NFC_FW_DWL_LOW, /* NFC enable without VEN gpio modification */ NFC_ENABLE, /* NFC disable without VEN gpio modification */ NFC_DISABLE }; enum nfcc_initial_core_reset_ntf { TIMEDOUT_INITIAL_CORE_RESET_NTF = 0, /* 0*/ ARRIVED_INITIAL_CORE_RESET_NTF, /* 1 */ Loading Loading
drivers/nfc/nq-nci.c +172 −27 Original line number Diff line number Diff line Loading @@ -41,21 +41,9 @@ static const struct of_device_id msm_match_table[] = { MODULE_DEVICE_TABLE(of, msm_match_table); #define DEV_COUNT 1 #define DEVICE_NAME "nq-nci" #define CLASS_NAME "nqx" #define MAX_BUFFER_SIZE (320) #define WAKEUP_SRC_TIMEOUT (2000) #define MAX_RETRY_COUNT 3 #define NCI_RESET_CMD_LEN 4 #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 #define MAX_IRQ_WAIT_TIME (90) //in ms struct nqx_dev { wait_queue_head_t read_wq; wait_queue_head_t cold_reset_read_wq; struct mutex read_mutex; struct mutex dev_ref_mutex; struct i2c_client *client; Loading @@ -72,10 +60,14 @@ struct nqx_dev { unsigned int ese_gpio; /* NFC VEN pin state powered by Nfc */ bool nfc_ven_enabled; /* NFC state reflected from MW */ bool nfc_enabled; /* NFC_IRQ state */ bool irq_enabled; /* NFC_IRQ wake-up state */ bool irq_wake_up; bool cold_reset_rsp_pending; uint8_t cold_reset_status; spinlock_t irq_enabled_lock; unsigned int count_irq; /* NFC_IRQ Count */ Loading @@ -97,6 +89,9 @@ static int nfcc_reboot(struct notifier_block *notifier, unsigned long val, static int nqx_clock_select(struct nqx_dev *nqx_dev); /*clock disable function*/ static int nqx_clock_deselect(struct nqx_dev *nqx_dev); static int nqx_standby_write(struct nqx_dev *nqx_dev, const unsigned char *buf, size_t len); static struct notifier_block nfcc_notifier = { .notifier_call = nfcc_reboot, .next = NULL, Loading Loading @@ -159,6 +154,92 @@ static irqreturn_t nqx_dev_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } static int is_data_available_for_read(struct nqx_dev *nqx_dev) { int ret; nqx_enable_irq(nqx_dev); ret = wait_event_interruptible_timeout(nqx_dev->read_wq, !nqx_dev->irq_enabled, msecs_to_jiffies(MAX_IRQ_WAIT_TIME)); return ret; } static int send_cold_reset_cmd(struct nqx_dev *nqx_dev) { int ret; char *cold_reset_cmd = NULL; if (gpio_get_value(nqx_dev->firm_gpio)) { dev_err(&nqx_dev->client->dev, "FW download in-progress\n"); return -EBUSY; } if (!gpio_get_value(nqx_dev->en_gpio)) { dev_err(&nqx_dev->client->dev, "VEN LOW - NFCC powered off\n"); return -ENODEV; } cold_reset_cmd = kzalloc(COLD_RESET_CMD_LEN, GFP_DMA | GFP_KERNEL); if (!cold_reset_cmd) return -ENOMEM; cold_reset_cmd[0] = COLD_RESET_CMD_GID; cold_reset_cmd[1] = COLD_RESET_OID; cold_reset_cmd[2] = COLD_RESET_CMD_PAYLOAD_LEN; ret = nqx_standby_write(nqx_dev, cold_reset_cmd, COLD_RESET_CMD_LEN); if (ret < 0) { dev_err(&nqx_dev->client->dev, "%s: write failed after max retry\n", __func__); } kfree(cold_reset_cmd); return ret; } static void read_cold_reset_rsp(struct nqx_dev *nqx_dev, bool isNfcEnabled, char *header) { int ret = -1; char *cold_reset_rsp = NULL; cold_reset_rsp = kzalloc(COLD_RESET_RSP_LEN, GFP_DMA | GFP_KERNEL); if (!cold_reset_rsp) return; /* * read header also if NFC is disabled * for enable case, will be taken care by nfc_read thread */ if (!isNfcEnabled) { ret = i2c_master_recv(nqx_dev->client, cold_reset_rsp, NCI_HEADER_LEN); if (ret != NCI_HEADER_LEN) { dev_err(&nqx_dev->client->dev, "%s: failure to read cold reset rsp header\n", __func__); goto error; } } else { memcpy(cold_reset_rsp, header, NCI_HEADER_LEN); } if ((NCI_HEADER_LEN + cold_reset_rsp[2]) > COLD_RESET_RSP_LEN) { dev_err(&nqx_dev->client->dev, "%s: - invalid response for cold_reset\n", __func__); ret = -EINVAL; goto error; } ret = i2c_master_recv(nqx_dev->client, &cold_reset_rsp[NCI_PAYLOAD_IDX], cold_reset_rsp[2]); if (ret != cold_reset_rsp[2]) { dev_err(&nqx_dev->client->dev, "%s: failure to read cold reset rsp status\n", __func__); goto error; } nqx_dev->cold_reset_status = cold_reset_rsp[NCI_PAYLOAD_IDX]; error: kfree(cold_reset_rsp); } static ssize_t nfc_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) { Loading Loading @@ -232,6 +313,24 @@ static ssize_t nfc_read(struct file *filp, char __user *buf, ret = -EIO; goto err; } /* check if it's response of cold reset command * NFC HAL process shouldn't receive this data as * command was sent by eSE HAL */ if (nqx_dev->cold_reset_rsp_pending && (tmp[0] == COLD_RESET_RSP_GID) && (tmp[1] == COLD_RESET_OID)) { read_cold_reset_rsp(nqx_dev, true, tmp); nqx_dev->cold_reset_rsp_pending = false; wake_up_interruptible(&nqx_dev->cold_reset_read_wq); mutex_unlock(&nqx_dev->read_mutex); /* * NFC process doesn't know about cold reset command * being sent as it was initiated by eSE process * we shouldn't return any data to NFC process */ return 0; } #ifdef NFC_KERNEL_BU dev_dbg(&nqx_dev->client->dev, "%s : NfcNciRx %x %x %x\n", __func__, tmp[0], tmp[1], tmp[2]); Loading Loading @@ -326,17 +425,19 @@ static int nqx_standby_write(struct nqx_dev *nqx_dev, return ret; } /* * Power management of the SN100 eSE * eSE and NFCC both are powered using VEN gpio in SN100, * VEN HIGH - eSE and NFCC both are powered on * VEN LOW - eSE and NFCC both are power down */ static int sn100_ese_pwr(struct nqx_dev *nqx_dev, unsigned long arg) { int r = -1; if (arg == 0) { if (arg == ESE_POWER_ON) { /** * Let's store the NFC VEN pin state * will check stored value in case of eSE power off request, Loading @@ -355,7 +456,7 @@ static int sn100_ese_pwr(struct nqx_dev *nqx_dev, unsigned long arg) dev_dbg(&nqx_dev->client->dev, "en_gpio already HIGH\n"); } r = 0; } else if (arg == 1) { } else if (arg == ESE_POWER_OFF) { if (!nqx_dev->nfc_ven_enabled) { dev_dbg(&nqx_dev->client->dev, "NFC not enabled, disabling en_gpio\n"); gpio_set_value(nqx_dev->en_gpio, 0); Loading @@ -365,7 +466,40 @@ static int sn100_ese_pwr(struct nqx_dev *nqx_dev, unsigned long arg) dev_dbg(&nqx_dev->client->dev, "keep en_gpio high as NFC is enabled\n"); } r = 0; } else if (arg == 3) { } else if (arg == ESE_COLD_RESET) { // set default value for status as failure nqx_dev->cold_reset_status = EIO; r = send_cold_reset_cmd(nqx_dev); if (r <= 0) { dev_err(&nqx_dev->client->dev, "failed to send cold reset command\n"); return nqx_dev->cold_reset_status; } nqx_dev->cold_reset_rsp_pending = true; // check if NFC is enabled if (nqx_dev->nfc_enabled) { /* * nfc_read thread will initiate cold reset response * and it will signal for data available */ wait_event_interruptible(nqx_dev->cold_reset_read_wq, !nqx_dev->cold_reset_rsp_pending); } else { /* * Read data as NFC thread is not active */ r = is_data_available_for_read(nqx_dev); if (r <= 0) { nqx_disable_irq(nqx_dev); nqx_dev->cold_reset_rsp_pending = false; return nqx_dev->cold_reset_status; } read_cold_reset_rsp(nqx_dev, false, NULL); nqx_dev->cold_reset_rsp_pending = false; } r = nqx_dev->cold_reset_status; } else if (arg == ESE_POWER_STATE) { // eSE power state r = gpio_get_value(nqx_dev->en_gpio); } Loading Loading @@ -556,7 +690,7 @@ int nfc_ioctl_power_states(struct file *filp, unsigned long arg) int r = 0; struct nqx_dev *nqx_dev = filp->private_data; if (arg == 0) { if (arg == NFC_POWER_OFF) { /* * We are attempting a hardware reset so let us disable * interrupts to avoid spurious notifications to upper Loading Loading @@ -590,7 +724,7 @@ int nfc_ioctl_power_states(struct file *filp, unsigned long arg) dev_err(&nqx_dev->client->dev, "unable to disable clock\n"); } nqx_dev->nfc_ven_enabled = false; } else if (arg == 1) { } else if (arg == NFC_POWER_ON) { nqx_enable_irq(nqx_dev); dev_dbg(&nqx_dev->client->dev, "gpio_set_value enable: %s: info: %p\n", Loading @@ -607,7 +741,7 @@ int nfc_ioctl_power_states(struct file *filp, unsigned long arg) dev_err(&nqx_dev->client->dev, "unable to enable clock\n"); } nqx_dev->nfc_ven_enabled = true; } else if (arg == 2) { } else if (arg == NFC_FW_DWL_VEN_TOGGLE) { /* * We are switching to Dowload Mode, toggle the enable pin * in order to set the NFCC in the new mode Loading @@ -629,7 +763,7 @@ int nfc_ioctl_power_states(struct file *filp, unsigned long arg) usleep_range(10000, 10100); gpio_set_value(nqx_dev->en_gpio, 1); usleep_range(10000, 10100); } else if (arg == 4) { } else if (arg == NFC_FW_DWL_HIGH) { /* * Setting firmware download gpio to HIGH for SN100U * before FW download start Loading @@ -641,7 +775,7 @@ int nfc_ioctl_power_states(struct file *filp, unsigned long arg) } else dev_err(&nqx_dev->client->dev, "firm_gpio is invalid\n"); } else if (arg == 6) { } else if (arg == NFC_FW_DWL_LOW) { /* * Setting firmware download gpio to LOW for SN100U * FW download finished Loading @@ -654,6 +788,16 @@ int nfc_ioctl_power_states(struct file *filp, unsigned long arg) dev_err(&nqx_dev->client->dev, "firm_gpio is invalid\n"); } } else if (arg == NFC_ENABLE) { /* * Setting flag true when NFC is enabled */ nqx_dev->nfc_enabled = true; } else if (arg == NFC_DISABLE) { /* * Setting flag false when NFC is disabled */ nqx_dev->nfc_enabled = false; } else { r = -ENOIOCTLCMD; } Loading Loading @@ -897,9 +1041,8 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) } goto err_nfcc_reset_failed; } nqx_enable_irq(nqx_dev); ret = wait_event_interruptible_timeout(nqx_dev->read_wq, !nqx_dev->irq_enabled, msecs_to_jiffies(MAX_IRQ_WAIT_TIME)); ret = is_data_available_for_read(nqx_dev); if (ret <= 0) { nqx_disable_irq(nqx_dev); goto err_nfcc_hw_check; Loading @@ -915,9 +1058,8 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) goto reset_enable_gpio; goto err_nfcc_hw_check; } nqx_enable_irq(nqx_dev); ret = wait_event_interruptible_timeout(nqx_dev->read_wq, !nqx_dev->irq_enabled, msecs_to_jiffies(MAX_IRQ_WAIT_TIME)); ret = is_data_available_for_read(nqx_dev); if (ret <= 0) { nqx_disable_irq(nqx_dev); goto err_nfcc_hw_check; Loading Loading @@ -1280,6 +1422,7 @@ static int nqx_probe(struct i2c_client *client, /* init mutex and queues */ init_waitqueue_head(&nqx_dev->read_wq); init_waitqueue_head(&nqx_dev->cold_reset_read_wq); mutex_init(&nqx_dev->read_mutex); mutex_init(&nqx_dev->dev_ref_mutex); spin_lock_init(&nqx_dev->irq_enabled_lock); Loading Loading @@ -1362,6 +1505,8 @@ static int nqx_probe(struct i2c_client *client, device_set_wakeup_capable(&client->dev, true); i2c_set_clientdata(client, nqx_dev); nqx_dev->irq_wake_up = false; nqx_dev->cold_reset_rsp_pending = false; nqx_dev->nfc_enabled = false; dev_err(&client->dev, "%s: probing NFCC NQxxx exited successfully\n", Loading
drivers/nfc/nq-nci.h +53 −0 Original line number Diff line number Diff line Loading @@ -24,12 +24,65 @@ #define SET_EMULATOR_TEST_POINT _IOW(0xE9, 0x05, unsigned int) #define NFCC_INITIAL_CORE_RESET_NTF _IOW(0xE9, 0x10, unsigned int) #define DEV_COUNT 1 #define DEVICE_NAME "nq-nci" #define CLASS_NAME "nqx" #define MAX_BUFFER_SIZE (320) #define WAKEUP_SRC_TIMEOUT (2000) #define NCI_HEADER_LEN 3 #define NCI_PAYLOAD_IDX 3 #define MAX_RETRY_COUNT 3 #define NCI_RESET_CMD_LEN 4 #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 #define MAX_IRQ_WAIT_TIME (90) //in ms #define COLD_RESET_CMD_LEN 3 #define COLD_RESET_RSP_LEN 4 #define COLD_RESET_CMD_GID 0x2F #define COLD_RESET_CMD_PAYLOAD_LEN 0x00 #define COLD_RESET_RSP_GID 0x4F #define COLD_RESET_OID 0x1E #define NFC_RX_BUFFER_CNT_START (0x0) #define PAYLOAD_HEADER_LENGTH (0x3) #define PAYLOAD_LENGTH_MAX (256) #define BYTE (0x8) #define NCI_IDENTIFIER (0x10) enum ese_ioctl_request { /* eSE POWER ON */ ESE_POWER_ON = 0, /* eSE POWER OFF */ ESE_POWER_OFF, /* eSE COLD RESET */ ESE_COLD_RESET, /* eSE POWER STATE */ ESE_POWER_STATE }; enum nfcc_ioctl_request { /* NFC disable request with VEN LOW */ NFC_POWER_OFF = 0, /* NFC enable request with VEN Toggle */ NFC_POWER_ON, /* firmware download request with VEN Toggle */ NFC_FW_DWL_VEN_TOGGLE, /* ISO reset request */ NFC_ISO_RESET, /* request for firmware download gpio HIGH */ NFC_FW_DWL_HIGH, /* hard reset request */ NFC_HARD_RESET, /* request for firmware download gpio LOW */ NFC_FW_DWL_LOW, /* NFC enable without VEN gpio modification */ NFC_ENABLE, /* NFC disable without VEN gpio modification */ NFC_DISABLE }; enum nfcc_initial_core_reset_ntf { TIMEDOUT_INITIAL_CORE_RESET_NTF = 0, /* 0*/ ARRIVED_INITIAL_CORE_RESET_NTF, /* 1 */ Loading