Loading drivers/nfc/nq-nci.c +110 −25 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ MODULE_DEVICE_TABLE(of, msm_match_table); #define MAX_BUFFER_SIZE (320) #define WAKEUP_SRC_TIMEOUT (2000) #define MAX_RETRY_COUNT 3 struct nqx_dev { wait_queue_head_t read_wq; Loading Loading @@ -264,6 +265,35 @@ out: return ret; } /** * nqx_standby_write() * @buf: pointer to data buffer * @len: # of bytes need to transfer * * write data buffer over I2C and retry * if NFCC is in stand by mode * * Return: # of bytes written or -ve value in case of error */ static int nqx_standby_write(struct nqx_dev *nqx_dev, const unsigned char *buf, size_t len) { int ret = -EINVAL; int retry_cnt; for (retry_cnt = 1; retry_cnt <= MAX_RETRY_COUNT; retry_cnt++) { ret = i2c_master_send(nqx_dev->client, buf, len); if (ret < 0) { dev_err(&nqx_dev->client->dev, "%s: write failed, Maybe in Standby Mode - Retry(%d)\n", __func__, retry_cnt); usleep_range(1000, 1100); } else if (ret == len) break; } return ret; } /* Power management of the eSE NFC & eSE ON : NFC_EN high and eSE_pwr_req high. Loading @@ -273,38 +303,94 @@ out: static int nqx_ese_pwr(struct nqx_dev *nqx_dev, unsigned long int arg) { int r = -1; const unsigned char svdd_off_cmd_warn[] = {0x2F, 0x31, 0x01, 0x01}; const unsigned char svdd_off_cmd_done[] = {0x2F, 0x31, 0x01, 0x00}; if (!gpio_is_valid(nqx_dev->ese_gpio)) { dev_err(&nqx_dev->client->dev, "%s: ese_gpio is not valid\n", __func__); return -EINVAL; } /* Let's store the NFC_EN pin state*/ if (arg == 0) { /* We want to power on the eSE and to do so we need the * eSE_pwr_req pin and the NFC_EN pin to be high */ nqx_dev->nfc_ven_enabled = gpio_get_value(nqx_dev->en_gpio); if (gpio_get_value(nqx_dev->ese_gpio)) { dev_dbg(&nqx_dev->client->dev, "ese_gpio is already high\n"); r = 0; } else { /** * Let's store the NFC_EN pin state * only if the eSE is not yet on */ nqx_dev->nfc_ven_enabled = gpio_get_value(nqx_dev->en_gpio); if (!nqx_dev->nfc_ven_enabled) { gpio_set_value(nqx_dev->en_gpio, 1); /* hardware dependent delay */ usleep_range(1000, 1100); } if (gpio_is_valid(nqx_dev->ese_gpio)) { if (gpio_get_value(nqx_dev->ese_gpio)) { dev_dbg(&nqx_dev->client->dev, "ese_gpio is already high\n"); r = 0; } else { gpio_set_value(nqx_dev->ese_gpio, 1); if (gpio_get_value(nqx_dev->ese_gpio)) { dev_dbg(&nqx_dev->client->dev, "ese_gpio is enabled\n"); r = 0; } } } } else if (arg == 1) { if (gpio_is_valid(nqx_dev->ese_gpio)) { if (nqx_dev->nfc_ven_enabled && ((nqx_dev->nqx_info.info.chip_type == NFCC_NQ_220) || (nqx_dev->nqx_info.info.chip_type == NFCC_PN66T))) { /** * Let's inform the CLF we're * powering off the eSE */ r = nqx_standby_write(nqx_dev, svdd_off_cmd_warn, sizeof(svdd_off_cmd_warn)); if (r < 0) { dev_err(&nqx_dev->client->dev, "%s: write failed after max retry\n", __func__); return -ENXIO; } dev_dbg(&nqx_dev->client->dev, "%s: svdd_off_cmd_warn sent\n", __func__); /* let's power down the eSE */ gpio_set_value(nqx_dev->ese_gpio, 0); dev_dbg(&nqx_dev->client->dev, "%s: nqx_dev->ese_gpio set to 0\n", __func__); /** * Time needed for the SVDD capacitor * to get discharged */ usleep_range(8000, 8100); /* Let's inform the CLF the eSE is now off */ r = nqx_standby_write(nqx_dev, svdd_off_cmd_done, sizeof(svdd_off_cmd_done)); if (r < 0) { dev_err(&nqx_dev->client->dev, "%s: write failed after max retry\n", __func__); return -ENXIO; } dev_dbg(&nqx_dev->client->dev, "%s: svdd_off_cmd_done sent\n", __func__); } else { /** * In case the NFC is off, * there's no need to send the i2c commands */ gpio_set_value(nqx_dev->ese_gpio, 0); } if (!gpio_get_value(nqx_dev->ese_gpio)) { dev_dbg(&nqx_dev->client->dev, "ese_gpio is disabled\n"); r = 0; } } if (!nqx_dev->nfc_ven_enabled) { /* hardware dependent delay */ usleep_range(1000, 1100); Loading @@ -312,13 +398,8 @@ static int nqx_ese_pwr(struct nqx_dev *nqx_dev, unsigned long int arg) gpio_set_value(nqx_dev->en_gpio, 0); } } else if (arg == 3) { if (!nqx_dev->nfc_ven_enabled) r = 0; else { if (gpio_is_valid(nqx_dev->ese_gpio)) r = gpio_get_value(nqx_dev->ese_gpio); } } return r; } Loading Loading @@ -621,6 +702,10 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) dev_dbg(&client->dev, "%s: ## NFCC == NQ330 ##\n", __func__); break; case NFCC_PN66T: dev_dbg(&client->dev, "%s: ## NFCC == PN66T ##\n", __func__); break; default: dev_err(&client->dev, "%s: - NFCC HW not Supported\n", __func__); Loading drivers/nfc/nq-nci.h +1 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ enum nfcc_chip_variant { NFCC_NQ_220 = 0x58, /**< NFCC NQ220 */ NFCC_NQ_310 = 0x40, /**< NFCC NQ310 */ NFCC_NQ_330 = 0x51, /**< NFCC NQ330 */ NFCC_PN66T = 0x18, /**< NFCC PN66T */ NFCC_NOT_SUPPORTED = 0xFF /**< NFCC is not supported */ }; #endif Loading
drivers/nfc/nq-nci.c +110 −25 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ MODULE_DEVICE_TABLE(of, msm_match_table); #define MAX_BUFFER_SIZE (320) #define WAKEUP_SRC_TIMEOUT (2000) #define MAX_RETRY_COUNT 3 struct nqx_dev { wait_queue_head_t read_wq; Loading Loading @@ -264,6 +265,35 @@ out: return ret; } /** * nqx_standby_write() * @buf: pointer to data buffer * @len: # of bytes need to transfer * * write data buffer over I2C and retry * if NFCC is in stand by mode * * Return: # of bytes written or -ve value in case of error */ static int nqx_standby_write(struct nqx_dev *nqx_dev, const unsigned char *buf, size_t len) { int ret = -EINVAL; int retry_cnt; for (retry_cnt = 1; retry_cnt <= MAX_RETRY_COUNT; retry_cnt++) { ret = i2c_master_send(nqx_dev->client, buf, len); if (ret < 0) { dev_err(&nqx_dev->client->dev, "%s: write failed, Maybe in Standby Mode - Retry(%d)\n", __func__, retry_cnt); usleep_range(1000, 1100); } else if (ret == len) break; } return ret; } /* Power management of the eSE NFC & eSE ON : NFC_EN high and eSE_pwr_req high. Loading @@ -273,38 +303,94 @@ out: static int nqx_ese_pwr(struct nqx_dev *nqx_dev, unsigned long int arg) { int r = -1; const unsigned char svdd_off_cmd_warn[] = {0x2F, 0x31, 0x01, 0x01}; const unsigned char svdd_off_cmd_done[] = {0x2F, 0x31, 0x01, 0x00}; if (!gpio_is_valid(nqx_dev->ese_gpio)) { dev_err(&nqx_dev->client->dev, "%s: ese_gpio is not valid\n", __func__); return -EINVAL; } /* Let's store the NFC_EN pin state*/ if (arg == 0) { /* We want to power on the eSE and to do so we need the * eSE_pwr_req pin and the NFC_EN pin to be high */ nqx_dev->nfc_ven_enabled = gpio_get_value(nqx_dev->en_gpio); if (gpio_get_value(nqx_dev->ese_gpio)) { dev_dbg(&nqx_dev->client->dev, "ese_gpio is already high\n"); r = 0; } else { /** * Let's store the NFC_EN pin state * only if the eSE is not yet on */ nqx_dev->nfc_ven_enabled = gpio_get_value(nqx_dev->en_gpio); if (!nqx_dev->nfc_ven_enabled) { gpio_set_value(nqx_dev->en_gpio, 1); /* hardware dependent delay */ usleep_range(1000, 1100); } if (gpio_is_valid(nqx_dev->ese_gpio)) { if (gpio_get_value(nqx_dev->ese_gpio)) { dev_dbg(&nqx_dev->client->dev, "ese_gpio is already high\n"); r = 0; } else { gpio_set_value(nqx_dev->ese_gpio, 1); if (gpio_get_value(nqx_dev->ese_gpio)) { dev_dbg(&nqx_dev->client->dev, "ese_gpio is enabled\n"); r = 0; } } } } else if (arg == 1) { if (gpio_is_valid(nqx_dev->ese_gpio)) { if (nqx_dev->nfc_ven_enabled && ((nqx_dev->nqx_info.info.chip_type == NFCC_NQ_220) || (nqx_dev->nqx_info.info.chip_type == NFCC_PN66T))) { /** * Let's inform the CLF we're * powering off the eSE */ r = nqx_standby_write(nqx_dev, svdd_off_cmd_warn, sizeof(svdd_off_cmd_warn)); if (r < 0) { dev_err(&nqx_dev->client->dev, "%s: write failed after max retry\n", __func__); return -ENXIO; } dev_dbg(&nqx_dev->client->dev, "%s: svdd_off_cmd_warn sent\n", __func__); /* let's power down the eSE */ gpio_set_value(nqx_dev->ese_gpio, 0); dev_dbg(&nqx_dev->client->dev, "%s: nqx_dev->ese_gpio set to 0\n", __func__); /** * Time needed for the SVDD capacitor * to get discharged */ usleep_range(8000, 8100); /* Let's inform the CLF the eSE is now off */ r = nqx_standby_write(nqx_dev, svdd_off_cmd_done, sizeof(svdd_off_cmd_done)); if (r < 0) { dev_err(&nqx_dev->client->dev, "%s: write failed after max retry\n", __func__); return -ENXIO; } dev_dbg(&nqx_dev->client->dev, "%s: svdd_off_cmd_done sent\n", __func__); } else { /** * In case the NFC is off, * there's no need to send the i2c commands */ gpio_set_value(nqx_dev->ese_gpio, 0); } if (!gpio_get_value(nqx_dev->ese_gpio)) { dev_dbg(&nqx_dev->client->dev, "ese_gpio is disabled\n"); r = 0; } } if (!nqx_dev->nfc_ven_enabled) { /* hardware dependent delay */ usleep_range(1000, 1100); Loading @@ -312,13 +398,8 @@ static int nqx_ese_pwr(struct nqx_dev *nqx_dev, unsigned long int arg) gpio_set_value(nqx_dev->en_gpio, 0); } } else if (arg == 3) { if (!nqx_dev->nfc_ven_enabled) r = 0; else { if (gpio_is_valid(nqx_dev->ese_gpio)) r = gpio_get_value(nqx_dev->ese_gpio); } } return r; } Loading Loading @@ -621,6 +702,10 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) dev_dbg(&client->dev, "%s: ## NFCC == NQ330 ##\n", __func__); break; case NFCC_PN66T: dev_dbg(&client->dev, "%s: ## NFCC == PN66T ##\n", __func__); break; default: dev_err(&client->dev, "%s: - NFCC HW not Supported\n", __func__); Loading
drivers/nfc/nq-nci.h +1 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ enum nfcc_chip_variant { NFCC_NQ_220 = 0x58, /**< NFCC NQ220 */ NFCC_NQ_310 = 0x40, /**< NFCC NQ310 */ NFCC_NQ_330 = 0x51, /**< NFCC NQ330 */ NFCC_PN66T = 0x18, /**< NFCC PN66T */ NFCC_NOT_SUPPORTED = 0xFF /**< NFCC is not supported */ }; #endif