summaryrefslogtreecommitdiffstats
path: root/target/linux/mvebu/patches-3.10/0075-irqchip-armada-370-xp-implement-MSI-support.patch
diff options
context:
space:
mode:
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.patch270
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;