Skip to contentSkip to conversation

irqchip: Add support for ARMv7-M's NVIC

PATCH Superseded Uwe Kleine-König 5 participants 10 messages Jun 12, 2013 – Jun 25, 2013

Subsystems (2)

v4 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

PATCH v4 1/1 irqchip: Add support for ARMv7-M's NVIC

This interrupt controller is found on Cortex-M3 and Cortex-M4 machines.

Support for this controller appeared in Catalin's Cortex tree based on 2.6.33 but was nearly completely rewritten.

---

Notes:
Changes since v3, sent with
Message-Id: <[email protected]>:

- use generic chip
- rename nvic_do_IRQ to nvic_handle_irq

This depends on the stuff currently in tip/irq/for-arm

 arch/arm/kernel/entry-v7m.S |   2 +-
 drivers/irqchip/Kconfig     |   5 ++
 drivers/irqchip/Makefile    |   1 +
 drivers/irqchip/irq-nvic.c  | 116 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 123 insertions(+), 1 deletion(-)
 create mode 100644 drivers/irqchip/irq-nvic.c
arch/arm/kernel/entry-v7m.S +1 -1
index e00621f..52b2643 100644
@@ -49,7 +49,7 @@ __irq_entry:
 	mov	r1, sp
 	stmdb	sp!, {lr}
 	@ routine called with r0 = irq number, r1 = struct pt_regs *
-	bl	nvic_do_IRQ
+	bl	nvic_handle_irq
 
 	pop	{lr}
 	@
drivers/irqchip/Kconfig +5 -0
index 4a33351..8317a7e 100644
@@ -10,6 +10,11 @@ config ARM_GIC
 config GIC_NON_BANKED
 	bool
 
+config ARM_NVIC
+	bool
+	select IRQ_DOMAIN
+	select GENERIC_IRQ_CHIP
+
 config ARM_VIC
 	bool
 	select IRQ_DOMAIN
drivers/irqchip/Makefile +1 -0
index cda4cb5..4bb277c 100644
@@ -10,6 +10,7 @@ obj-$(CONFIG_METAG_PERFCOUNTER_IRQS)	+= irq-metag.o
 obj-$(CONFIG_ARCH_SUNXI)		+= irq-sun4i.o
 obj-$(CONFIG_ARCH_SPEAR3XX)		+= spear-shirq.o
 obj-$(CONFIG_ARM_GIC)			+= irq-gic.o
+obj-$(CONFIG_ARM_NVIC)			+= irq-nvic.o
 obj-$(CONFIG_ARM_VIC)			+= irq-vic.o
 obj-$(CONFIG_SIRF_IRQ)			+= irq-sirfsoc.o
 obj-$(CONFIG_RENESAS_INTC_IRQPIN)	+= irq-renesas-intc-irqpin.o
drivers/irqchip/irq-nvic.c new file +116 -0

116 lines not on this page · raw message

Signature · 1 line
1.8.3
#1 lore raw

Hello,

Quoted 9 lines · Uwe Kleine-K?nig

This interrupt controller is found on Cortex-M3 and Cortex-M4 machines.

Support for this controller appeared in Catalin's Cortex tree based on 2.6.33 but was nearly completely rewritten.

---

Quoted 8 lines

Notes:
Changes since v3, sent with
Message-Id: <[email protected]>:

- use generic chip
- rename nvic_do_IRQ to nvic_handle_irq

This depends on the stuff currently in tip/irq/for-arm

It also depends on Russell King's devel-stable branch. So the options to apply it in case you are otherwise happy with it:

- apply on top of tip/irq/for-arm dropping the change to arch/arm/kernel/entry-v7m.S and let me add that change seperately; or
- let it go through Russell's tree (the dependency on tip/irq/for-arm doesn't stop the patch to be applied on that one, it just won't compile); or
- wait until there is a tree that contains both branches; or
- merge the two trees and apply it on top of the merge.

Best regards
Uwe

Signature · 2 lines
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Acked-by on v4 1/1
#2 lore raw
In reply to Uwe Kleine-König
Quoted 7 lines · Uwe Kleine-K??nig

This interrupt controller is found on Cortex-M3 and Cortex-M4 machines.

Support for this controller appeared in Catalin's Cortex tree based on 2.6.33 but was nearly completely rewritten.

Since you pretty much re-wrote my original code, you can drop my Signed-off-by. Feel free to replace with:

