* [PATCH 1/2] dt-bindings: interrupt-controller: Add binding for the Microsemi Ocelot interrupt controller
@ 2018-03-20 13:52 Alexandre Belloni
2018-03-20 13:52 ` [PATCH 2/2] irqchip: Add a driver for the Microsemi Ocelot controller Alexandre Belloni
0 siblings, 1 reply; 3+ messages in thread
From: Alexandre Belloni @ 2018-03-20 13:52 UTC (permalink / raw)
To: Marc Zyngier
Cc: Jason Cooper, Thomas Gleixner, linux-kernel, Alexandre Belloni
Add the Device Tree binding documentation for the Microsemi Ocelot
interrupt controller that is part of the ICPU. It is connected directly to
the MIPS core interrupt controller.
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
.../interrupt-controller/mscc,ocelot-icpu-intr.txt | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
create mode 100644 Documentation/devicetree/bindings/interrupt-controller/mscc,ocelot-icpu-intr.txt
diff --git a/Documentation/devicetree/bindings/interrupt-controller/mscc,ocelot-icpu-intr.txt b/Documentation/devicetree/bindings/interrupt-controller/mscc,ocelot-icpu-intr.txt
new file mode 100644
index 000000000000..b47a8a02b17b
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/mscc,ocelot-icpu-intr.txt
@@ -0,0 +1,22 @@
+Microsemi Ocelot SoC ICPU Interrupt Controller
+
+Required properties:
+
+- compatible : should be "mscc,ocelot-icpu-intr"
+- reg : Specifies base physical address and size of the registers.
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+ interrupt source. The value shall be 1.
+- interrupt-parent : phandle of the CPU interrupt controller.
+- interrupts : Specifies the CPU interrupt the controller is connected to.
+
+Example:
+
+ intc: interrupt-controller@70000070 {
+ compatible = "mscc,ocelot-icpu-intr";
+ reg = <0x70000070 0x70>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ interrupt-parent = <&cpuintc>;
+ interrupts = <2>;
+ };
--
2.16.2
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 2/2] irqchip: Add a driver for the Microsemi Ocelot controller
2018-03-20 13:52 [PATCH 1/2] dt-bindings: interrupt-controller: Add binding for the Microsemi Ocelot interrupt controller Alexandre Belloni
@ 2018-03-20 13:52 ` Alexandre Belloni
2018-03-20 14:03 ` Thomas Gleixner
0 siblings, 1 reply; 3+ messages in thread
From: Alexandre Belloni @ 2018-03-20 13:52 UTC (permalink / raw)
To: Marc Zyngier
Cc: Jason Cooper, Thomas Gleixner, linux-kernel, Alexandre Belloni
The Microsemi Ocelot SoC has a pretty simple IRQ controller in its ICPU
block. Add a driver for it.
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
drivers/irqchip/Kconfig | 5 ++
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-mscc-ocelot.c | 109 ++++++++++++++++++++++++++++++++++++++
3 files changed, 115 insertions(+)
create mode 100644 drivers/irqchip/irq-mscc-ocelot.c
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index d913aec85109..0270797765f9 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -286,6 +286,11 @@ config IRQ_MXS
select IRQ_DOMAIN
select STMP_DEVICE
+config MSCC_OCELOT_IRQ
+ bool
+ select IRQ_DOMAIN
+ select GENERIC_IRQ_CHIP
+
config MVEBU_GICP
bool
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index d27e3e3619e0..63d7bb434c33 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -72,6 +72,7 @@ obj-$(CONFIG_ARCH_SA1100) += irq-sa11x0.o
obj-$(CONFIG_INGENIC_IRQ) += irq-ingenic.o
obj-$(CONFIG_IMX_GPCV2) += irq-imx-gpcv2.o
obj-$(CONFIG_PIC32_EVIC) += irq-pic32-evic.o
+obj-$(CONFIG_MSCC_OCELOT_IRQ) += irq-mscc-ocelot.o
obj-$(CONFIG_MVEBU_GICP) += irq-mvebu-gicp.o
obj-$(CONFIG_MVEBU_ICU) += irq-mvebu-icu.o
obj-$(CONFIG_MVEBU_ODMI) += irq-mvebu-odmi.o
diff --git a/drivers/irqchip/irq-mscc-ocelot.c b/drivers/irqchip/irq-mscc-ocelot.c
new file mode 100644
index 000000000000..c2cf46758a59
--- /dev/null
+++ b/drivers/irqchip/irq-mscc-ocelot.c
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Microsemi Ocelot IRQ controller driver
+ *
+ * License: Dual MIT/GPL
+ * Copyright (c) 2017 Microsemi Corporation
+ */
+#include <linux/bitops.h>
+#include <linux/irq.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/interrupt.h>
+
+#define ICPU_CFG_INTR_INTR_STICKY 0x10
+#define ICPU_CFG_INTR_INTR_ENA 0x18
+#define ICPU_CFG_INTR_INTR_ENA_CLR 0x1c
+#define ICPU_CFG_INTR_INTR_ENA_SET 0x20
+#define ICPU_CFG_INTR_DST_INTR_IDENT(x) (0x38 + 0x4 * (x))
+#define ICPU_CFG_INTR_INTR_TRIGGER(x) (0x5c + 0x4 * (x))
+
+#define OCELOT_NR_IRQ 24
+
+static void ocelot_irq_unmask(struct irq_data *data)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
+ struct irq_chip_type *ct = irq_data_get_chip_type(data);
+ unsigned int mask = data->mask;
+ u32 val;
+
+ irq_gc_lock(gc);
+ val = irq_reg_readl(gc, ICPU_CFG_INTR_INTR_TRIGGER(0)) |
+ irq_reg_readl(gc, ICPU_CFG_INTR_INTR_TRIGGER(1));
+ if ((val & mask) == 0)
+ irq_reg_writel(gc, mask, ICPU_CFG_INTR_INTR_STICKY);
+
+ *ct->mask_cache &= ~mask;
+ irq_reg_writel(gc, mask, ICPU_CFG_INTR_INTR_ENA_SET);
+ irq_gc_unlock(gc);
+}
+
+static void ocelot_irq_handler(struct irq_desc *desc)
+{
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct irq_domain *d = irq_desc_get_handler_data(desc);
+ struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, 0);
+ u32 reg = irq_reg_readl(gc, ICPU_CFG_INTR_DST_INTR_IDENT(0));
+
+ chained_irq_enter(chip, desc);
+
+ while (reg) {
+ u32 hwirq = __fls(reg);
+
+ generic_handle_irq(irq_find_mapping(d, hwirq));
+ reg &= ~(BIT(hwirq));
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static int __init ocelot_irq_init(struct device_node *node,
+ struct device_node *parent)
+{
+ struct irq_domain *domain;
+ struct irq_chip_generic *gc;
+ int parent_irq, ret;
+
+ domain = irq_domain_add_linear(node, OCELOT_NR_IRQ,
+ &irq_generic_chip_ops, NULL);
+ if (!domain) {
+ pr_err("%s: unable to add irq domain\n", node->name);
+ return -ENOMEM;
+ }
+
+ ret = irq_alloc_domain_generic_chips(domain, OCELOT_NR_IRQ, 1,
+ "icpu", handle_level_irq,
+ 0, 0, 0);
+ if (ret) {
+ pr_err("%s: unable to alloc irq domain gc\n", node->name);
+ return ret;
+ }
+
+ gc = irq_get_domain_generic_chip(domain, 0);
+ gc->reg_base = of_iomap(node, 0);
+ if (!gc->reg_base) {
+ pr_err("%s: unable to map resource\n", node->name);
+ return -ENOMEM;
+ }
+
+ gc->chip_types[0].regs.ack = ICPU_CFG_INTR_INTR_STICKY;
+ gc->chip_types[0].regs.mask = ICPU_CFG_INTR_INTR_ENA_CLR;
+ gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit;
+ gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit;
+ gc->chip_types[0].chip.irq_unmask = ocelot_irq_unmask;
+
+ irq_reg_writel(gc, 0, ICPU_CFG_INTR_INTR_ENA); /* Mask all */
+ irq_reg_writel(gc, 0xffffffff, ICPU_CFG_INTR_INTR_STICKY); /* Ack pending */
+
+ parent_irq = irq_of_parse_and_map(node, 0);
+ if (!parent_irq)
+ return -EINVAL;
+
+ irq_set_chained_handler_and_data(parent_irq, ocelot_irq_handler,
+ domain);
+
+ return 0;
+}
+IRQCHIP_DECLARE(ocelot_icpu, "mscc,ocelot-icpu-intr", ocelot_irq_init);
--
2.16.2
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH 2/2] irqchip: Add a driver for the Microsemi Ocelot controller
2018-03-20 13:52 ` [PATCH 2/2] irqchip: Add a driver for the Microsemi Ocelot controller Alexandre Belloni
@ 2018-03-20 14:03 ` Thomas Gleixner
0 siblings, 0 replies; 3+ messages in thread
From: Thomas Gleixner @ 2018-03-20 14:03 UTC (permalink / raw)
To: Alexandre Belloni; +Cc: Marc Zyngier, Jason Cooper, linux-kernel
On Tue, 20 Mar 2018, Alexandre Belloni wrote:
> --- /dev/null
> +++ b/drivers/irqchip/irq-mscc-ocelot.c
> @@ -0,0 +1,109 @@
> +// SPDX-License-Identifier: (GPL-2.0 OR MIT)
> +/*
> + * Microsemi Ocelot IRQ controller driver
> + *
> + * License: Dual MIT/GPL
The whole point of SPDX identifiers is to get rid of this kind of sloppy
and inexact license references. The SPDX identifier above is clear and
precise: The code is dual licensed under GPL V2 only or MIT.
Now looking again at your extra line:
> + * License: Dual MIT/GPL
It does not tell which version of GPL.
Please get rid of that.
> + * Copyright (c) 2017 Microsemi Corporation
> + */
> +#include <linux/bitops.h>
> +#include <linux/irq.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/irqchip.h>
> +#include <linux/irqchip/chained_irq.h>
> +#include <linux/interrupt.h>
> +
> +#define ICPU_CFG_INTR_INTR_STICKY 0x10
> +#define ICPU_CFG_INTR_INTR_ENA 0x18
> +#define ICPU_CFG_INTR_INTR_ENA_CLR 0x1c
> +#define ICPU_CFG_INTR_INTR_ENA_SET 0x20
> +#define ICPU_CFG_INTR_DST_INTR_IDENT(x) (0x38 + 0x4 * (x))
> +#define ICPU_CFG_INTR_INTR_TRIGGER(x) (0x5c + 0x4 * (x))
> +
> +#define OCELOT_NR_IRQ 24
> +
> +static void ocelot_irq_unmask(struct irq_data *data)
> +{
> + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
> + struct irq_chip_type *ct = irq_data_get_chip_type(data);
> + unsigned int mask = data->mask;
> + u32 val;
> +
> + irq_gc_lock(gc);
> + val = irq_reg_readl(gc, ICPU_CFG_INTR_INTR_TRIGGER(0)) |
> + irq_reg_readl(gc, ICPU_CFG_INTR_INTR_TRIGGER(1));
> + if ((val & mask) == 0)
Usual kernel style is:
if (!(val & mask))
> + irq_reg_writel(gc, mask, ICPU_CFG_INTR_INTR_STICKY);
> +
> + *ct->mask_cache &= ~mask;
> + irq_reg_writel(gc, mask, ICPU_CFG_INTR_INTR_ENA_SET);
> + irq_gc_unlock(gc);
> +}
> +
> + irq_reg_writel(gc, 0, ICPU_CFG_INTR_INTR_ENA); /* Mask all */
> + irq_reg_writel(gc, 0xffffffff, ICPU_CFG_INTR_INTR_STICKY); /* Ack pending */
Please do not use tail comments. They are annoying as they disturb the
visual parsing.
/* Mask and ack all interrupts */
irq_reg_writel(gc, 0, ICPU_CFG_INTR_INTR_ENA);
irq_reg_writel(gc, 0xffffffff, ICPU_CFG_INTR_INTR_STICKY);
is way better to read.
Other than those nitpicks. Nice work!
Thanks,
tglx
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2018-03-20 14:03 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-20 13:52 [PATCH 1/2] dt-bindings: interrupt-controller: Add binding for the Microsemi Ocelot interrupt controller Alexandre Belloni
2018-03-20 13:52 ` [PATCH 2/2] irqchip: Add a driver for the Microsemi Ocelot controller Alexandre Belloni
2018-03-20 14:03 ` Thomas Gleixner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®