Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 695e2f5

Browse files
Olivier Moysanjic23
authored andcommitted
iio: adc: stm32-adc: fix a regression when using dma and irq
Since overrun interrupt support has been added, there's a regression when two ADCs are used at the same time, with: - an ADC configured to use IRQs. EOCIE bit is set. The handler is normally called in this case. - an ADC configured to use DMA. EOCIE bit isn't set. EOC triggers the DMA request. It's then automatically cleared by DMA read. But the handler gets called due to status bit is temporarily set (IRQ triggered by the other ADC). This is a regression as similar issue had been fixed earlier by commit dcb1092 ("iio: adc: stm32-adc: fix a race when using several adcs with dma and irq"). Issue is that stm32_adc_eoc_enabled() returns non-zero value (always) since OVR bit has been added and enabled for both DMA and IRQ case. Remove OVR mask in IER register, and rely only on CSR status for overrun. To avoid subsequent calls to interrupt routine on overrun, CSR OVR bit has to be cleared. CSR OVR bit cannot be cleared directly by software. To do this ADC must be stopped first, and OVR bit in ADC ISR has to be cleared. Also add a check in ADC IRQ handler to report spurious IRQs. Fixes: cc06e67 ("iio: adc: stm32-adc: Add check on overrun interrupt") Signed-off-by: Olivier Moysan <[email protected]> Signed-off-by: Fabrice Gasnier <[email protected]> Cc: <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jonathan Cameron <[email protected]>
1 parent 15207a9 commit 695e2f5

File tree

2 files changed

+65
-26
lines changed

2 files changed

+65
-26
lines changed

drivers/iio/adc/stm32-adc-core.c

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,16 @@
4141
* struct stm32_adc_common_regs - stm32 common registers
4242
* @csr: common status register offset
4343
* @ccr: common control register offset
44-
* @eoc1_msk: adc1 end of conversion flag in @csr
45-
* @eoc2_msk: adc2 end of conversion flag in @csr
46-
* @eoc3_msk: adc3 end of conversion flag in @csr
44+
* @eoc_msk: array of eoc (end of conversion flag) masks in csr for adc1..n
45+
* @ovr_msk: array of ovr (overrun flag) masks in csr for adc1..n
4746
* @ier: interrupt enable register offset for each adc
4847
* @eocie_msk: end of conversion interrupt enable mask in @ier
4948
*/
5049
struct stm32_adc_common_regs {
5150
u32 csr;
5251
u32 ccr;
53-
u32 eoc1_msk;
54-
u32 eoc2_msk;
55-
u32 eoc3_msk;
52+
u32 eoc_msk[STM32_ADC_MAX_ADCS];
53+
u32 ovr_msk[STM32_ADC_MAX_ADCS];
5654
u32 ier;
5755
u32 eocie_msk;
5856
};
@@ -282,21 +280,20 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev,
282280
static const struct stm32_adc_common_regs stm32f4_adc_common_regs = {
283281
.csr = STM32F4_ADC_CSR,
284282
.ccr = STM32F4_ADC_CCR,
285-
.eoc1_msk = STM32F4_EOC1 | STM32F4_OVR1,
286-
.eoc2_msk = STM32F4_EOC2 | STM32F4_OVR2,
287-
.eoc3_msk = STM32F4_EOC3 | STM32F4_OVR3,
283+
.eoc_msk = { STM32F4_EOC1, STM32F4_EOC2, STM32F4_EOC3},
284+
.ovr_msk = { STM32F4_OVR1, STM32F4_OVR2, STM32F4_OVR3},
288285
.ier = STM32F4_ADC_CR1,
289-
.eocie_msk = STM32F4_EOCIE | STM32F4_OVRIE,
286+
.eocie_msk = STM32F4_EOCIE,
290287
};
291288

292289
/* STM32H7 common registers definitions */
293290
static const struct stm32_adc_common_regs stm32h7_adc_common_regs = {
294291
.csr = STM32H7_ADC_CSR,
295292
.ccr = STM32H7_ADC_CCR,
296-
.eoc1_msk = STM32H7_EOC_MST | STM32H7_OVR_MST,
297-
.eoc2_msk = STM32H7_EOC_SLV | STM32H7_OVR_SLV,
293+
.eoc_msk = { STM32H7_EOC_MST, STM32H7_EOC_SLV},
294+
.ovr_msk = { STM32H7_OVR_MST, STM32H7_OVR_SLV},
298295
.ier = STM32H7_ADC_IER,
299-
.eocie_msk = STM32H7_EOCIE | STM32H7_OVRIE,
296+
.eocie_msk = STM32H7_EOCIE,
300297
};
301298

