Merge "NFC: Inform CLF whenever eSE is powered off"
This commit is contained in:
commit
d3fdecd206
2 changed files with 112 additions and 27 deletions
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -273,39 +303,95 @@ 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 (!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 {
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
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 already high\n");
|
||||
dev_dbg(&nqx_dev->client->dev, "ese_gpio is enabled\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)) {
|
||||
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 &&
|
||||
((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);
|
||||
|
@ -313,12 +399,7 @@ 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);
|
||||
}
|
||||
r = gpio_get_value(nqx_dev->ese_gpio);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
@ -624,6 +705,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__);
|
||||
|
|
|
@ -48,7 +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…
Add table
Reference in a new issue