diff options
-rw-r--r-- | drivers/irqchip/Kconfig | 1 | ||||
-rw-r--r-- | drivers/irqchip/irq-ti-sci-inta.c | 40 |
2 files changed, 40 insertions, 1 deletions
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 2c8d5daad57c..fcf9457cc1d9 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -433,6 +433,7 @@ config TI_SCI_INTA_IRQCHIP bool depends on TI_SCI_PROTOCOL select IRQ_DOMAIN_HIERARCHY + select TI_SCI_INTA_MSI_DOMAIN help This enables the irqchip driver support for K3 Interrupt aggregator over TI System Control Interface available on some new TI's SoCs. diff --git a/drivers/irqchip/irq-ti-sci-inta.c b/drivers/irqchip/irq-ti-sci-inta.c index 87e0abe0041f..011b60a49e3f 100644 --- a/drivers/irqchip/irq-ti-sci-inta.c +++ b/drivers/irqchip/irq-ti-sci-inta.c @@ -18,6 +18,7 @@ #include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/irqchip/chained_irq.h> +#include <linux/soc/ti/ti_sci_inta_msi.h> #include <linux/soc/ti/ti_sci_protocol.h> #include <asm-generic/msi.h> @@ -28,6 +29,9 @@ #define HWIRQ_TO_DEVID(hwirq) (((hwirq) >> (TI_SCI_DEV_ID_SHIFT)) & \ (TI_SCI_DEV_ID_MASK)) #define HWIRQ_TO_IRQID(hwirq) ((hwirq) & (TI_SCI_IRQ_ID_MASK)) +#define TO_HWIRQ(dev, index) ((((dev) & TI_SCI_DEV_ID_MASK) << \ + TI_SCI_DEV_ID_SHIFT) | \ + ((index) & TI_SCI_IRQ_ID_MASK)) #define MAX_EVENTS_PER_VINT 64 #define VINT_ENABLE_SET_OFFSET 0x0 @@ -484,9 +488,34 @@ static const struct irq_domain_ops ti_sci_inta_irq_domain_ops = { .alloc = ti_sci_inta_irq_domain_alloc, }; +static struct irq_chip ti_sci_inta_msi_irq_chip = { + .name = "MSI-INTA", + .flags = IRQCHIP_SUPPORTS_LEVEL_MSI, +}; + +static void ti_sci_inta_msi_set_desc(msi_alloc_info_t *arg, + struct msi_desc *desc) +{ + struct platform_device *pdev = to_platform_device(desc->dev); + + arg->desc = desc; + arg->hwirq = TO_HWIRQ(pdev->id, desc->inta.dev_index); +} + +static struct msi_domain_ops ti_sci_inta_msi_ops = { + .set_desc = ti_sci_inta_msi_set_desc, +}; + +static struct msi_domain_info ti_sci_inta_msi_domain_info = { + .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | + MSI_FLAG_LEVEL_CAPABLE), + .ops = &ti_sci_inta_msi_ops, + .chip = &ti_sci_inta_msi_irq_chip, +}; + static int ti_sci_inta_irq_domain_probe(struct platform_device *pdev) { - struct irq_domain *parent_domain, *domain; + struct irq_domain *parent_domain, *domain, *msi_domain; struct device_node *parent_node, *node; struct ti_sci_inta_irq_domain *inta; struct device *dev = &pdev->dev; @@ -551,6 +580,15 @@ static int ti_sci_inta_irq_domain_probe(struct platform_device *pdev) return -ENOMEM; } + msi_domain = ti_sci_inta_msi_create_irq_domain(of_node_to_fwnode(node), + &ti_sci_inta_msi_domain_info, + domain); + if (!msi_domain) { + irq_domain_remove(domain); + dev_err(dev, "Failed to allocate msi domain\n"); + return -ENOMEM; + } + INIT_LIST_HEAD(&inta->vint_list); mutex_init(&inta->vint_mutex); |