Skip to content

Commit feb500c

Browse files
Sean Andersonjic23
authored andcommitted
iio: xilinx-ams: Unmask interrupts after updating alarms
To convert level-triggered alarms into edge-triggered IIO events, alarms are masked when they are triggered. To ensure we catch subsequent alarms, we then periodically poll to see if the alarm is still active. If it isn't, we unmask it. Active but masked alarms are stored in current_masked_alarm. If an active alarm is disabled, it will remain set in current_masked_alarm until ams_unmask_worker clears it. If the alarm is re-enabled before ams_unmask_worker runs, then it will never be cleared from current_masked_alarm. This will prevent the alarm event from being pushed even if the alarm is still active. Fix this by recalculating current_masked_alarm immediately when enabling or disabling alarms. Fixes: d5c7062 ("iio: adc: Add Xilinx AMS driver") Signed-off-by: Sean Anderson <sean.anderson@linux.dev> Reviewed-by: O'Griofa, Conall <conall.ogriofa@amd.com> Tested-by: Erim, Salih <Salih.Erim@amd.com> Acked-by: Erim, Salih <Salih.Erim@amd.com> Link: https://patch.msgid.link/20250715002847.2035228-1-sean.anderson@linux.dev Cc: <Stable@vger.kernel.org> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
1 parent 3c63ba1 commit feb500c

1 file changed

Lines changed: 25 additions & 20 deletions

File tree

drivers/iio/adc/xilinx-ams.c

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,29 @@ static void ams_update_pl_alarm(struct ams *ams, unsigned long alarm_mask)
389389
ams_pl_update_reg(ams, AMS_REG_CONFIG3, AMS_REGCFG3_ALARM_MASK, cfg);
390390
}
391391

392+
static void ams_unmask(struct ams *ams)
393+
{
394+
unsigned int status, unmask;
395+
396+
status = readl(ams->base + AMS_ISR_0);
397+
398+
/* Clear those bits which are not active anymore */
399+
unmask = (ams->current_masked_alarm ^ status) & ams->current_masked_alarm;
400+
401+
/* Clear status of disabled alarm */
402+
unmask |= ams->intr_mask;
403+
404+
ams->current_masked_alarm &= status;
405+
406+
/* Also clear those which are masked out anyway */
407+
ams->current_masked_alarm &= ~ams->intr_mask;
408+
409+
/* Clear the interrupts before we unmask them */
410+
writel(unmask, ams->base + AMS_ISR_0);
411+
412+
ams_update_intrmask(ams, ~AMS_ALARM_MASK, ~AMS_ALARM_MASK);
413+
}
414+
392415
static void ams_update_alarm(struct ams *ams, unsigned long alarm_mask)
393416
{
394417
unsigned long flags;
@@ -401,6 +424,7 @@ static void ams_update_alarm(struct ams *ams, unsigned long alarm_mask)
401424

402425
spin_lock_irqsave(&ams->intr_lock, flags);
403426
ams_update_intrmask(ams, AMS_ISR0_ALARM_MASK, ~alarm_mask);
427+
ams_unmask(ams);
404428
spin_unlock_irqrestore(&ams->intr_lock, flags);
405429
}
406430

@@ -1035,28 +1059,9 @@ static void ams_handle_events(struct iio_dev *indio_dev, unsigned long events)
10351059
static void ams_unmask_worker(struct work_struct *work)
10361060
{
10371061
struct ams *ams = container_of(work, struct ams, ams_unmask_work.work);
1038-
unsigned int status, unmask;
10391062

10401063
spin_lock_irq(&ams->intr_lock);
1041-
1042-
status = readl(ams->base + AMS_ISR_0);
1043-
1044-
/* Clear those bits which are not active anymore */
1045-
unmask = (ams->current_masked_alarm ^ status) & ams->current_masked_alarm;
1046-
1047-
/* Clear status of disabled alarm */
1048-
unmask |= ams->intr_mask;
1049-
1050-
ams->current_masked_alarm &= status;
1051-
1052-
/* Also clear those which are masked out anyway */
1053-
ams->current_masked_alarm &= ~ams->intr_mask;
1054-
1055-
/* Clear the interrupts before we unmask them */
1056-
writel(unmask, ams->base + AMS_ISR_0);
1057-
1058-
ams_update_intrmask(ams, ~AMS_ALARM_MASK, ~AMS_ALARM_MASK);
1059-
1064+
ams_unmask(ams);
10601065
spin_unlock_irq(&ams->intr_lock);
10611066

10621067
/* If still pending some alarm re-trigger the timer */

0 commit comments

Comments
 (0)