diff mbox series

[06/18] irqchip: add sl28cpld interrupt controller support

Message ID 20200317205017.28280-7-michael@walle.cc (mailing list archive)
State Changes Requested
Headers show
Series Add support for Kontron sl28cpld | expand

Commit Message

Michael Walle March 17, 2020, 8:50 p.m. UTC
This patch adds support for the interrupt controller inside the sl28
CPLD management controller.

Signed-off-by: Michael Walle <michael@walle.cc>
---
 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

Comments

Guenter Roeck March 18, 2020, 4:53 p.m. UTC | #1
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@walle.cc>
> ---
>  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
>
Michael Walle March 18, 2020, 5:06 p.m. UTC | #2
Am 2020-03-18 17:53, schrieb Guenter Roeck:
> 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@walle.cc>
>> ---
>>  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 ?

I though it was a good idea to have that gradually build up, esp. since
these patches might go through different reviewers/trees. That being 
said,
I'll change it though.

> It does explain the I2C=y, but I really think it should be bool from
> the start if it ends up
> there.

Ok.

> 
>>  	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 ?

oh damn. this is a left-over which slipped through. There should just
be a SL28CPLD_INTC.

-michael

> 
>>  	select MFD_CORE
>>  	help
>>  	  This option enables support for the board management controller
>>
Guenter Roeck March 18, 2020, 8:35 p.m. UTC | #3
On 3/18/20 10:06 AM, Michael Walle wrote:
> Am 2020-03-18 17:53, schrieb Guenter Roeck:
>> 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@walle.cc>
>>> ---
>>>  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 ?
> 
> I though it was a good idea to have that gradually build up, esp. since
> these patches might go through different reviewers/trees. That being said,
> I'll change it though.
> 

Gradually build up is fine, but that doesn't mean to do it one way first and
change it later. This only results in feedback like mine - I2C=y just
didn't make sense in the previous patch. Please keep in mind that doing
things one way first and then changing them later only wastes people's time.
It would be much better to mention in the previous patch that the symbol is
declared bool because a subsequent patch introduces an interrupt controller
driver which needs to be built-in.

Thanks,
Guenter

>> It does explain the I2C=y, but I really think it should be bool from
>> the start if it ends up
>> there.
> 
> Ok.
> 
>>
>>>      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 ?
> 
> oh damn. this is a left-over which slipped through. There should just
> be a SL28CPLD_INTC.
> 
> -michael
> 
>>
>>>      select MFD_CORE
>>>      help
>>>        This option enables support for the board management controller
>>>
diff mbox series

Patch

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"
 	depends on I2C=y
 	depends on OF
 	select REGMAP_I2C
 	select REGMAP_IRQ
-	select SL28CPLD_IRQ
+	select SL28CPLD_INTC
 	select MFD_CORE
 	help
 	  This option enables support for the board management controller