Acked-by on v4 1/1
#3 lore raw
In reply to Uwe Kleine-König
Quoted 7 lines · Uwe Kleine-K?nig

This interrupt controller is found on Cortex-M3 and Cortex-M4 machines.

Support for this controller appeared in Catalin's Cortex tree based on 2.6.33 but was nearly completely rewritten.

Wow, I hadn't followed the details of the generic irqchip patches, but this looks great, almost no code left at all!

#4 lore raw

PATCH v4 1/1 irqchip: Add support for ARMv7-M's NVIC

In reply to Uwe Kleine-König
Quoted 9 lines · Uwe Kleine-K??nig

This interrupt controller is found on Cortex-M3 and Cortex-M4 machines.

Support for this controller appeared in Catalin's Cortex tree based on 2.6.33 but was nearly completely rewritten.

---

Quoted 8 lines

Notes:
Changes since v3, sent with
Message-Id: <[email protected]>:

- use generic chip
- rename nvic_do_IRQ to nvic_handle_irq

This depends on the stuff currently in tip/irq/for-arm

Minor comments below, but it looks good to me. Nice and small.

drivers/irqchip/irq-nvic.c line 49

Quoted 6 lines
drivers/irqchip/irq-nvic.c new file +6 -0
+asmlinkage void __exception_irq_entry
+nvic_handle_irq(irq_hw_number_t hwirq, struct pt_regs *regs)
+{
+	unsigned int irq = irq_linear_revmap(nvic_irq_domain, hwirq);
+
+	handle_IRQ(irq, regs);

Or simply:

	handle_IRQ(irq_linear_revmap(nvic_irq_domain, hwirq), regs);

:)

Quoted 8 lines
drivers/irqchip/irq-nvic.c new file +8 -0
+static int __init nvic_of_init(struct device_node *node,
+			       struct device_node *parent)
+{
+	void __iomem *nvic_base;
+	unsigned int irqs, i, ret;
+	unsigned numbanks = (readl_relaxed(V7M_SCS_ICTR) &
+			     V7M_SCS_ICTR_INTLINESNUM_MASK) + 1;
+	unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;

drivers/irqchip/irq-nvic.c line 77

Quoted 10 lines
drivers/irqchip/irq-nvic.c new file +10 -0
+
+	nvic_base = of_iomap(node, 0);
+	if (!nvic_base) {
+		pr_warn("unable to map nvic registers\n");
+		return -ENOMEM;
+	}
+
+	irqs = numbanks * 32;
+	if (irqs > NVIC_MAX_IRQ)
+		irqs = NVIC_MAX_IRQ;

I would display some kind of message here.

Quoted 47 lines
drivers/irqchip/irq-nvic.c new file +39 -0
+
+	nvic_irq_domain =
+		irq_domain_add_linear(node, irqs, &irq_generic_chip_ops, NULL);
+	if (!nvic_irq_domain) {
+		pr_warn("Failed to allocate irq domain\n");
+		return -ENOMEM;
+	}
+
+	ret = irq_alloc_domain_generic_chips(nvic_irq_domain, 32, numbanks,
+					     "nvic_irq", handle_fasteoi_irq,
+					     clr, 0, IRQ_GC_INIT_MASK_CACHE);
+	if (ret) {
+		pr_warn("Failed to allocate irq chips\n");
+		irq_domain_remove(nvic_irq_domain);
+		return ret;
+	}
+
+	for (i = 0; i < numbanks; ++i) {
+		struct irq_chip_generic *gc =
+			irq_get_domain_generic_chip(nvic_irq_domain, 32 * i);
+		gc->reg_base = nvic_base + 4 * i;
+		gc->chip_types[0].regs.enable = NVIC_ISER;
+		gc->chip_types[0].regs.disable = NVIC_ICER;
+		gc->chip_types[0].chip.irq_mask = irq_gc_mask_disable_reg;
+		gc->chip_types[0].chip.irq_unmask = irq_gc_unmask_enable_reg;
+		gc->chip_types[0].chip.irq_eoi = nvic_eoi;
+	}
+
+	/* Disable all interrupts */
+	for (i = 0; i < irqs; i += 32)
+		writel_relaxed(~0, nvic_base + NVIC_ICER + i * 4 / 32);
+
+	/* Set priority on all interrupts */
+	for (i = 0; i < irqs; i += 4)
+		writel_relaxed(0, nvic_base + NVIC_IPR + i);
+
+	return 0;
+}
+IRQCHIP_DECLARE(armv7m_nvic, "arm,armv7m-nvic", nvic_of_init);
Signature · 7 lines
1.8.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
Signature · 1 line
email sent from notmuch.vim plugin
#5 lore raw
Quoted 31 lines · Grant Likely
Quoted 9 lines · Uwe Kleine-K?nig

