diff mbox series

[RFC,1/2] irqchip: ti-tsir: Add support for Timesync Interrupt Router

Message ID 20250205160119.136639-2-c-vankar@ti.com (mailing list archive)
State RFC
Headers show
Series Add support for Timesync Interrupt Router | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Guessed tree name to be net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 1 of 1 maintainers
netdev/build_clang success Errors and warnings before: 47 this patch: 47
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 10 this patch: 10
netdev/checkpatch warning WARNING: added, moved or deleted file(s), does MAINTAINERS need updating? WARNING: line length of 100 exceeds 80 columns WARNING: line length of 81 exceeds 80 columns WARNING: line length of 83 exceeds 80 columns WARNING: line length of 86 exceeds 80 columns WARNING: line length of 90 exceeds 80 columns WARNING: line length of 91 exceeds 80 columns WARNING: line length of 92 exceeds 80 columns WARNING: line length of 95 exceeds 80 columns
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Chintan Vankar Feb. 5, 2025, 4:01 p.m. UTC
Timesync Interrupt Router is an instantiation of generic interrupt router
module. It provides a mechanism to mux M interrupt inputs to N interrupt
outputs, where all M inputs are selectable to be driven as per N output.
Timesync Interrupt Router's inputs are either from peripherals or from
Device sync Events.

Add support for Timesync Interrupt Router driver to map input received
from peripherals with the corresponding output.

Signed-off-by: Chintan Vankar <c-vankar@ti.com>
---
 drivers/irqchip/Kconfig            |   9 +++
 drivers/irqchip/Makefile           |   1 +
 drivers/irqchip/ti-timesync-intr.c | 109 +++++++++++++++++++++++++++++
 3 files changed, 119 insertions(+)
 create mode 100644 drivers/irqchip/ti-timesync-intr.c
diff mbox series

Patch

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index c11b9965c4ad..48b9d907be0f 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -557,6 +557,15 @@  config TI_SCI_INTA_IRQCHIP
 	  If you wish to use interrupt aggregator irq resources managed by the
 	  TI System Controller, say Y here. Otherwise, say N.
 
+config TI_TS_INTR
+	bool
+	select IRQ_DOMAIN_HIERARCHY
+	help
+	  This enables the irqchip driver support for K3 Timesync Interrupt
+	  router available on TI's SoCs.
+	  To enable Timesync Interrupt Router's mapping, say Y here. Otherwise
+	  say N.
+
 config TI_PRUSS_INTC
 	tristate
 	depends on TI_PRUSS
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 25e9ad29b8c4..00c49f6d492a 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -129,3 +129,4 @@  obj-$(CONFIG_IRQ_IDT3243X)		+= irq-idt3243x.o
 obj-$(CONFIG_APPLE_AIC)			+= irq-apple-aic.o
 obj-$(CONFIG_MCHP_EIC)			+= irq-mchp-eic.o
 obj-$(CONFIG_SUNPLUS_SP7021_INTC)	+= irq-sp7021-intc.o
+obj-$(CONFIG_TS_INTR)			+= ti-timesync-intr.o
diff --git a/drivers/irqchip/ti-timesync-intr.c b/drivers/irqchip/ti-timesync-intr.c
new file mode 100644
index 000000000000..11f26ca649d2
--- /dev/null
+++ b/drivers/irqchip/ti-timesync-intr.c
@@ -0,0 +1,109 @@ 
+// SPDX-License-Identifier: GPL
+/*
+ * Texas Instruments K3 Timesync Interrupt Router driver
+ *
+ * Copyright (C) 2025 Texas Instruments Incorporated - https://www.ti.com/
+ *	Chintan Vankar <c-vankar@ti.com>
+ */
+
+#include <linux/irqchip.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
+#include <linux/list.h>
+
+#define DRIVER_NAME	"ti-tsir"
+
+#define TIMESYNC_INTRTR_ENABLE			GENMASK(5, 0)
+#define TIMESYNC_INTRTR_INT_ENABLE		BIT(16)
+#define TIMESYNC_INTRTR_MAX_OUTPUT_LINES	48
+
+struct tsr_chip_data {
+	void __iomem		*tsr_base;
+	struct irq_domain	*domain;
+	u64			flags;
+};
+
+static struct irq_chip ts_intr_irq_chip = {
+	.name			= "TIMESYNC_INTRTR",
+};
+
+static u32 output_line_to_virq[TIMESYNC_INTRTR_MAX_OUTPUT_LINES];
+static struct tsr_chip_data tsr_data;
+
+static int ts_intr_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
+				    unsigned int nr_irqs, void *arg)
+{
+	unsigned int output_line, input_line, output_line_offset;
+	struct irq_fwspec *fwspec = (struct irq_fwspec *)arg;
+	int ret;
+
+	irq_domain_set_hwirq_and_chip(domain, virq, output_line,
+				      &ts_intr_irq_chip,
+				      NULL);
+
+	/* Check for two input parameters: output line and corresponding input line */
+	if (fwspec->param_count != 2)
+		return -EINVAL;
+
+	output_line = fwspec->param[0];
+
+	/* Timesync Interrupt Router's mux-controller register starts at offset 4 from base
+	 * address and each output line are at offset in multiple of 4s in Timesync INTR's
+	 * register space, calculate the register offset from provided output line.
+	 */
+	output_line_offset = 4 * output_line + 0x4;
+	output_line_to_virq[output_line] = virq;
+	input_line = fwspec->param[1] & TIMESYNC_INTRTR_ENABLE;
+
+	/* Map output line corresponding to input line */
+	writel(input_line, tsr_data.tsr_base + output_line_offset);
+
+	/* When interrupt enable bit is set for Timesync Interrupt Router it maps the output
+	 * line with the existing input line, hence enable interrupt line after we set bits for
+	 * output line.
+	 */
+	input_line |= TIMESYNC_INTRTR_INT_ENABLE;
+	writel(input_line, tsr_data.tsr_base + output_line_offset);
+
+	return 0;
+}
+
+static void ts_intr_irq_domain_free(struct irq_domain *domain, unsigned int virq,
+				    unsigned int nr_irqs)
+{
+	struct output_line_to_virq *node, *n;
+	unsigned int output_line_offset;
+	int i;
+
+	for (i = 0; i < TIMESYNC_INTRTR_MAX_OUTPUT_LINES; i++) {
+		if (output_line_to_virq[i] == virq) {
+			/* Calculate the register offset value from provided output line */
+			output_line_offset = 4 * i + 0x4;
+			writel(~TIMESYNC_INTRTR_INT_ENABLE, tsr_data.tsr_base + output_line_offset);
+		}
+	}
+}
+
+static const struct irq_domain_ops ts_intr_irq_domain_ops = {
+	.alloc		= ts_intr_irq_domain_alloc,
+	.free		= ts_intr_irq_domain_free,
+};
+
+static int tsr_init(struct device_node *node)
+{
+	tsr_data.tsr_base = of_iomap(node, 0);
+	if (IS_ERR(tsr_data.tsr_base)) {
+		pr_err("Unable to get reg\n");
+		return PTR_ERR(tsr_data.tsr_base);
+	}
+
+	tsr_data.domain = irq_domain_create_tree(&node->fwnode, &ts_intr_irq_domain_ops, &tsr_data);
+
+	return 0;
+}
+
+IRQCHIP_DECLARE(ts_intr, "ti,ts-intr", tsr_init);
+
+MODULE_AUTHOR("Chintan Vankar <c-vankar@ti.com>");
+MODULE_DESCRIPTION("Driver to configure Timesync Interrupt Router");
+MODULE_LICENSE("GPL");