[PATCH 1/2] iio: adc: qcom-spmi-adc5-gen3: Share SDAM0 IRQ with ADC_TM auxiliary driver

From: Jishnu Prakash

Date: Fri May 15 2026 - 05:21:42 EST


The SDAM0 IRQ can be triggered for both EOC (end of conversion) events for
immediate ADC reads done in this driver and for threshold violation events,
based on ADC_TM thresholds configured from the auxiliary ADC_TM driver on
TM channels on the first SDAM.

At present, this interrupt is handled only in the ISR in the main ADC driver.
When the ISR is triggered for an ADC_TM event, this driver notifies the ADC_TM
driver by calling a notifier callback exposed from it for this purpose.

To simplify the interrupt handling in both drivers, share the interrupt between
the drivers. With this, ADC_TM interrupts on SDAM0 will be handled directly in
the ADC_TM driver, so remove the notifier callback and all TM interrupt
handling in the main ADC ISR.

Signed-off-by: Jishnu Prakash <jishnu.prakash@xxxxxxxxxxxxxxxx>
---
drivers/iio/adc/qcom-spmi-adc5-gen3.c | 52 +++++----------------------
include/linux/iio/adc/qcom-adc5-gen3-common.h | 2 --
2 files changed, 8 insertions(+), 46 deletions(-)

diff --git a/drivers/iio/adc/qcom-spmi-adc5-gen3.c b/drivers/iio/adc/qcom-spmi-adc5-gen3.c
index f8168a14b907..a819c3e627a0 100644
--- a/drivers/iio/adc/qcom-spmi-adc5-gen3.c
+++ b/drivers/iio/adc/qcom-spmi-adc5-gen3.c
@@ -56,9 +56,6 @@ struct adc5_channel_prop {
* requests from multiple clients.
* @data: software configuration data.
* @n_tm_channels: number of ADC channels used for TM measurements.
- * @handler: TM callback to be called for threshold violation interrupt
- * on first SDAM.
- * @tm_aux: pointer to auxiliary TM device.
*/
struct adc5_chip {
struct device *dev;
@@ -70,8 +67,6 @@ struct adc5_chip {
struct mutex lock;
const struct adc5_data *data;
unsigned int n_tm_channels;
- void (*handler)(struct auxiliary_device *tm_aux);
- struct auxiliary_device *tm_aux;
};

int adc5_gen3_read(struct adc5_device_data *adc, unsigned int sdam_index,
@@ -287,23 +282,21 @@ static irqreturn_t adc5_gen3_isr(int irq, void *dev_id)
{
struct adc5_chip *adc = dev_id;
struct device *dev = adc->dev;
- struct auxiliary_device *adev;
u8 status, eoc_status, val;
- u8 tm_status[2];
int ret;

ret = adc5_gen3_read(&adc->dev_data, ADC5_GEN3_VADC_SDAM,
ADC5_GEN3_STATUS1, &status, sizeof(status));
if (ret) {
dev_err(dev, "adc read status1 failed with %d\n", ret);
- return IRQ_HANDLED;
+ return IRQ_NONE;
}

ret = adc5_gen3_read(&adc->dev_data, ADC5_GEN3_VADC_SDAM,
ADC5_GEN3_EOC_STS, &eoc_status, sizeof(eoc_status));
if (ret) {
dev_err(dev, "adc read eoc status failed with %d\n", ret);
- return IRQ_HANDLED;
+ return IRQ_NONE;
}

if (status & ADC5_GEN3_STATUS1_CONV_FAULT) {
@@ -316,30 +309,13 @@ static irqreturn_t adc5_gen3_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}

- /* CHAN0 is the preconfigured channel for immediate conversion */
- if (eoc_status & ADC5_GEN3_EOC_CHAN_0)
- complete(&adc->complete);
-
- ret = adc5_gen3_read(&adc->dev_data, ADC5_GEN3_VADC_SDAM,
- ADC5_GEN3_TM_HIGH_STS, tm_status, sizeof(tm_status));
- if (ret) {
- dev_err(dev, "adc read TM status failed with %d\n", ret);
- return IRQ_HANDLED;
- }
-
- dev_dbg(dev, "Interrupt status:%#x, EOC status:%#x, high:%#x, low:%#x\n",
- status, eoc_status, tm_status[0], tm_status[1]);
-
- if (tm_status[0] || tm_status[1]) {
- adev = adc->tm_aux;
- if (!adev || !adev->dev.driver) {
- dev_err(dev, "adc_tm auxiliary device not initialized\n");
- return IRQ_HANDLED;
- }
+ dev_dbg(dev, "Interrupt status:%#x, EOC status:%#x\n", status, eoc_status);

- adc->handler(adev);
- }
+ /* CHAN0 is the preconfigured channel for immediate conversion */
+ if (!(eoc_status & ADC5_GEN3_EOC_CHAN_0))
+ return IRQ_NONE;

+ complete(&adc->complete);
return IRQ_HANDLED;
}

@@ -684,8 +660,6 @@ static int adc5_gen3_add_aux_tm_device(struct adc5_chip *adc)
if (ret)
return ret;

- adc->tm_aux = &aux_device->aux_dev;
-
return 0;
}

@@ -741,16 +715,6 @@ int adc5_gen3_therm_code_to_temp(struct device *dev,
}
EXPORT_SYMBOL_NS_GPL(adc5_gen3_therm_code_to_temp, "QCOM_SPMI_ADC5_GEN3");

-void adc5_gen3_register_tm_event_notifier(struct device *dev,
- void (*handler)(struct auxiliary_device *))
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev->parent);
- struct adc5_chip *adc = iio_priv(indio_dev);
-
- adc->handler = handler;
-}
-EXPORT_SYMBOL_NS_GPL(adc5_gen3_register_tm_event_notifier, "QCOM_SPMI_ADC5_GEN3");
-
static int adc5_gen3_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -818,7 +782,7 @@ static int adc5_gen3_probe(struct platform_device *pdev)
}

ret = devm_request_irq(dev, adc->dev_data.base[ADC5_GEN3_VADC_SDAM].irq,
- adc5_gen3_isr, 0,
+ adc5_gen3_isr, IRQF_ONESHOT | IRQF_SHARED,
adc->dev_data.base[ADC5_GEN3_VADC_SDAM].irq_name,
adc);
if (ret)
diff --git a/include/linux/iio/adc/qcom-adc5-gen3-common.h b/include/linux/iio/adc/qcom-adc5-gen3-common.h
index 6303eaa6640b..39cbfcbdb101 100644
--- a/include/linux/iio/adc/qcom-adc5-gen3-common.h
+++ b/include/linux/iio/adc/qcom-adc5-gen3-common.h
@@ -205,7 +205,5 @@ int adc5_gen3_get_scaled_reading(struct device *dev,
int adc5_gen3_therm_code_to_temp(struct device *dev,
struct adc5_channel_common_prop *common_props,
u16 code, int *val);
-void adc5_gen3_register_tm_event_notifier(struct device *dev,
- void (*handler)(struct auxiliary_device *));

#endif /* QCOM_ADC5_GEN3_COMMON_H */

--
2.43.0