Commit 1c7ea43f authored by Fabrice Gasnier's avatar Fabrice Gasnier Committed by Lee Jones

mfd: stm32-timers: Add support for interrupts

There are two types of STM32 timers that may have:

- a global interrupt line
- 4 dedicated interrupt lines.

Those interrupts are optional as defined in the dt-bindings. Enforce checks
on either one, four or no interrupts are provided with their names.
Optionally get them here, to be used by child devices.
Signed-off-by: default avatarFabrice Gasnier <fabrice.gasnier@foss.st.com>
Link: https://lore.kernel.org/r/20230829134029.2402868-5-fabrice.gasnier@foss.st.comSigned-off-by: default avatarLee Jones <lee@kernel.org>
parent 63416320
......@@ -215,6 +215,48 @@ static void stm32_timers_dma_remove(struct device *dev,
dma_release_channel(ddata->dma.chans[i]);
}
static const char * const stm32_timers_irq_name[STM32_TIMERS_MAX_IRQS] = {
"brk", "up", "trg-com", "cc"
};
static int stm32_timers_irq_probe(struct platform_device *pdev,
struct stm32_timers *ddata)
{
int i, ret;
/*
* STM32 Timer may have either:
* - a unique global interrupt line
* - four dedicated interrupt lines that may be handled separately.
* Optionally get them here, to be used by child devices.
*/
ret = platform_get_irq_byname_optional(pdev, "global");
if (ret < 0 && ret != -ENXIO) {
return ret;
} else if (ret != -ENXIO) {
ddata->irq[STM32_TIMERS_IRQ_GLOBAL_BRK] = ret;
ddata->nr_irqs = 1;
return 0;
}
for (i = 0; i < STM32_TIMERS_MAX_IRQS; i++) {
ret = platform_get_irq_byname_optional(pdev, stm32_timers_irq_name[i]);
if (ret < 0 && ret != -ENXIO) {
return ret;
} else if (ret != -ENXIO) {
ddata->irq[i] = ret;
ddata->nr_irqs++;
}
}
if (ddata->nr_irqs && ddata->nr_irqs != STM32_TIMERS_MAX_IRQS) {
dev_err(&pdev->dev, "Invalid number of IRQs %d\n", ddata->nr_irqs);
return -EINVAL;
}
return 0;
}
static int stm32_timers_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
......@@ -245,6 +287,10 @@ static int stm32_timers_probe(struct platform_device *pdev)
stm32_timers_get_arr_size(ddata);
ret = stm32_timers_irq_probe(pdev, ddata);
if (ret)
return ret;
ret = stm32_timers_dma_probe(dev, ddata);
if (ret) {
stm32_timers_dma_remove(dev, ddata);
......
......@@ -102,6 +102,15 @@ enum stm32_timers_dmas {
STM32_TIMERS_MAX_DMAS,
};
/* STM32 Timer may have either a unique global interrupt or 4 interrupt lines */
enum stm32_timers_irqs {
STM32_TIMERS_IRQ_GLOBAL_BRK, /* global or brk IRQ */
STM32_TIMERS_IRQ_UP,
STM32_TIMERS_IRQ_TRG_COM,
STM32_TIMERS_IRQ_CC,
STM32_TIMERS_MAX_IRQS,
};
/**
* struct stm32_timers_dma - STM32 timer DMA handling.
* @completion: end of DMA transfer completion
......@@ -123,6 +132,8 @@ struct stm32_timers {
struct regmap *regmap;
u32 max_arr;
struct stm32_timers_dma dma; /* Only to be used by the parent */
unsigned int nr_irqs;
int irq[STM32_TIMERS_MAX_IRQS];
};
#if IS_REACHABLE(CONFIG_MFD_STM32_TIMERS)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment