diff options
Diffstat (limited to 'target/linux/mvebu/patches-3.10/0075-irqchip-armada-370-xp-implement-MSI-support.patch')
-rw-r--r-- | target/linux/mvebu/patches-3.10/0075-irqchip-armada-370-xp-implement-MSI-support.patch | 270 |
1 files changed, 0 insertions, 270 deletions
diff --git a/target/linux/mvebu/patches-3.10/0075-irqchip-armada-370-xp-implement-MSI-support.patch b/target/linux/mvebu/patches-3.10/0075-irqchip-armada-370-xp-implement-MSI-support.patch deleted file mode 100644 index 999b493c55..0000000000 --- a/target/linux/mvebu/patches-3.10/0075-irqchip-armada-370-xp-implement-MSI-support.patch +++ /dev/null @@ -1,270 +0,0 @@ -From eaa70d53f6b827f147d775a3de7ff3ef27d0fae6 Mon Sep 17 00:00:00 2001 -From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> -Date: Thu, 6 Jun 2013 18:25:16 +0200 -Subject: [PATCH 075/203] irqchip: armada-370-xp: implement MSI support - -This commit introduces the support for the MSI interrupts in the -armada-370-xp interrupt controller driver. It registers an MSI chip to -the MSI chip registry, which will be used by the Marvell PCIe host -controller driver. - -The MSI interrupts use the 16 high doorbells, and are therefore -notified using IRQ1 of the main interrupt controller. - -Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> -Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com> ---- - .../devicetree/bindings/arm/armada-370-xp-mpic.txt | 3 + - drivers/irqchip/irq-armada-370-xp.c | 182 ++++++++++++++++++++- - 2 files changed, 184 insertions(+), 1 deletion(-) - ---- a/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt -+++ b/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt -@@ -4,6 +4,8 @@ Marvell Armada 370 and Armada XP Interru - Required properties: - - compatible: Should be "marvell,mpic" - - interrupt-controller: Identifies the node as an interrupt controller. -+- msi-controller: Identifies the node as an PCI Message Signaled -+ Interrupt controller. - - #interrupt-cells: The number of cells to define the interrupts. Should be 1. - The cell is the IRQ number - -@@ -24,6 +26,7 @@ Example: - #address-cells = <1>; - #size-cells = <1>; - interrupt-controller; -+ msi-controller; - reg = <0xd0020a00 0x1d0>, - <0xd0021070 0x58>; - }; ---- a/drivers/irqchip/irq-armada-370-xp.c -+++ b/drivers/irqchip/irq-armada-370-xp.c -@@ -21,7 +21,10 @@ - #include <linux/io.h> - #include <linux/of_address.h> - #include <linux/of_irq.h> -+#include <linux/of_pci.h> - #include <linux/irqdomain.h> -+#include <linux/slab.h> -+#include <linux/msi.h> - #include <asm/mach/arch.h> - #include <asm/exception.h> - #include <asm/smp_plat.h> -@@ -51,12 +54,22 @@ - #define IPI_DOORBELL_START (0) - #define IPI_DOORBELL_END (8) - #define IPI_DOORBELL_MASK 0xFF -+#define PCI_MSI_DOORBELL_START (16) -+#define PCI_MSI_DOORBELL_NR (16) -+#define PCI_MSI_DOORBELL_END (32) -+#define PCI_MSI_DOORBELL_MASK 0xFFFF0000 - - static DEFINE_RAW_SPINLOCK(irq_controller_lock); - - static void __iomem *per_cpu_int_base; - static void __iomem *main_int_base; - static struct irq_domain *armada_370_xp_mpic_domain; -+#ifdef CONFIG_PCI_MSI -+static struct irq_domain *armada_370_xp_msi_domain; -+static DECLARE_BITMAP(msi_used, PCI_MSI_DOORBELL_NR); -+static DEFINE_MUTEX(msi_used_lock); -+static phys_addr_t msi_doorbell_addr; -+#endif - - /* - * In SMP mode: -@@ -87,6 +100,144 @@ static void armada_370_xp_irq_unmask(str - ARMADA_370_XP_INT_CLEAR_MASK_OFFS); - } - -+#ifdef CONFIG_PCI_MSI -+ -+static int armada_370_xp_alloc_msi(void) -+{ -+ int hwirq; -+ -+ mutex_lock(&msi_used_lock); -+ hwirq = find_first_zero_bit(&msi_used, PCI_MSI_DOORBELL_NR); -+ if (hwirq >= PCI_MSI_DOORBELL_NR) -+ hwirq = -ENOSPC; -+ else -+ set_bit(hwirq, msi_used); -+ mutex_unlock(&msi_used_lock); -+ -+ return hwirq; -+} -+ -+static void armada_370_xp_free_msi(int hwirq) -+{ -+ mutex_lock(&msi_used_lock); -+ if (!test_bit(hwirq, msi_used)) -+ pr_err("trying to free unused MSI#%d\n", hwirq); -+ else -+ clear_bit(hwirq, msi_used); -+ mutex_unlock(&msi_used_lock); -+} -+ -+static int armada_370_xp_setup_msi_irq(struct msi_chip *chip, -+ struct pci_dev *pdev, -+ struct msi_desc *desc) -+{ -+ struct msi_msg msg; -+ irq_hw_number_t hwirq; -+ int virq; -+ -+ hwirq = armada_370_xp_alloc_msi(); -+ if (hwirq < 0) -+ return hwirq; -+ -+ virq = irq_create_mapping(armada_370_xp_msi_domain, hwirq); -+ if (!virq) { -+ armada_370_xp_free_msi(hwirq); -+ return -EINVAL; -+ } -+ -+ irq_set_msi_desc(virq, desc); -+ -+ msg.address_lo = msi_doorbell_addr; -+ msg.address_hi = 0; -+ msg.data = 0xf00 | (hwirq + 16); -+ -+ write_msi_msg(virq, &msg); -+ return 0; -+} -+ -+static void armada_370_xp_teardown_msi_irq(struct msi_chip *chip, -+ unsigned int irq) -+{ -+ struct irq_data *d = irq_get_irq_data(irq); -+ irq_dispose_mapping(irq); -+ armada_370_xp_free_msi(d->hwirq); -+} -+ -+static struct irq_chip armada_370_xp_msi_irq_chip = { -+ .name = "armada_370_xp_msi_irq", -+ .irq_enable = unmask_msi_irq, -+ .irq_disable = mask_msi_irq, -+ .irq_mask = mask_msi_irq, -+ .irq_unmask = unmask_msi_irq, -+}; -+ -+static int armada_370_xp_msi_map(struct irq_domain *domain, unsigned int virq, -+ irq_hw_number_t hw) -+{ -+ irq_set_chip_and_handler(virq, &armada_370_xp_msi_irq_chip, -+ handle_simple_irq); -+ set_irq_flags(virq, IRQF_VALID); -+ -+ return 0; -+} -+ -+static const struct irq_domain_ops armada_370_xp_msi_irq_ops = { -+ .map = armada_370_xp_msi_map, -+}; -+ -+static int armada_370_xp_msi_init(struct device_node *node, -+ phys_addr_t main_int_phys_base) -+{ -+ struct msi_chip *msi_chip; -+ u32 reg; -+ int ret; -+ -+ msi_doorbell_addr = main_int_phys_base + -+ ARMADA_370_XP_SW_TRIG_INT_OFFS; -+ -+ msi_chip = kzalloc(sizeof(*msi_chip), GFP_KERNEL); -+ if (!msi_chip) -+ return -ENOMEM; -+ -+ msi_chip->setup_irq = armada_370_xp_setup_msi_irq; -+ msi_chip->teardown_irq = armada_370_xp_teardown_msi_irq; -+ msi_chip->of_node = node; -+ -+ armada_370_xp_msi_domain = -+ irq_domain_add_linear(NULL, PCI_MSI_DOORBELL_NR, -+ &armada_370_xp_msi_irq_ops, -+ NULL); -+ if (!armada_370_xp_msi_domain) { -+ kfree(msi_chip); -+ return -ENOMEM; -+ } -+ -+ ret = of_pci_msi_chip_add(msi_chip); -+ if (ret < 0) { -+ irq_domain_remove(armada_370_xp_msi_domain); -+ kfree(msi_chip); -+ return ret; -+ } -+ -+ reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS) -+ | PCI_MSI_DOORBELL_MASK; -+ -+ writel(reg, per_cpu_int_base + -+ ARMADA_370_XP_IN_DRBEL_MSK_OFFS); -+ -+ /* Unmask IPI interrupt */ -+ writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); -+ -+ return 0; -+} -+#else -+static inline int armada_370_xp_msi_init(struct device_node *node, -+ phys_addr_t main_int_phys_base) -+{ -+ return 0; -+} -+#endif -+ - #ifdef CONFIG_SMP - static int armada_xp_set_affinity(struct irq_data *d, - const struct cpumask *mask_val, bool force) -@@ -214,12 +365,39 @@ armada_370_xp_handle_irq(struct pt_regs - if (irqnr > 1022) - break; - -- if (irqnr > 0) { -+ 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) { -+ u32 msimask, msinr; -+ -+ msimask = readl_relaxed(per_cpu_int_base + -+ ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS) -+ & PCI_MSI_DOORBELL_MASK; -+ -+ writel(~PCI_MSI_DOORBELL_MASK, per_cpu_int_base + -+ ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS); -+ -+ for (msinr = PCI_MSI_DOORBELL_START; -+ msinr < PCI_MSI_DOORBELL_END; msinr++) { -+ int irq; -+ -+ if (!(msimask & BIT(msinr))) -+ continue; -+ -+ irq = irq_find_mapping(armada_370_xp_msi_domain, -+ msinr - 16); -+ handle_IRQ(irq, regs); -+ } -+ } -+#endif -+ - #ifdef CONFIG_SMP - /* IPI Handling */ - if (irqnr == 0) { -@@ -292,6 +470,8 @@ static int __init armada_370_xp_mpic_of_ - - #endif - -+ armada_370_xp_msi_init(node, main_int_res.start); -+ - set_handle_irq(armada_370_xp_handle_irq); - - return 0; |