iio: rradc: Update reading BATT_ID channel
There is a need for RRADC driver to return fresh results of the BATT_ID channel which could take upto 1.5 seconds in round robin mode. Switch the RRADC driver to continuous mode when client requests the BATT_ID channel to obtain the results faster. In addition explicity force the batt_id to ensure it forces a conversion on the new read. The existing USBIN_V channel also requires having the RRADC in continuous mode therefore have a common support for clients that uses continuous mode. Change-Id: I5b89ed9f0015bc6db3adce22e3ac6d0d0283e2bf Signed-off-by: Siddartha Mohanadoss <smohanad@codeaurora.org>
This commit is contained in:
parent
368fecd7df
commit
d3cb6fa63a
1 changed files with 162 additions and 74 deletions
|
@ -28,9 +28,8 @@
|
||||||
#define FG_ADC_RR_SKIN_TEMP_MSB 0x51
|
#define FG_ADC_RR_SKIN_TEMP_MSB 0x51
|
||||||
#define FG_ADC_RR_RR_ADC_CTL 0x52
|
#define FG_ADC_RR_RR_ADC_CTL 0x52
|
||||||
#define FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL_MASK 0x8
|
#define FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL_MASK 0x8
|
||||||
#define FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL BIT(3)
|
#define FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL BIT(3)
|
||||||
#define FG_ADC_RR_ADC_LOG 0x53
|
#define FG_ADC_RR_ADC_LOG 0x53
|
||||||
#define FG_ADC_RR_ADC_LOG_CLR_CTRL_MASK 0xFE
|
|
||||||
#define FG_ADC_RR_ADC_LOG_CLR_CTRL BIT(0)
|
#define FG_ADC_RR_ADC_LOG_CLR_CTRL BIT(0)
|
||||||
|
|
||||||
#define FG_ADC_RR_FAKE_BATT_LOW_LSB 0x58
|
#define FG_ADC_RR_FAKE_BATT_LOW_LSB 0x58
|
||||||
|
@ -40,6 +39,7 @@
|
||||||
|
|
||||||
#define FG_ADC_RR_BATT_ID_CTRL 0x60
|
#define FG_ADC_RR_BATT_ID_CTRL 0x60
|
||||||
#define FG_ADC_RR_BATT_ID_TRIGGER 0x61
|
#define FG_ADC_RR_BATT_ID_TRIGGER 0x61
|
||||||
|
#define FG_ADC_RR_BATT_ID_TRIGGER_CTL BIT(0)
|
||||||
#define FG_ADC_RR_BATT_ID_STS 0x62
|
#define FG_ADC_RR_BATT_ID_STS 0x62
|
||||||
#define FG_ADC_RR_BATT_ID_CFG 0x63
|
#define FG_ADC_RR_BATT_ID_CFG 0x63
|
||||||
#define FG_ADC_RR_BATT_ID_5_LSB 0x66
|
#define FG_ADC_RR_BATT_ID_5_LSB 0x66
|
||||||
|
@ -182,9 +182,11 @@
|
||||||
#define FG_RR_ADC_COHERENT_CHECK_RETRY 5
|
#define FG_RR_ADC_COHERENT_CHECK_RETRY 5
|
||||||
#define FG_RR_ADC_MAX_CONTINUOUS_BUFFER_LEN 16
|
#define FG_RR_ADC_MAX_CONTINUOUS_BUFFER_LEN 16
|
||||||
#define FG_RR_ADC_STS_CHANNEL_READING_MASK 0x3
|
#define FG_RR_ADC_STS_CHANNEL_READING_MASK 0x3
|
||||||
|
#define FG_RR_ADC_STS_CHANNEL_STS 0x2
|
||||||
|
|
||||||
#define FG_RR_CONV_CONTINUOUS_TIME_MIN 80000
|
#define FG_RR_CONV_CONTINUOUS_TIME_MIN_US 50000
|
||||||
#define FG_RR_CONV_CONTINUOUS_TIME_MAX 81000
|
#define FG_RR_CONV_CONTINUOUS_TIME_MAX_US 51000
|
||||||
|
#define FG_RR_CONV_MAX_RETRY_CNT 50
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The channel number is not a physical index in hardware,
|
* The channel number is not a physical index in hardware,
|
||||||
|
@ -570,40 +572,157 @@ static const struct rradc_channels rradc_chans[] = {
|
||||||
FG_ADC_RR_AUX_THERM_STS)
|
FG_ADC_RR_AUX_THERM_STS)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int rradc_enable_continuous_mode(struct rradc_chip *chip)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
/* Clear channel log */
|
||||||
|
rc = rradc_masked_write(chip, FG_ADC_RR_ADC_LOG,
|
||||||
|
FG_ADC_RR_ADC_LOG_CLR_CTRL,
|
||||||
|
FG_ADC_RR_ADC_LOG_CLR_CTRL);
|
||||||
|
if (rc < 0) {
|
||||||
|
pr_err("log ctrl update to clear failed:%d\n", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = rradc_masked_write(chip, FG_ADC_RR_ADC_LOG,
|
||||||
|
FG_ADC_RR_ADC_LOG_CLR_CTRL, 0);
|
||||||
|
if (rc < 0) {
|
||||||
|
pr_err("log ctrl update to not clear failed:%d\n", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Switch to continuous mode */
|
||||||
|
rc = rradc_masked_write(chip, FG_ADC_RR_RR_ADC_CTL,
|
||||||
|
FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL_MASK,
|
||||||
|
FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL);
|
||||||
|
if (rc < 0) {
|
||||||
|
pr_err("Update to continuous mode failed:%d\n", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rradc_disable_continuous_mode(struct rradc_chip *chip)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
/* Switch to non continuous mode */
|
||||||
|
rc = rradc_masked_write(chip, FG_ADC_RR_RR_ADC_CTL,
|
||||||
|
FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL_MASK, 0);
|
||||||
|
if (rc < 0) {
|
||||||
|
pr_err("Update to non-continuous mode failed:%d\n", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rradc_check_status_ready_with_retry(struct rradc_chip *chip,
|
||||||
|
struct rradc_chan_prop *prop, u8 *buf, u16 status)
|
||||||
|
{
|
||||||
|
int rc = 0, retry_cnt = 0, mask = 0;
|
||||||
|
|
||||||
|
switch (prop->channel) {
|
||||||
|
case RR_ADC_BATT_ID:
|
||||||
|
/* BATT_ID STS bit does not get set initially */
|
||||||
|
mask = FG_RR_ADC_STS_CHANNEL_STS;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mask = FG_RR_ADC_STS_CHANNEL_READING_MASK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (((buf[0] & mask) != mask) &&
|
||||||
|
(retry_cnt < FG_RR_CONV_MAX_RETRY_CNT)) {
|
||||||
|
pr_debug("%s is not ready; nothing to read:0x%x\n",
|
||||||
|
rradc_chans[prop->channel].datasheet_name, buf[0]);
|
||||||
|
usleep_range(FG_RR_CONV_CONTINUOUS_TIME_MIN_US,
|
||||||
|
FG_RR_CONV_CONTINUOUS_TIME_MAX_US);
|
||||||
|
retry_cnt++;
|
||||||
|
rc = rradc_read(chip, status, buf, 1);
|
||||||
|
if (rc < 0) {
|
||||||
|
pr_err("status read failed:%d\n", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retry_cnt >= FG_RR_CONV_MAX_RETRY_CNT)
|
||||||
|
rc = -ENODATA;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rradc_read_channel_with_continuous_mode(struct rradc_chip *chip,
|
||||||
|
struct rradc_chan_prop *prop, u8 *buf)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
u16 status = 0;
|
||||||
|
|
||||||
|
rc = rradc_enable_continuous_mode(chip);
|
||||||
|
if (rc < 0) {
|
||||||
|
pr_err("Failed to switch to continuous mode\n");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = rradc_chans[prop->channel].sts;
|
||||||
|
rc = rradc_read(chip, status, buf, 1);
|
||||||
|
if (rc < 0) {
|
||||||
|
pr_err("status read failed:%d\n", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = rradc_check_status_ready_with_retry(chip, prop,
|
||||||
|
buf, status);
|
||||||
|
if (rc < 0) {
|
||||||
|
pr_err("Status read failed:%d\n", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = rradc_disable_continuous_mode(chip);
|
||||||
|
if (rc < 0) {
|
||||||
|
pr_err("Failed to switch to non continuous mode\n");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static int rradc_do_conversion(struct rradc_chip *chip,
|
static int rradc_do_conversion(struct rradc_chip *chip,
|
||||||
struct rradc_chan_prop *prop, u16 *data)
|
struct rradc_chan_prop *prop, u16 *data)
|
||||||
{
|
{
|
||||||
int rc = 0, bytes_to_read = 0, retry = 0;
|
int rc = 0, bytes_to_read = 0;
|
||||||
u8 buf[6];
|
u8 buf[6];
|
||||||
u16 offset = 0, batt_id_5 = 0, batt_id_15 = 0, batt_id_150 = 0;
|
u16 offset = 0, batt_id_5 = 0, batt_id_15 = 0, batt_id_150 = 0;
|
||||||
u16 status = 0;
|
u16 status = 0;
|
||||||
|
|
||||||
mutex_lock(&chip->lock);
|
mutex_lock(&chip->lock);
|
||||||
|
|
||||||
if ((prop->channel != RR_ADC_BATT_ID) &&
|
switch (prop->channel) {
|
||||||
(prop->channel != RR_ADC_CHG_HOT_TEMP) &&
|
case RR_ADC_BATT_ID:
|
||||||
(prop->channel != RR_ADC_CHG_TOO_HOT_TEMP) &&
|
rc = rradc_masked_write(chip, FG_ADC_RR_BATT_ID_TRIGGER,
|
||||||
(prop->channel != RR_ADC_SKIN_HOT_TEMP) &&
|
FG_ADC_RR_BATT_ID_TRIGGER_CTL,
|
||||||
(prop->channel != RR_ADC_SKIN_TOO_HOT_TEMP) &&
|
FG_ADC_RR_BATT_ID_TRIGGER_CTL);
|
||||||
(prop->channel != RR_ADC_USBIN_V)) {
|
|
||||||
/* BATT_ID STS bit does not get set initially */
|
|
||||||
status = rradc_chans[prop->channel].sts;
|
|
||||||
rc = rradc_read(chip, status, buf, 1);
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
pr_err("status read failed:%d\n", rc);
|
pr_err("BATT_ID trigger set failed:%d\n", rc);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf[0] &= FG_RR_ADC_STS_CHANNEL_READING_MASK;
|
rc = rradc_read_channel_with_continuous_mode(chip, prop, buf);
|
||||||
if (buf[0] != FG_RR_ADC_STS_CHANNEL_READING_MASK) {
|
if (rc < 0) {
|
||||||
pr_debug("%s is not ready; nothing to read\n",
|
pr_err("Error reading in continuous mode:%d\n", rc);
|
||||||
rradc_chans[prop->channel].datasheet_name);
|
|
||||||
rc = -ENODATA;
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (prop->channel == RR_ADC_USBIN_V) {
|
rc = rradc_masked_write(chip, FG_ADC_RR_BATT_ID_TRIGGER,
|
||||||
|
FG_ADC_RR_BATT_ID_TRIGGER_CTL, 0);
|
||||||
|
if (rc < 0) {
|
||||||
|
pr_err("BATT_ID trigger re-set failed:%d\n", rc);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RR_ADC_USBIN_V:
|
||||||
/* Force conversion every cycle */
|
/* Force conversion every cycle */
|
||||||
rc = rradc_masked_write(chip, FG_ADC_RR_USB_IN_V_TRIGGER,
|
rc = rradc_masked_write(chip, FG_ADC_RR_USB_IN_V_TRIGGER,
|
||||||
FG_ADC_RR_USB_IN_V_EVERY_CYCLE_MASK,
|
FG_ADC_RR_USB_IN_V_EVERY_CYCLE_MASK,
|
||||||
|
@ -613,58 +732,9 @@ static int rradc_do_conversion(struct rradc_chip *chip,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear channel log */
|
rc = rradc_read_channel_with_continuous_mode(chip, prop, buf);
|
||||||
rc = rradc_masked_write(chip, FG_ADC_RR_ADC_LOG,
|
|
||||||
FG_ADC_RR_ADC_LOG_CLR_CTRL_MASK,
|
|
||||||
FG_ADC_RR_ADC_LOG_CLR_CTRL);
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
pr_err("log ctrl update to clear failed:%d\n", rc);
|
pr_err("Error reading in continuous mode:%d\n", rc);
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = rradc_masked_write(chip, FG_ADC_RR_ADC_LOG,
|
|
||||||
FG_ADC_RR_ADC_LOG_CLR_CTRL_MASK, 0);
|
|
||||||
if (rc < 0) {
|
|
||||||
pr_err("log ctrl update to not clear failed:%d\n", rc);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Switch to continuous mode */
|
|
||||||
rc = rradc_masked_write(chip, FG_ADC_RR_RR_ADC_CTL,
|
|
||||||
FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL_MASK,
|
|
||||||
FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL);
|
|
||||||
if (rc < 0) {
|
|
||||||
pr_err("Update to continuous mode failed:%d\n", rc);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = rradc_chans[prop->channel].sts;
|
|
||||||
rc = rradc_read(chip, status, buf, 1);
|
|
||||||
if (rc < 0) {
|
|
||||||
pr_err("status read failed:%d\n", rc);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf[0] &= FG_RR_ADC_STS_CHANNEL_READING_MASK;
|
|
||||||
while ((buf[0] != FG_RR_ADC_STS_CHANNEL_READING_MASK) &&
|
|
||||||
(retry < 2)) {
|
|
||||||
pr_debug("%s is not ready; nothing to read\n",
|
|
||||||
rradc_chans[prop->channel].datasheet_name);
|
|
||||||
usleep_range(FG_RR_CONV_CONTINUOUS_TIME_MIN,
|
|
||||||
FG_RR_CONV_CONTINUOUS_TIME_MAX);
|
|
||||||
retry++;
|
|
||||||
rc = rradc_read(chip, status, buf, 1);
|
|
||||||
if (rc < 0) {
|
|
||||||
pr_err("status read failed:%d\n", rc);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Switch to non continuous mode */
|
|
||||||
rc = rradc_masked_write(chip, FG_ADC_RR_RR_ADC_CTL,
|
|
||||||
FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL_MASK, 0);
|
|
||||||
if (rc < 0) {
|
|
||||||
pr_err("Update to continuous mode failed:%d\n", rc);
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -675,11 +745,29 @@ static int rradc_do_conversion(struct rradc_chip *chip,
|
||||||
pr_err("Restore every cycle update failed:%d\n", rc);
|
pr_err("Restore every cycle update failed:%d\n", rc);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case RR_ADC_CHG_HOT_TEMP:
|
||||||
|
case RR_ADC_CHG_TOO_HOT_TEMP:
|
||||||
|
case RR_ADC_SKIN_HOT_TEMP:
|
||||||
|
case RR_ADC_SKIN_TOO_HOT_TEMP:
|
||||||
|
pr_debug("Read only the data registers\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
status = rradc_chans[prop->channel].sts;
|
||||||
|
rc = rradc_read(chip, status, buf, 1);
|
||||||
|
if (rc < 0) {
|
||||||
|
pr_err("status read failed:%d\n", rc);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
if (retry >= 2) {
|
rc = rradc_check_status_ready_with_retry(chip, prop,
|
||||||
|
buf, status);
|
||||||
|
if (rc < 0) {
|
||||||
|
pr_debug("Status read failed:%d\n", rc);
|
||||||
rc = -ENODATA;
|
rc = -ENODATA;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = rradc_chans[prop->channel].lsb;
|
offset = rradc_chans[prop->channel].lsb;
|
||||||
|
|
Loading…
Add table
Reference in a new issue