summaryrefslogtreecommitdiffstats
path: root/drivers/mfd/stm32-timers.c
diff options
context:
space:
mode:
authorFabrice Gasnier <fabrice.gasnier@foss.st.com>2023-08-29 15:40:25 +0200
committerLee Jones <lee@kernel.org>2023-11-01 11:02:12 +0100
commit1c7ea43fc42b09080657c83683846c4be672bd91 (patch)
tree5890f6e812ca2444df22fcc2551cb92bd10d585c /drivers/mfd/stm32-timers.c
parentmfd: twl-core: Add a clock subdevice for the TWL6032 (diff)
downloadlinux-1c7ea43fc42b09080657c83683846c4be672bd91.tar.xz
linux-1c7ea43fc42b09080657c83683846c4be672bd91.zip
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: Fabrice Gasnier <fabrice.gasnier@foss.st.com> Link: https://lore.kernel.org/r/20230829134029.2402868-5-fabrice.gasnier@foss.st.com Signed-off-by: Lee Jones <lee@kernel.org>
Diffstat (limited to 'drivers/mfd/stm32-timers.c')
-rw-r--r--drivers/mfd/stm32-timers.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/drivers/mfd/stm32-timers.c b/drivers/mfd/stm32-timers.c
index 732a28db80fa..a656a1c186a8 100644
--- a/drivers/mfd/stm32-timers.c
+++ b/drivers/mfd/stm32-timers.c
@@ -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);