302299
static const unsigned int stm32_adc_offset[STM32_ADC_MAX_ADCS] = {
@@ -318,6 +315,7 @@ static void stm32_adc_irq_handler(struct irq_desc *desc)
318315
{
319316
struct stm32_adc_priv *priv = irq_desc_get_handler_data(desc);
320317
struct irq_chip *chip = irq_desc_get_chip(desc);
318+
int i;
321319
u32 status;
322320

323321
chained_irq_enter(chip, desc);
@@ -335,17 +333,12 @@ static void stm32_adc_irq_handler(struct irq_desc *desc)
335333
* before invoking the interrupt handler (e.g. call ISR only for
336334
* IRQ-enabled ADCs).
337335
*/
338-
if (status & priv->cfg->regs->eoc1_msk &&
339-
stm32_adc_eoc_enabled(priv, 0))
340-
generic_handle_irq(irq_find_mapping(priv->domain, 0));
341-
342-
if (status & priv->cfg->regs->eoc2_msk &&
343-
stm32_adc_eoc_enabled(priv, 1))
344-
generic_handle_irq(irq_find_mapping(priv->domain, 1));
345-
346-
if (status & priv->cfg->regs->eoc3_msk &&
347-
stm32_adc_eoc_enabled(priv, 2))
348-
generic_handle_irq(irq_find_mapping(priv->domain, 2));
336+
for (i = 0; i < priv->cfg->num_irqs; i++) {
337+
if ((status & priv->cfg->regs->eoc_msk[i] &&
338+
stm32_adc_eoc_enabled(priv, i)) ||
339+
(status & priv->cfg->regs->ovr_msk[i]))
340+
generic_handle_irq(irq_find_mapping(priv->domain, i));
341+
}
349342

350343
chained_irq_exit(chip, desc);
351344
};

drivers/iio/adc/stm32-adc.c

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ struct stm32_adc;
154154
* @start_conv: routine to start conversions
155155
* @stop_conv: routine to stop conversions
156156
* @unprepare: optional unprepare routine (disable, power-down)
157+
* @irq_clear: routine to clear irqs
157158
* @smp_cycles: programmable sampling time (ADC clock cycles)
158159
*/
159160
struct stm32_adc_cfg {
@@ -166,6 +167,7 @@ struct stm32_adc_cfg {
166167
void (*start_conv)(struct iio_dev *, bool dma);
167168
void (*stop_conv)(struct iio_dev *);
168169
void (*unprepare)(struct iio_dev *);
170+
void (*irq_clear)(struct iio_dev *indio_dev, u32 msk);
169171
const unsigned int *smp_cycles;
170172
};
171173

@@ -621,6 +623,13 @@ static void stm32f4_adc_stop_conv(struct iio_dev *indio_dev)
621623
STM32F4_ADON | STM32F4_DMA | STM32F4_DDS);
622624
}
623625

626+
static void stm32f4_adc_irq_clear(struct iio_dev *indio_dev, u32 msk)
627+
{
628+
struct stm32_adc *adc = iio_priv(indio_dev);
629+
630+
stm32_adc_clr_bits(adc, adc->cfg->regs->isr_eoc.reg, msk);
631+
}
632+
624633
static void stm32h7_adc_start_conv(struct iio_dev *indio_dev, bool dma)
625634
{
626635
struct stm32_adc *adc = iio_priv(indio_dev);
@@ -659,6 +668,13 @@ static void stm32h7_adc_stop_conv(struct iio_dev *indio_dev)
659668
stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR, STM32H7_DMNGT_MASK);
660669
}
661670