This interrupt controller is found on Cortex-M3 and Cortex-M4 machines.

Support for this controller appeared in Catalin's Cortex tree based on 2.6.33 but was nearly completely rewritten.

---

Quoted 8 lines

Notes:
Changes since v3, sent with
Message-Id: <[email protected]>:

- use generic chip
- rename nvic_do_IRQ to nvic_handle_irq

This depends on the stuff currently in tip/irq/for-arm

Minor comments below, but it looks good to me. Nice and small.

drivers/irqchip/irq-nvic.c line 49

Quoted 6 lines
drivers/irqchip/irq-nvic.c new file +6 -0
+asmlinkage void __exception_irq_entry
+nvic_handle_irq(irq_hw_number_t hwirq, struct pt_regs *regs)
+{
+	unsigned int irq = irq_linear_revmap(nvic_irq_domain, hwirq);
+
+	handle_IRQ(irq, regs);

Or simply:

Quoted 1 line
	handle_IRQ(irq_linear_revmap(nvic_irq_domain, hwirq), regs);

I think my version is more readable, so I tend to keep it the way I suggested.

Quoted 12 lines
Quoted 12 lines
drivers/irqchip/irq-nvic.c new file +12 -0
+static int __init nvic_of_init(struct device_node *node,
+			       struct device_node *parent)
+{
+	void __iomem *nvic_base;
+	unsigned int irqs, i, ret;
+	unsigned numbanks = (readl_relaxed(V7M_SCS_ICTR) &
+			     V7M_SCS_ICTR_INTLINESNUM_MASK) + 1;
+	unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
+
+	nvic_base = of_iomap(node, 0);
+	if (!nvic_base) {
+		pr_warn("unable to map nvic registers\n");
Quoted 8 lines

drivers/irqchip/irq-nvic.c line 77

Quoted 6 lines
drivers/irqchip/irq-nvic.c new file +6 -0
+		return -ENOMEM;
+	}
+
+	irqs = numbanks * 32;
+	if (irqs > NVIC_MAX_IRQ)
+		irqs = NVIC_MAX_IRQ;

I would display some kind of message here.

That's not an error case. The documentation about INTLINESNUM reads:

The total number of interrupt lines supported by an implementation, defined in groups of 32. That is, the total number of interrupt lines is up to (32*(INTLINESNUM+1)). However, the absolute maximum number of interrupts is 496, corresponding to the INTLINESNUM value 0b1111.

And the documentation for e.g. NVIC_ISER0 - NVIC_ISER15 reads:

	Usage constraints NVIC_ISERn[31:0] are the set-enable bits for
	interrupts (31+(32*n)) - (32*n).
	When n=15, bits [31:16] are reserved.

So it's just an implementation detail that the last bank can only contain 16 interrupts. There is a comment describing that fact at the definition of NVIC_MAX_IRQ.

So I think this case is important enough to clutter the kernel log.

Best regards
Uwe

Signature · 2 lines
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
#6 lore raw
In reply to Uwe Kleine-König

Hello Thomas, hello Grant,

Quoted 9 lines · Uwe Kleine-K?nig

This interrupt controller is found on Cortex-M3 and Cortex-M4 machines.

Support for this controller appeared in Catalin's Cortex tree based on 2.6.33 but was nearly completely rewritten.

---

Quoted 8 lines

Notes:
Changes since v3, sent with
Message-Id: <[email protected]>:

- use generic chip
- rename nvic_do_IRQ to nvic_handle_irq

This depends on the stuff currently in tip/irq/for-arm

I see that tip/irq/for-arm went into next via Grant's irqdomain tree. I assume that means the changes go in for 3.11?

Are you OK with my patch? I can resend with the accumulated Acks and the arch/arm hunk dropped if it helps you. Just tell me what you want.

Best regards
Uwe

Signature · 2 lines
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
#7 lore raw
Quoted 16 lines · Uwe Kleine-K?nig

Hello Thomas, hello Grant,

Quoted 13 lines · Uwe Kleine-K?nig

This interrupt controller is found on Cortex-M3 and Cortex-M4 machines.

Support for this controller appeared in Catalin's Cortex tree based on 2.6.33 but was nearly completely rewritten.

---

Notes:
Changes since v3, sent with
Message-Id: <[email protected]>:

Quoted 6 lines
Quoted 4 lines

- use generic chip
- rename nvic_do_IRQ to nvic_handle_irq

This depends on the stuff currently in tip/irq/for-arm

I see that tip/irq/for-arm went into next via Grant's irqdomain tree. I assume that means the changes go in for 3.11?

Yes, the plan is to put that branch into v3.11. I don't know if Thomas plans to send a separate pull request for the irq/for-arm branch, or if he is going to let it go as part of my pull request. I'll work it out with him when the merge window opens. It would probably be best for your patch to be applied on the irq/for-arm branch and pushed separately from my irqdomain branch since I don't maintain any of the irqchip drivers.

g.

#8 lore raw
Quoted 21 lines · Grant Likely
Quoted 19 lines · Uwe Kleine-K?nig

Hello Thomas, hello Grant,

Quoted 16 lines · Uwe Kleine-K?nig

This interrupt controller is found on Cortex-M3 and Cortex-M4 machines.

Support for this controller appeared in Catalin's Cortex tree based on 2.6.33 but was nearly completely rewritten.

---

Notes:
Changes since v3, sent with
Message-Id: <[email protected]>:

- use generic chip
- rename nvic_do_IRQ to nvic_handle_irq

Quoted 7 lines
Quoted 3 lines
Quoted 1 line

This depends on the stuff currently in tip/irq/for-arm

I see that tip/irq/for-arm went into next via Grant's irqdomain tree. I assume that means the changes go in for 3.11?

Yes, the plan is to put that branch into v3.11. I don't know if Thomas plans to send a separate pull request for the irq/for-arm branch, or if he is going to let it go as part of my pull request. I'll work it

irq/for-arm is in irq/core as well. So whoever sends first will merge it and the later pull request will just contain the same commits.

Quoted 4 lines

out with him when the merge window opens. It would probably be best for your patch to be applied on the irq/for-arm branch and pushed separately from my irqdomain branch since I don't maintain any of the irqchip drivers.

I can take it via tip/irq/core.

Thanks,

tglx

#9 lore raw
In reply to Uwe Kleine-König
Quoted 1 line · Uwe Kleine-K?nig

This interrupt controller is found on Cortex-M3 and Cortex-M4 machines.

I don't think that anyone is searching for interrupt controllers as they are simply an essential part of the M3/4 SoCs.

Quoted 4 lines

This depends on the stuff currently in tip/irq/for-arm

 arch/arm/kernel/entry-v7m.S |   2 +-

This is not depending on my tree. I can take the patch if

- you drop the arm related change and do that cleanup later

or

- the relevant maintainers provide their ACK.

Quoted 4 lines
drivers/irqchip/irq-nvic.c new file +4 -0
+	for (i = 0; i < numbanks; ++i) {
+		struct irq_chip_generic *gc =
+			irq_get_domain_generic_chip(nvic_irq_domain, 32 * i);
+		gc->reg_base = nvic_base + 4 * i;

drivers/irqchip/irq-nvic.c line 108

Quoted 10 lines
drivers/irqchip/irq-nvic.c new file +10 -0
+		gc->chip_types[0].regs.enable = NVIC_ISER;
+		gc->chip_types[0].regs.disable = NVIC_ICER;
+		gc->chip_types[0].chip.irq_mask = irq_gc_mask_disable_reg;
+		gc->chip_types[0].chip.irq_unmask = irq_gc_unmask_enable_reg;
+		gc->chip_types[0].chip.irq_eoi = nvic_eoi;
+	}
+
+	/* Disable all interrupts */
+	for (i = 0; i < irqs; i += 32)
+		writel_relaxed(~0, nvic_base + NVIC_ICER + i * 4 / 32);

So this is another, slightly different loop than the previous one

drivers/irqchip/irq-nvic.c line 95

Quoted 1 line
drivers/irqchip/irq-nvic.c new file +1 -0
+	for (i = 0; i < numbanks; ++i) {

This time based on irqs and increasing the irq number per loop by a full bank. Why not doing this in the above loop which does exaclty the same and you don't have to do the odd register base math. A simple

	writel_relaxed(~0, gc->reg_base + NVIC_ICER);

in the banks loop is sufficient, right?

Thanks,

tglx