From 23dbb3507882d984bc3f15a71155a64b104fb908 Mon Sep 17 00:00:00 2001 From: Anjelique Melendez Date: Wed, 9 Mar 2022 13:00:47 -0800 Subject: [PATCH] iio: adc: qcom-spmi-adc5-gen3: Fix __tm_handler_work() loop conditions Currently __tm_handler_work() assumes that each element in chan_props[] represents 1 SDAM register. However, chan_props[] has an element for every ADC and ADC TM channel. Since every ADC channel shares the same SDAM register the loop within __tm_handler_work() has incorrect conditions. Fix this. While at it, remove __tm_handler_work() which was invoked for every SDAM as tm_handler_work() goes through all channels. Change-Id: I5f3444ab831ff2067a1a53f49dea0c5dbbdc8758 Signed-off-by: Anjelique Melendez --- drivers/iio/adc/qcom-spmi-adc5-gen3.c | 115 ++++++++++++-------------- 1 file changed, 53 insertions(+), 62 deletions(-) diff --git a/drivers/iio/adc/qcom-spmi-adc5-gen3.c b/drivers/iio/adc/qcom-spmi-adc5-gen3.c index dc61e6342047..0d39f047e417 100644 --- a/drivers/iio/adc/qcom-spmi-adc5-gen3.c +++ b/drivers/iio/adc/qcom-spmi-adc5-gen3.c @@ -592,50 +592,15 @@ static irqreturn_t adc5_gen3_isr(int irq, void *dev_id) return IRQ_NONE; } -static void __tm_handler_work(struct adc5_chip *adc, unsigned int sdam_index) +static void tm_handler_work(struct work_struct *work) { struct adc5_channel_prop *chan_prop; u8 tm_status[2], buf[16], val; - int ret, i; + int ret, i, sdam_index = -1; + struct adc5_chip *adc = container_of(work, struct adc5_chip, + tm_handler_work); - mutex_lock(&adc->lock); - - ret = adc5_read(adc, sdam_index, ADC5_GEN3_TM_HIGH_STS, tm_status, 2); - if (ret < 0) { - pr_err("adc read TM status failed with %d\n", ret); - goto work_unlock; - } - - ret = adc5_write(adc, sdam_index, ADC5_GEN3_TM_HIGH_STS_CLR, tm_status, 2); - if (ret < 0) { - pr_err("adc write TM status failed with %d\n", ret); - goto work_unlock; - } - - /* To indicate conversion request is only to clear a status */ - val = 0; - ret = adc5_write(adc, sdam_index, ADC5_GEN3_PERPH_CH, &val, 1); - if (ret < 0) { - pr_err("adc write status clear conv_req failed with %d\n", ret); - goto work_unlock; - } - - val = ADC5_GEN3_CONV_REQ_REQ; - ret = adc5_write(adc, sdam_index, ADC5_GEN3_CONV_REQ, &val, 1); - if (ret < 0) { - pr_err("adc write conv_req failed with %d\n", ret); - goto work_unlock; - } - - ret = adc5_read(adc, sdam_index, ADC5_GEN3_CH0_DATA0, buf, sizeof(buf)); - if (ret < 0) { - pr_err("adc read data failed with %d\n", ret); - goto work_unlock; - } - - mutex_unlock(&adc->lock); - - for (i = sdam_index * 8; i < (sdam_index + 1) * 8; i++) { + for (i = 0; i < adc->nchannels; i++) { bool upper_set = false, lower_set = false; u8 data_low = 0, data_high = 0; u16 code = 0; @@ -643,10 +608,47 @@ static void __tm_handler_work(struct adc5_chip *adc, unsigned int sdam_index) chan_prop = &adc->chan_props[i]; offset = chan_prop->tm_chan_index; - if (!chan_prop->adc_tm) + + if (chan_prop->adc_tm != ADC_TM && chan_prop->adc_tm != ADC_TM_NON_THERMAL) continue; mutex_lock(&adc->lock); + if (chan_prop->sdam_index != sdam_index) { + sdam_index = chan_prop->sdam_index; + ret = adc5_read(adc, sdam_index, ADC5_GEN3_TM_HIGH_STS, tm_status, 2); + if (ret < 0) { + pr_err("adc read TM status failed with %d\n", ret); + goto work_unlock; + } + + ret = adc5_write(adc, sdam_index, ADC5_GEN3_TM_HIGH_STS_CLR, tm_status, 2); + if (ret < 0) { + pr_err("adc write TM status failed with %d\n", ret); + goto work_unlock; + } + + /* To indicate conversion request is only to clear a status */ + val = 0; + ret = adc5_write(adc, sdam_index, ADC5_GEN3_PERPH_CH, &val, 1); + if (ret < 0) { + pr_err("adc write status clear conv_req failed with %d\n", ret); + goto work_unlock; + } + + val = ADC5_GEN3_CONV_REQ_REQ; + ret = adc5_write(adc, sdam_index, ADC5_GEN3_CONV_REQ, &val, 1); + if (ret < 0) { + pr_err("adc write conv_req failed with %d\n", ret); + goto work_unlock; + } + + ret = adc5_read(adc, sdam_index, ADC5_GEN3_CH0_DATA0, buf, sizeof(buf)); + if (ret < 0) { + pr_err("adc read data failed with %d\n", ret); + goto work_unlock; + } + } + if ((tm_status[0] & BIT(offset)) && (chan_prop->high_thr_en)) upper_set = true; @@ -703,16 +705,6 @@ static void __tm_handler_work(struct adc5_chip *adc, unsigned int sdam_index) mutex_unlock(&adc->lock); } -static void tm_handler_work(struct work_struct *work) -{ - int i; - struct adc5_chip *adc = container_of(work, struct adc5_chip, - tm_handler_work); - - for (i = 0; i < adc->num_sdams; i++) - __tm_handler_work(adc, i); -} - static int adc5_gen3_of_xlate(struct iio_dev *indio_dev, const struct of_phandle_args *iiospec) { @@ -1575,7 +1567,7 @@ static int adc5_get_dt_data(struct adc5_chip *adc, struct device_node *node) { const struct adc5_channels *adc_chan; struct iio_chan_spec *iio_chan; - struct adc5_channel_prop prop, *chan_props; + struct adc5_channel_prop *chan_props; struct device_node *child; unsigned int index = 0; const struct of_device_id *id; @@ -1607,21 +1599,20 @@ static int adc5_get_dt_data(struct adc5_chip *adc, struct device_node *node) adc->data = data; for_each_available_child_of_node(node, child) { - ret = adc5_get_dt_channel_data(adc, &prop, child, data); + ret = adc5_get_dt_channel_data(adc, chan_props, child, data); if (ret < 0) { of_node_put(child); return ret; } - prop.chip = adc; - if (prop.scale_fn_type == -EINVAL) - prop.scale_fn_type = - data->adc_chans[prop.channel].scale_fn_type; - *chan_props = prop; - adc_chan = &data->adc_chans[prop.channel]; - iio_chan->channel = prop.channel; - iio_chan->datasheet_name = prop.datasheet_name; - iio_chan->extend_name = prop.datasheet_name; + chan_props->chip = adc; + if (chan_props->scale_fn_type == -EINVAL) + chan_props->scale_fn_type = + data->adc_chans[chan_props->channel].scale_fn_type; + adc_chan = &data->adc_chans[chan_props->channel]; + iio_chan->channel = chan_props->channel; + iio_chan->datasheet_name = chan_props->datasheet_name; + iio_chan->extend_name = chan_props->datasheet_name; iio_chan->info_mask_separate = adc_chan->info_mask; iio_chan->type = adc_chan->type; iio_chan->address = index;