2020-04-23 17:50:18

by Michael Walle

[permalink] [raw]
Subject: [PATCH v3 06/16] irqchip: add sl28cpld interrupt controller support

This patch adds support for the interrupt controller inside the sl28
CPLD management controller.

Signed-off-by: Michael Walle <[email protected]>
---
drivers/irqchip/Kconfig | 3 ++
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-sl28cpld.c | 97 ++++++++++++++++++++++++++++++++++
drivers/mfd/Kconfig | 2 +
4 files changed, 103 insertions(+)
create mode 100644 drivers/irqchip/irq-sl28cpld.c

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index a85aada04a64..234db932e7cf 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 37bbe39bf909..e3c6b94f7b0a 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -107,3 +107,4 @@ obj-$(CONFIG_TI_SCI_INTR_IRQCHIP) += irq-ti-sci-intr.o
obj-$(CONFIG_TI_SCI_INTA_IRQCHIP) += irq-ti-sci-inta.o
obj-$(CONFIG_LOONGSON_LIOINTC) += irq-loongson-liointc.o
obj-$(CONFIG_LOONGSON_HTPIC) += irq-loongson-htpic.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..88de71d32b09
--- /dev/null
+++ b/drivers/irqchip/irq-sl28cpld.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * sl28cpld interrupt controller driver.
+ *
+ * Copyright 2019 Kontron Europe GmbH
+ */
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define INTC_IE 0x00
+#define INTC_IP 0x01
+
+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;
+
+ if (!pdev->dev.parent)
+ return -ENODEV;
+
+ irqchip = devm_kzalloc(&pdev->dev, sizeof(*irqchip), GFP_KERNEL);
+ if (!irqchip)
+ return -ENOMEM;
+
+ 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 const struct platform_device_id sl28cpld_intc_id_table[] = {
+ { "sl28cpld-intc" },
+ {}
+};
+MODULE_DEVICE_TABLE(platform, sl28cpld_intc_id_table);
+
+static struct platform_driver sl28cpld_intc_driver = {
+ .probe = sl28cpld_intc_probe,
+ .id_table = sl28cpld_intc_id_table,
+ .driver = {
+ .name = KBUILD_MODNAME,
+ }
+};
+module_platform_driver(sl28cpld_intc_driver);
+
+MODULE_DESCRIPTION("sl28cpld Interrupt Controller Driver");
+MODULE_AUTHOR("Michael Walle <[email protected]>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index be0c8d93c526..9e848a455172 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -2065,6 +2065,8 @@ config MFD_SL28CPLD
depends on I2C=y
depends on OF
select REGMAP_I2C
+ select REGMAP_IRQ
+ select SL28CPLD_INTC
select MFD_CORE
help
This option enables support for the board management controller
--
2.20.1


2020-04-27 11:42:38

by Thomas Gleixner

[permalink] [raw]
Subject: Re: [PATCH v3 06/16] irqchip: add sl28cpld interrupt controller support

Michael Walle <[email protected]> writes:

> This patch adds support for the interrupt controller inside the sl28

git grep 'This patch' Documentation/process/

> CPLD management controller.
>
> +static int sl28cpld_intc_probe(struct platform_device *pdev)
> +{
> + struct sl28cpld_intc *irqchip;
> + struct resource *res;
> + unsigned int irq;
> + int ret;
> +
> + if (!pdev->dev.parent)
> + return -ENODEV;
> +
> + irqchip = devm_kzalloc(&pdev->dev, sizeof(*irqchip), GFP_KERNEL);
> + if (!irqchip)
> + return -ENOMEM;
> +
> + 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,

What's the point of IRQF_SHARED | IRQF_ONESHOT here?

> + &irqchip->chip, &irqchip->irq_data);

Thanks,

tglx

2020-04-27 17:42:29

by Michael Walle

[permalink] [raw]
Subject: Re: [PATCH v3 06/16] irqchip: add sl28cpld interrupt controller support

Hi Thomas,

thanks for the review.

Am 2020-04-27 13:40, schrieb Thomas Gleixner:
> Michael Walle <[email protected]> writes:
>
>> This patch adds support for the interrupt controller inside the sl28
>
> git grep 'This patch' Documentation/process/

ok.

>
>> CPLD management controller.
>>
>> +static int sl28cpld_intc_probe(struct platform_device *pdev)
>> +{
>> + struct sl28cpld_intc *irqchip;
>> + struct resource *res;
>> + unsigned int irq;
>> + int ret;
>> +
>> + if (!pdev->dev.parent)
>> + return -ENODEV;
>> +
>> + irqchip = devm_kzalloc(&pdev->dev, sizeof(*irqchip), GFP_KERNEL);
>> + if (!irqchip)
>> + return -ENOMEM;
>> +
>> + 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,
>
> What's the point of IRQF_SHARED | IRQF_ONESHOT here?

IRQF_SHARED because this interrupt is shared with all the blocks
which can generate interrupts, i.e. the GPIO contollers.

IRQF_ONESHOT, because its is a threaded interrupt with no primary
handler. But I just noticed, that regmap-irq will also set the
IRQF_ONESHOT. But that the commit 09cadf6e088b ("regmap-irq:
set IRQF_ONESHOT flag to ensure IRQ request") reads like it is
just there to be sure. So I don't know if it should also be set
here.

-michael

>
>> + &irqchip->chip, &irqchip->irq_data);
>
> Thanks,
>
> tglx

2020-04-27 17:48:46

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH v3 06/16] irqchip: add sl28cpld interrupt controller support

On Mon, Apr 27, 2020 at 07:40:11PM +0200, Michael Walle wrote:

> IRQF_ONESHOT, because its is a threaded interrupt with no primary
> handler. But I just noticed, that regmap-irq will also set the
> IRQF_ONESHOT. But that the commit 09cadf6e088b ("regmap-irq:
> set IRQF_ONESHOT flag to ensure IRQ request") reads like it is
> just there to be sure. So I don't know if it should also be set
> here.

Looking at the changelog there the "we can't be sure" bit is that
coccinelle couldn't follow the flags through from the caller to make
sure that IRQF_ONESHOT is set so we're just oring it in unconditionally.


Attachments:
(No filename) (620.00 B)
signature.asc (499.00 B)
Download all attachments

2020-04-27 18:03:39

by Michael Walle

[permalink] [raw]
Subject: Re: [PATCH v3 06/16] irqchip: add sl28cpld interrupt controller support

Am 2020-04-27 19:44, schrieb Mark Brown:
> On Mon, Apr 27, 2020 at 07:40:11PM +0200, Michael Walle wrote:
>
>> IRQF_ONESHOT, because its is a threaded interrupt with no primary
>> handler. But I just noticed, that regmap-irq will also set the
>> IRQF_ONESHOT. But that the commit 09cadf6e088b ("regmap-irq:
>> set IRQF_ONESHOT flag to ensure IRQ request") reads like it is
>> just there to be sure. So I don't know if it should also be set
>> here.
>
> Looking at the changelog there the "we can't be sure" bit is that
> coccinelle couldn't follow the flags through from the caller to make
> sure that IRQF_ONESHOT is set so we're just oring it in
> unconditionally.

So it is correct that IRQF_ONESHOT is also set in the driver which is
using regmap_add_irq_chip(), right?

-michael

2020-04-27 18:10:14

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH v3 06/16] irqchip: add sl28cpld interrupt controller support

On Mon, Apr 27, 2020 at 08:01:14PM +0200, Michael Walle wrote:
> Am 2020-04-27 19:44, schrieb Mark Brown:

> > Looking at the changelog there the "we can't be sure" bit is that
> > coccinelle couldn't follow the flags through from the caller to make
> > sure that IRQF_ONESHOT is set so we're just oring it in unconditionally.

> So it is correct that IRQF_ONESHOT is also set in the driver which is
> using regmap_add_irq_chip(), right?

It shouldn't break anything and my instinct is that it's better form.


Attachments:
(No filename) (520.00 B)
signature.asc (499.00 B)
Download all attachments

2020-04-27 19:05:01

by Thomas Gleixner

[permalink] [raw]
Subject: Re: [PATCH v3 06/16] irqchip: add sl28cpld interrupt controller support

Michael,

Michael Walle <[email protected]> writes:
> Am 2020-04-27 13:40, schrieb Thomas Gleixner:
>>> +
>>> + ret = devm_regmap_add_irq_chip(&pdev->dev, irqchip->regmap, irq,
>>> + IRQF_SHARED | IRQF_ONESHOT, 0,
>>
>> What's the point of IRQF_SHARED | IRQF_ONESHOT here?
>
> IRQF_SHARED because this interrupt is shared with all the blocks
> which can generate interrupts, i.e. the GPIO contollers.

Why are people still designing hardware with shared interrupts? Shared
interrupts are broken by design and that's well known for decades.

> IRQF_ONESHOT, because its is a threaded interrupt with no primary
> handler. But I just noticed, that regmap-irq will also set the
> IRQF_ONESHOT. But that the commit 09cadf6e088b ("regmap-irq:
> set IRQF_ONESHOT flag to ensure IRQ request") reads like it is
> just there to be sure. So I don't know if it should also be set
> here.

Ok. Wasn't aware of that magic threaded interrupt connection.

Thanks,

tglx