iio: qcom-spmi-adc5: Update ADC5 Gen3 conversion request logic

1.Remove mutexes used in TM configure API to avoid deadlock.

2.Update register writes in immediate and TM configure APIs.

3.Correct register and bit to check for end of conversion for immediate
conversion in IRQ handler.

Change-Id: I68d0bc4d6aeef089939d0d9ae9161b6122bf110e
Signed-off-by: Jishnu Prakash <jprakash@codeaurora.org>
This commit is contained in:
Jishnu Prakash 2021-05-25 14:41:14 +05:30 committed by David Collins
parent f8f8647cb8
commit 50f3f5d30d

View File

@ -33,7 +33,7 @@ static LIST_HEAD(adc_tm_device_list);
#define ADC5_GEN3_STATUS1 0x46
#define ADC5_GEN3_STATUS1_CONV_FAULT BIT(7)
#define ADC5_GEN3_STATUS1_THR_CROSS BIT(6)
#define ADC5_GEN3_STATUS1_EOC BIT(1)
#define ADC5_GEN3_STATUS1_EOC BIT(0)
#define ADC5_GEN3_TM_EN_STS 0x47
@ -42,6 +42,7 @@ static LIST_HEAD(adc_tm_device_list);
#define ADC5_GEN3_TM_LOW_STS 0x49
#define ADC5_GEN3_EOC_STS 0x4a
#define ADC5_GEN3_EOC_CHAN_0 BIT(0)
#define ADC5_GEN3_EOC_CLR 0x4b
@ -373,8 +374,11 @@ static int adc5_gen3_configure(struct adc5_chip *adc,
buf[0] &= (u8) ~ADC5_GEN3_SID_MASK;
buf[0] &= prop->sid;
/* Use channel 0 by default for immediate conversion */
buf[1] = 0;
/*
* Use channel 0 by default for immediate conversion and
* to indicate there is an actual conversion request
*/
buf[1] = ADC5_GEN3_CHAN_CONV_REQ | 0;
buf[2] = prop->timer;
@ -383,13 +387,10 @@ static int adc5_gen3_configure(struct adc5_chip *adc,
/* Update fast average sample value */
buf[4] &= (u8) ~ADC5_GEN3_FAST_AVG_CTL_SAMPLES_MASK;
buf[4] |= prop->avg_samples;
buf[4] |= prop->avg_samples | ADC5_GEN3_FAST_AVG_CTL_EN;
/*
* Select ADC channel and indicate there is an actual
* conversion request
*/
buf[5] = ADC5_GEN3_CHAN_CONV_REQ | prop->channel;
/* Select ADC channel */
buf[5] = prop->channel;
/* Select HW settle delay for channel */
buf[6] &= (u8) ~ADC5_GEN3_HW_SETTLE_DELAY_MASK;
@ -482,7 +483,7 @@ static int adc5_gen3_do_conversion(struct adc5_chip *adc,
goto unlock;
/* To indicate conversion request is only to clear a status */
val = ~ADC5_GEN3_CHAN_CONV_REQ | prop->channel;
val = 0;
ret = adc5_write(adc, ADC5_GEN3_PERPH_CH, &val, 1);
if (ret < 0)
goto unlock;
@ -530,16 +531,17 @@ static void adc5_gen3_dump_regs_debug(struct adc5_chip *adc)
static irqreturn_t adc5_gen3_isr(int irq, void *dev_id)
{
struct adc5_chip *adc = dev_id;
u8 status, tm_status[2];
u8 status, tm_status[2], eoc_status;
int ret;
ret = adc5_read(adc, ADC5_GEN3_STATUS1, &status, 1);
ret = adc5_read(adc, ADC5_GEN3_EOC_STS, &eoc_status, 1);
if (ret < 0) {
pr_err("adc read status failed with %d\n", ret);
pr_err("adc read eoc status failed with %d\n", ret);
goto handler_end;
}
if (status & ADC5_GEN3_STATUS1_EOC)
/* CHAN0 is the preconfigured channel for immediate conversion */
if (eoc_status & ADC5_GEN3_EOC_CHAN_0)
complete(&adc->complete);
ret = adc5_read(adc, ADC5_GEN3_TM_HIGH_STS, tm_status, 2);
@ -551,8 +553,14 @@ static irqreturn_t adc5_gen3_isr(int irq, void *dev_id)
if (tm_status[0] || tm_status[1])
schedule_work(&adc->tm_handler_work);
pr_debug("Interrupt status:%#x, high:%#x, low:%#x\n",
status, tm_status[0], tm_status[1]);
ret = adc5_read(adc, ADC5_GEN3_STATUS1, &status, 1);
if (ret < 0) {
pr_err("adc read status1 failed with %d\n", ret);
goto handler_end;
}
pr_debug("Interrupt status:%#x, EOC status:%#x, high:%#x, low:%#x\n",
status, eoc_status, tm_status[0], tm_status[1]);
if (status & ADC5_GEN3_STATUS1_CONV_FAULT) {
pr_err("Unexpected conversion fault\n");
@ -586,7 +594,7 @@ static void tm_handler_work(struct work_struct *work)
}
/* To indicate conversion request is only to clear a status */
val = (u8) ~ADC5_GEN3_CHAN_CONV_REQ;
val = 0;
ret = adc5_write(adc, ADC5_GEN3_PERPH_CH, &val, 1);
val = ADC5_GEN3_CONV_REQ_REQ;
@ -774,20 +782,23 @@ static int adc_tm5_gen3_configure(struct adc5_channel_prop *prop)
u32 mask = 0;
struct adc5_chip *adc = prop->chip;
mutex_lock(&adc->lock);
ret = adc5_gen3_poll_wait_hs(adc);
if (ret < 0)
goto tm_config_unlock;
return ret;
ret = adc5_read(adc, ADC5_GEN3_SID, buf, sizeof(buf));
if (ret < 0)
goto tm_config_unlock;
return ret;
/* Write SID */
buf[0] &= (u8) ~ADC5_GEN3_SID_MASK;
buf[0] &= prop->sid;
buf[1] = prop->tm_chan_index;
/*
* Select TM channel and indicate there is an actual
* conversion request
*/
buf[1] = ADC5_GEN3_CHAN_CONV_REQ | prop->tm_chan_index;
buf[2] = prop->timer;
@ -796,13 +807,10 @@ static int adc_tm5_gen3_configure(struct adc5_channel_prop *prop)
/* Update fast average sample value */
buf[4] &= (u8) ~ADC5_GEN3_FAST_AVG_CTL_SAMPLES_MASK;
buf[4] |= prop->avg_samples;
buf[4] |= prop->avg_samples | ADC5_GEN3_FAST_AVG_CTL_EN;
/*
* Select ADC channel and indicate there is an actual
* conversion request
*/
buf[5] = ADC5_GEN3_CHAN_CONV_REQ | prop->channel;
/* Select ADC channel */
buf[5] = prop->channel;
/* Select HW settle delay for channel */
buf[6] &= (u8) ~ADC5_GEN3_HW_SETTLE_DELAY_MASK;
@ -820,15 +828,10 @@ static int adc_tm5_gen3_configure(struct adc5_channel_prop *prop)
ret = adc5_write(adc, ADC5_GEN3_SID, buf, sizeof(buf));
if (ret < 0)
goto tm_config_unlock;
return ret;
conv_req = ADC5_GEN3_CONV_REQ_REQ;
ret = adc5_write(adc, ADC5_GEN3_CONV_REQ, &conv_req, 1);
tm_config_unlock:
mutex_unlock(&adc->lock);
return ret;
return adc5_write(adc, ADC5_GEN3_CONV_REQ, &conv_req, 1);
}
static int adc_tm5_gen3_set_trip_temp(void *data,