671+
static void stm32h7_adc_irq_clear(struct iio_dev *indio_dev, u32 msk)
672+
{
673+
struct stm32_adc *adc = iio_priv(indio_dev);
674+
/* On STM32H7 IRQs are cleared by writing 1 into ISR register */
675+
stm32_adc_set_bits(adc, adc->cfg->regs->isr_eoc.reg, msk);
676+
}
677+
662678
static int stm32h7_adc_exit_pwr_down(struct iio_dev *indio_dev)
663679
{
664680
struct stm32_adc *adc = iio_priv(indio_dev);
@@ -1235,17 +1251,40 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev,
12351251
}
12361252
}
12371253

1254+
static void stm32_adc_irq_clear(struct iio_dev *indio_dev, u32 msk)
1255+
{
1256+
struct stm32_adc *adc = iio_priv(indio_dev);
1257+
1258+
adc->cfg->irq_clear(indio_dev, msk);
1259+
}
1260+
12381261
static irqreturn_t stm32_adc_threaded_isr(int irq, void *data)
12391262
{
12401263
struct iio_dev *indio_dev = data;
12411264
struct stm32_adc *adc = iio_priv(indio_dev);
12421265
const struct stm32_adc_regspec *regs = adc->cfg->regs;
12431266
u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg);
1267+
u32 mask = stm32_adc_readl(adc, regs->ier_eoc.reg);
12441268

1245-
if (status & regs->isr_ovr.mask)
1269+
/* Check ovr status right now, as ovr mask should be already disabled */
1270+
if (status & regs->isr_ovr.mask) {
1271+
/*
1272+
* Clear ovr bit to avoid subsequent calls to IRQ handler.
1273+
* This requires to stop ADC first. OVR bit state in ISR,
1274+
* is propaged to CSR register by hardware.
1275+
*/
1276+
adc->cfg->stop_conv(indio_dev);
1277+
stm32_adc_irq_clear(indio_dev, regs->isr_ovr.mask);
12461278
dev_err(&indio_dev->dev, "Overrun, stopping: restart needed\n");
1279+
return IRQ_HANDLED;
1280+
}
12471281

1248-
return IRQ_HANDLED;
1282+
if (!(status & mask))
1283+
dev_err_ratelimited(&indio_dev->dev,
1284+
"Unexpected IRQ: IER=0x%08x, ISR=0x%08x\n",
1285+
mask, status);
1286+
1287+
return IRQ_NONE;
12491288
}
12501289

12511290
static irqreturn_t stm32_adc_isr(int irq, void *data)
@@ -1254,6 +1293,10 @@ static irqreturn_t stm32_adc_isr(int irq, void *data)
12541293
struct stm32_adc *adc = iio_priv(indio_dev);
12551294
const struct stm32_adc_regspec *regs = adc->cfg->regs;
12561295
u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg);
1296+
u32 mask = stm32_adc_readl(adc, regs->ier_eoc.reg);
1297+
1298+
if (!(status & mask))
1299+
return IRQ_WAKE_THREAD;
12571300

12581301
if (status & regs->isr_ovr.mask) {
12591302
/*
@@ -2046,6 +2089,7 @@ static const struct stm32_adc_cfg stm32f4_adc_cfg = {
20462089
.start_conv = stm32f4_adc_start_conv,
20472090
.stop_conv = stm32f4_adc_stop_conv,
20482091
.smp_cycles = stm32f4_adc_smp_cycles,
2092+
.irq_clear = stm32f4_adc_irq_clear,
20492093
};
20502094

20512095
static const struct stm32_adc_cfg stm32h7_adc_cfg = {
@@ -2057,6 +2101,7 @@ static const struct stm32_adc_cfg stm32h7_adc_cfg = {
20572101
.prepare = stm32h7_adc_prepare,
20582102
.unprepare = stm32h7_adc_unprepare,
20592103
.smp_cycles = stm32h7_adc_smp_cycles,
2104+
.irq_clear = stm32h7_adc_irq_clear,
20602105
};
20612106

20622107
static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
@@ -2069,6 +2114,7 @@ static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
20692114
.prepare = stm32h7_adc_prepare,
20702115
.unprepare = stm32h7_adc_unprepare,
20712116
.smp_cycles = stm32h7_adc_smp_cycles,
2117+
.irq_clear = stm32h7_adc_irq_clear,
20722118
};
20732119

20742120
static const struct of_device_id stm32_adc_of_match[] = {

0 commit comments

Comments
 (0)