}
EXPORT_SYMBOL_NS_GPL(ad_sd_reset, "IIO_AD_SIGMA_DELTA");
+static bool ad_sd_disable_irq(struct ad_sigma_delta *sigma_delta)
+{
+ guard(spinlock_irqsave)(&sigma_delta->irq_lock);
+
+ /* It's already off, return false to indicate nothing was changed */
+ if (sigma_delta->irq_dis)
+ return false;
+
+ sigma_delta->irq_dis = true;
+ disable_irq_nosync(sigma_delta->irq_line);
+ return true;
+}
+
+static void ad_sd_enable_irq(struct ad_sigma_delta *sigma_delta)
+{
+ guard(spinlock_irqsave)(&sigma_delta->irq_lock);
+
+ sigma_delta->irq_dis = false;
+ enable_irq(sigma_delta->irq_line);
+}
+
int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta,
unsigned int mode, unsigned int channel)
{
if (ret < 0)
goto out;
- sigma_delta->irq_dis = false;
- enable_irq(sigma_delta->irq_line);
+ ad_sd_enable_irq(sigma_delta);
time_left = wait_for_completion_timeout(&sigma_delta->completion, 2 * HZ);
if (time_left == 0) {
- sigma_delta->irq_dis = true;
- disable_irq_nosync(sigma_delta->irq_line);
+ ad_sd_disable_irq(sigma_delta);
ret = -EIO;
} else {
ret = 0;
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_SINGLE);
- sigma_delta->irq_dis = false;
- enable_irq(sigma_delta->irq_line);
+ ad_sd_enable_irq(sigma_delta);
ret = wait_for_completion_interruptible_timeout(
&sigma_delta->completion, HZ);
&raw_sample);
out:
- if (!sigma_delta->irq_dis) {
- disable_irq_nosync(sigma_delta->irq_line);
- sigma_delta->irq_dis = true;
- }
+ ad_sd_disable_irq(sigma_delta);
sigma_delta->keep_cs_asserted = false;
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
if (ret)
goto err_unlock;
- sigma_delta->irq_dis = false;
- enable_irq(sigma_delta->irq_line);
+ ad_sd_enable_irq(sigma_delta);
return 0;
reinit_completion(&sigma_delta->completion);
wait_for_completion_timeout(&sigma_delta->completion, HZ);
- if (!sigma_delta->irq_dis) {
- disable_irq_nosync(sigma_delta->irq_line);
- sigma_delta->irq_dis = true;
- }
+ ad_sd_disable_irq(sigma_delta);
sigma_delta->keep_cs_asserted = false;
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
irq_handled:
iio_trigger_notify_done(indio_dev->trig);
- sigma_delta->irq_dis = false;
- enable_irq(sigma_delta->irq_line);
+ ad_sd_enable_irq(sigma_delta);
return IRQ_HANDLED;
}
* So read the MOSI line as GPIO (if available) and only trigger the irq
* if the line is active. Without such a GPIO assume this is a valid
* interrupt.
+ *
+ * Also as disable_irq_nosync() is used to disable the irq, only act if
+ * the irq wasn't disabled before.
*/
- if (!sigma_delta->rdy_gpiod || gpiod_get_value(sigma_delta->rdy_gpiod)) {
+ if ((!sigma_delta->rdy_gpiod || gpiod_get_value(sigma_delta->rdy_gpiod)) &&
+ ad_sd_disable_irq(sigma_delta)) {
complete(&sigma_delta->completion);
- disable_irq_nosync(irq);
- sigma_delta->irq_dis = true;
iio_trigger_poll(sigma_delta->trig);
return IRQ_HANDLED;
}
}
+ spin_lock_init(&sigma_delta->irq_lock);
+
if (info->irq_line)
sigma_delta->irq_line = info->irq_line;
else