On 3/17/20 1:50 PM, Michael Walle wrote: > This patch adds support for the interrupt controller inside the sl28 > CPLD management controller. > > Signed-off-by: Michael Walle <michael@xxxxxxxx> > --- > drivers/irqchip/Kconfig | 3 ++ > drivers/irqchip/Makefile | 1 + > drivers/irqchip/irq-sl28cpld.c | 92 ++++++++++++++++++++++++++++++++++ > drivers/mfd/Kconfig | 4 +- > 4 files changed, 98 insertions(+), 2 deletions(-) > create mode 100644 drivers/irqchip/irq-sl28cpld.c > > diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig > index 24fe08702ef7..3fd7415c8b55 100644 > --- a/drivers/irqchip/Kconfig > +++ b/drivers/irqchip/Kconfig > @@ -246,6 +246,9 @@ config RENESAS_RZA1_IRQC > Enable support for the Renesas RZ/A1 Interrupt Controller, to use up > to 8 external interrupts with configurable sense select. > > +config SL28CPLD_INTC > + bool > + > config ST_IRQCHIP > bool > select REGMAP > diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile > index eae0d78cbf22..0f4a37782609 100644 > --- a/drivers/irqchip/Makefile > +++ b/drivers/irqchip/Makefile > @@ -105,3 +105,4 @@ obj-$(CONFIG_MADERA_IRQ) += irq-madera.o > obj-$(CONFIG_LS1X_IRQ) += irq-ls1x.o > obj-$(CONFIG_TI_SCI_INTR_IRQCHIP) += irq-ti-sci-intr.o > obj-$(CONFIG_TI_SCI_INTA_IRQCHIP) += irq-ti-sci-inta.o > +obj-$(CONFIG_SL28CPLD_INTC) += irq-sl28cpld.o > diff --git a/drivers/irqchip/irq-sl28cpld.c b/drivers/irqchip/irq-sl28cpld.c > new file mode 100644 > index 000000000000..fa52ed79137b > --- /dev/null > +++ b/drivers/irqchip/irq-sl28cpld.c > @@ -0,0 +1,92 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * SMARC-sAL28 Interrupt core driver. > + * > + * Copyright 2019 Kontron Europe GmbH > + */ > + > +#include <linux/kernel.h> > +#include <linux/module.h> > +#include <linux/of.h> > +#include <linux/of_address.h> > +#include <linux/of_platform.h> > +#include <linux/i2c.h> > +#include <linux/regmap.h> > +#include <linux/interrupt.h> > +#include <linux/mfd/core.h> > + > +#define INTC_IE 0 > +#define INTC_IP 1 > + > +static const struct regmap_irq sl28cpld_irqs[] = { > + REGMAP_IRQ_REG_LINE(0, 8), > + REGMAP_IRQ_REG_LINE(1, 8), > + REGMAP_IRQ_REG_LINE(2, 8), > + REGMAP_IRQ_REG_LINE(3, 8), > + REGMAP_IRQ_REG_LINE(4, 8), > + REGMAP_IRQ_REG_LINE(5, 8), > + REGMAP_IRQ_REG_LINE(6, 8), > + REGMAP_IRQ_REG_LINE(7, 8), > +}; > + > +struct sl28cpld_intc { > + struct regmap *regmap; > + struct regmap_irq_chip chip; > + struct regmap_irq_chip_data *irq_data; > +}; > + > +static int sl28cpld_intc_probe(struct platform_device *pdev) > +{ > + struct sl28cpld_intc *irqchip; > + struct resource *res; > + unsigned int irq; > + int ret; > + > + irqchip = devm_kzalloc(&pdev->dev, sizeof(*irqchip), GFP_KERNEL); > + if (!irqchip) > + return -ENOMEM; > + > + if (!pdev->dev.parent) > + return -ENODEV; > + > + irqchip->regmap = dev_get_regmap(pdev->dev.parent, NULL); > + if (!irqchip->regmap) > + return -ENODEV; > + > + irq = platform_get_irq(pdev, 0); > + if (irq < 0) > + return irq; > + > + res = platform_get_resource(pdev, IORESOURCE_REG, 0); > + if (!res) > + return -EINVAL; > + > + irqchip->chip.name = "sl28cpld-intc"; > + irqchip->chip.irqs = sl28cpld_irqs; > + irqchip->chip.num_irqs = ARRAY_SIZE(sl28cpld_irqs); > + irqchip->chip.num_regs = 1; > + irqchip->chip.status_base = res->start + INTC_IP; > + irqchip->chip.mask_base = res->start + INTC_IE; > + irqchip->chip.mask_invert = true, > + irqchip->chip.ack_base = res->start + INTC_IP; > + > + ret = devm_regmap_add_irq_chip(&pdev->dev, irqchip->regmap, irq, > + IRQF_SHARED | IRQF_ONESHOT, 0, > + &irqchip->chip, &irqchip->irq_data); > + if (ret) > + return ret; > + dev_info(&pdev->dev, "registered IRQ %d\n", irq); > + > + return 0; > +} > + > +static struct platform_driver sl28cpld_intc_driver = { > + .probe = sl28cpld_intc_probe, > + .driver = { > + .name = "sl28cpld-intc", > + } > +}; > +module_platform_driver(sl28cpld_intc_driver); > + > +MODULE_DESCRIPTION("sl28cpld Interrupt Controller Driver"); > +MODULE_LICENSE("GPL"); > diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig > index 01588c366476..4f741d640705 100644 > --- a/drivers/mfd/Kconfig > +++ b/drivers/mfd/Kconfig > @@ -2060,12 +2060,12 @@ config SGI_MFD_IOC3 > then say Y. Otherwise say N. > > config MFD_SL28CPLD > - tristate "Kontron sl28 core driver" > + bool "Kontron sl28 core driver" This is .... unusual. Why declare it tristate only to re-declare it bool in the next patch ? It does explain the I2C=y, but I really think it should be bool from the start if it ends up there. > depends on I2C=y > depends on OF > select REGMAP_I2C > select REGMAP_IRQ > - select SL28CPLD_IRQ > + select SL28CPLD_INTC What is the point of introducing SL28CPLD_IRQ in the first place ? > select MFD_CORE > help > This option enables support for the board management controller >