On 12/09/2024 20:24, Arturs Artamonovs via B4 Relay wrote: > From: Arturs Artamonovs <arturs.artamonovs@xxxxxxxxxx> > > Support seting extra indepdendent interrupt on pin activity. > > Signed-off-by: Arturs Artamonovs <Arturs.Artamonovs@xxxxxxxxxx> > Co-developed-by: Nathan Barrett-Morrison <nathan.morrison@xxxxxxxxxxx> > Signed-off-by: Nathan Barrett-Morrison <nathan.morrison@xxxxxxxxxxx> > Co-developed-by: Greg Malysa <greg.malysa@xxxxxxxxxxx> > Signed-off-by: Greg Malysa <greg.malysa@xxxxxxxxxxx> > --- > drivers/irqchip/Kconfig | 9 ++ > drivers/irqchip/Makefile | 2 + > drivers/irqchip/irq-adi-adsp.c | 310 +++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 321 insertions(+) > > diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig > index d078bdc48c38f13af9a129974f3b637dfee0e40f..1bc8f1bd45b3d2f69d2d0e6c8fa01b17b12ce241 100644 > --- a/drivers/irqchip/Kconfig > +++ b/drivers/irqchip/Kconfig > @@ -91,6 +91,15 @@ config ALPINE_MSI > select PCI_MSI > select GENERIC_IRQ_CHIP > > +config ADI_ADSP_IRQ > + bool "ADI PORT PINT Driver" What is "PORT"? What is "PINT"? > + depends on OF > + depends on (ARCH_SC59X_64 || ARCH_SC59X) Missing compile test. > + select IRQ_DOMAIN > + help > + Say Y to enable the PORT-based PINT interrupt controller for Expand acronyms here. > + Analog Devices ADSP devices. > + > config AL_FIC > bool "Amazon's Annapurna Labs Fabric Interrupt Controller" > depends on OF > diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile > index 15635812b2d6605a2dd3bb0e5fb3170ab2cb0f77..258a188676fd97e713f3cebe16e3d563add095f3 100644 > --- a/drivers/irqchip/Makefile > +++ b/drivers/irqchip/Makefile > @@ -1,6 +1,8 @@ > # SPDX-License-Identifier: GPL-2.0 > obj-$(CONFIG_IRQCHIP) += irqchip.o > > + Why? > +obj-$(CONFIG_ADI_ADSP_IRQ) += irq-adi-adsp.o > obj-$(CONFIG_AL_FIC) += irq-al-fic.o > obj-$(CONFIG_ALPINE_MSI) += irq-alpine-msi.o ... > + > +static int adsp_pint_irq_set_type(struct irq_data *d, unsigned int type) > +{ > + struct adsp_pint *pint = irq_data_get_irq_chip_data(d); > + unsigned int pos = BIT(d->hwirq); > + > + switch (type) { > + case IRQ_TYPE_PROBE: > + type = IRQ_TYPE_EDGE_BOTH; > + fallthrough; > + case IRQ_TYPE_EDGE_BOTH: > + /* start by looking for rising edge */ > + writel(pos, pint->regs + ADSP_PINT_REG_INVERT_CLEAR); > + writel(pos, pint->regs + ADSP_PINT_REG_EDGE_SET); > + return 0; > + > + case IRQ_TYPE_EDGE_FALLING: > + writel(pos, pint->regs + ADSP_PINT_REG_INVERT_SET); > + writel(pos, pint->regs + ADSP_PINT_REG_EDGE_SET); > + return 0; > + > + case IRQ_TYPE_EDGE_RISING: > + writel(pos, pint->regs + ADSP_PINT_REG_INVERT_CLEAR); > + writel(pos, pint->regs + ADSP_PINT_REG_EDGE_SET); > + return 0; > + > + case IRQ_TYPE_LEVEL_HIGH: > + writel(pos, pint->regs + ADSP_PINT_REG_INVERT_CLEAR); > + writel(pos, pint->regs + ADSP_PINT_REG_EDGE_CLEAR); > + return 0; > + > + case IRQ_TYPE_LEVEL_LOW: > + writel(pos, pint->regs + ADSP_PINT_REG_INVERT_SET); > + writel(pos, pint->regs + ADSP_PINT_REG_EDGE_CLEAR); > + return 0; > + > + default: > + return -EINVAL; > + } > + Fix blank line issues everywhere. > +} > + > +static int adsp_pint_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct device_node *np = dev->of_node; > + struct adsp_pint *pint; > + > + pint = devm_kzalloc(dev, sizeof(*pint), GFP_KERNEL); > + if (!pint) > + return -ENOMEM; > + > + pint->regs = devm_platform_ioremap_resource(pdev, 0); > + if (IS_ERR(pint->regs)) > + return PTR_ERR(pint->regs); > + > + pint->chip.name = "adsp-pint"; > + pint->chip.irq_ack = adsp_pint_irq_ack; > + pint->chip.irq_mask = adsp_pint_irq_mask; > + pint->chip.irq_unmask = adsp_pint_irq_unmask; > + pint->chip.irq_set_type = adsp_pint_irq_set_type; > + // @todo potentially only SEC supports wake options, not gic > + > + // @todo determine if we actually need a raw spinlock > + > + pint->domain = irq_domain_add_linear(np, ADSP_PINT_IRQS, > + &adsp_irq_domain_ops, pint); > + if (!pint->domain) { > + dev_err(dev, "Could not create irq domain\n"); > + return -EINVAL; > + } > + > + pint->irq = platform_get_irq(pdev, 0); > + if (!pint->irq) { That's a bug, technically. Read the doc. Why -EINVAL is a valid interrupt? > + dev_err(dev, "Could not find parent interrupt for port\n"); > + return -EINVAL; > + } > + > + irq_set_chained_handler_and_data(pint->irq, adsp_pint_irq_handler, pint); > + platform_set_drvdata(pdev, pint); > + > + return 0; > +} > + > +static void adsp_pint_remove(struct platform_device *pdev) > +{ > + struct adsp_pint *pint = platform_get_drvdata(pdev); > + > + irq_set_chained_handler_and_data(pint->irq, NULL, NULL); > + irq_domain_remove(pint->domain); > +} > + > +static const struct of_device_id adsp_pint_of_match[] = { > + { .compatible = "adi,adsp-pint" }, > + { } > +}; > +MODULE_DEVICE_TABLE(of, adsp_pint_of_match); > + > +static struct platform_driver adsp_pint_driver = { > + .driver = { > + .name = "adsp-port-pint", Bindings are always before the users. Best regards, Krzysztof