Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d0e3a971 authored by Thomas Gleixner's avatar Thomas Gleixner
Browse files

Merge tag 'irqchip-mvebu-3.15' of git://git.infradead.org/linux-mvebu into irq/core



irqchip mvebu changes for v3.15

 - armada-370-xp
    - add MSI helper
    - MPIC chained handler

Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parents b04c644e bc69b8ad
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
Marvell Armada 370 and Armada XP Interrupt Controller
Marvell Armada 370, 375, 38x, XP Interrupt Controller
-----------------------------------------------------

Required properties:
@@ -16,7 +16,13 @@ Required properties:
  automatically map to the interrupt controller registers of the
  current CPU)

Optional properties:

- interrupts: If defined, then it indicates that this MPIC is
  connected as a slave to another interrupt controller. This is
  typically the case on Armada 375 and Armada 38x, where the MPIC is
  connected as a slave to the Cortex-A9 GIC. The provided interrupt
  indicate to which GIC interrupt the MPIC output is connected.

Example:

+69 −27
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/io.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
@@ -42,6 +43,7 @@
#define ARMADA_370_XP_INT_SOURCE_CTL(irq)	(0x100 + irq*4)

#define ARMADA_370_XP_CPU_INTACK_OFFS		(0x44)
#define ARMADA_375_PPI_CAUSE			(0x10)

#define ARMADA_370_XP_SW_TRIG_INT_OFFS           (0x4)
#define ARMADA_370_XP_IN_DRBEL_MSK_OFFS          (0xc)
@@ -352,29 +354,9 @@ static struct irq_domain_ops armada_370_xp_mpic_irq_ops = {
	.xlate = irq_domain_xlate_onecell,
};

static asmlinkage void __exception_irq_entry
armada_370_xp_handle_irq(struct pt_regs *regs)
{
	u32 irqstat, irqnr;

	do {
		irqstat = readl_relaxed(per_cpu_int_base +
					ARMADA_370_XP_CPU_INTACK_OFFS);
		irqnr = irqstat & 0x3FF;

		if (irqnr > 1022)
			break;

		if (irqnr > 1) {
			irqnr =	irq_find_mapping(armada_370_xp_mpic_domain,
					irqnr);
			handle_IRQ(irqnr, regs);
			continue;
		}

#ifdef CONFIG_PCI_MSI
		/* MSI handling */
		if (irqnr == 1) {
static void armada_370_xp_handle_msi_irq(struct pt_regs *regs, bool is_chained)
{
	u32 msimask, msinr;

	msimask = readl_relaxed(per_cpu_int_base +
@@ -393,11 +375,65 @@ armada_370_xp_handle_irq(struct pt_regs *regs)

		irq = irq_find_mapping(armada_370_xp_msi_domain,
				       msinr - 16);

		if (is_chained)
			generic_handle_irq(irq);
		else
			handle_IRQ(irq, regs);
	}
}
#else
static void armada_370_xp_handle_msi_irq(struct pt_regs *r, bool b) {}
#endif

static void armada_370_xp_mpic_handle_cascade_irq(unsigned int irq,
						  struct irq_desc *desc)
{
	struct irq_chip *chip = irq_get_chip(irq);
	unsigned long irqmap, irqn;
	unsigned int cascade_irq;

	chained_irq_enter(chip, desc);

	irqmap = readl_relaxed(per_cpu_int_base + ARMADA_375_PPI_CAUSE);

	if (irqmap & BIT(0)) {
		armada_370_xp_handle_msi_irq(NULL, true);
		irqmap &= ~BIT(0);
	}

	for_each_set_bit(irqn, &irqmap, BITS_PER_LONG) {
		cascade_irq = irq_find_mapping(armada_370_xp_mpic_domain, irqn);
		generic_handle_irq(cascade_irq);
	}

	chained_irq_exit(chip, desc);
}

static asmlinkage void __exception_irq_entry
armada_370_xp_handle_irq(struct pt_regs *regs)
{
	u32 irqstat, irqnr;

	do {
		irqstat = readl_relaxed(per_cpu_int_base +
					ARMADA_370_XP_CPU_INTACK_OFFS);
		irqnr = irqstat & 0x3FF;

		if (irqnr > 1022)
			break;

		if (irqnr > 1) {
			irqnr =	irq_find_mapping(armada_370_xp_mpic_domain,
					irqnr);
			handle_IRQ(irqnr, regs);
			continue;
		}

		/* MSI handling */
		if (irqnr == 1)
			armada_370_xp_handle_msi_irq(regs, false);

#ifdef CONFIG_SMP
		/* IPI Handling */
		if (irqnr == 0) {
@@ -427,6 +463,7 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
					     struct device_node *parent)
{
	struct resource main_int_res, per_cpu_int_res;
	int parent_irq;
	u32 control;

	BUG_ON(of_address_to_resource(node, 0, &main_int_res));
@@ -455,8 +492,6 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,

	BUG_ON(!armada_370_xp_mpic_domain);

	irq_set_default_host(armada_370_xp_mpic_domain);

#ifdef CONFIG_SMP
	armada_xp_mpic_smp_cpu_init();

@@ -472,7 +507,14 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,

	armada_370_xp_msi_init(node, main_int_res.start);

	parent_irq = irq_of_parse_and_map(node, 0);
	if (parent_irq <= 0) {
		irq_set_default_host(armada_370_xp_mpic_domain);
		set_handle_irq(armada_370_xp_handle_irq);
	} else {
		irq_set_chained_handler(parent_irq,
					armada_370_xp_mpic_handle_cascade_irq);
	}

	return 0;
}