From c24a8a7a99885d5b986f38f6631f69e7794a3e5e Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Sat, 21 Dec 2013 16:52:13 +0530 Subject: MIPS: Netlogic: Add MSI support for XLP Add MSI chip and MSIX chip definitions. For MSI, we map the link interrupt to a MSI link IRQ which will do a second level of dispatch based on the MSI status register. The MSI chip definitions use the MSI enable register to enable and disable the MSI irqs. For MSI-X, we split the 32 available MSI-X vectors across the four PCIe links (8 each). These PIC interrupts generate an IRQ per link which uses a second level dispatch as well. The MSI-X chip definition uses the standard functions to enable and disable interrupts. Signed-off-by: Jayachandran C Signed-off-by: John Crispin Patchwork: http://patchwork.linux-mips.org/patch/6270/ --- arch/mips/netlogic/common/irq.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) (limited to 'arch/mips/netlogic/common/irq.c') diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c index 1c7e3a1b81ab..3800bf6551ab 100644 --- a/arch/mips/netlogic/common/irq.c +++ b/arch/mips/netlogic/common/irq.c @@ -180,6 +180,7 @@ static void __init nlm_init_percpu_irqs(void) #endif } + void nlm_setup_pic_irq(int node, int picirq, int irq, int irt) { struct nlm_pic_irq *pic_data; @@ -207,24 +208,24 @@ void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *)) static void nlm_init_node_irqs(int node) { - int i, irt; - uint64_t irqmask; struct nlm_soc_info *nodep; + int i, irt; pr_info("Init IRQ for node %d\n", node); nodep = nlm_get_node(node); - irqmask = PERCPU_IRQ_MASK; + nodep->irqmask = PERCPU_IRQ_MASK; for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ; i++) { irt = nlm_irq_to_irt(i); - if (irt == -1) + if (irt == -1) /* unused irq */ continue; - nlm_setup_pic_irq(node, i, i, irt); - /* set interrupts to first cpu in node */ + nodep->irqmask |= 1ull << i; + if (irt == -2) /* not a direct PIC irq */ + continue; + nlm_pic_init_irt(nodep->picbase, irt, i, node * NLM_CPUS_PER_NODE, 0); - irqmask |= (1ull << i); + nlm_setup_pic_irq(node, i, i, irt); } - nodep->irqmask = irqmask; } void nlm_smp_irq_init(int hwcpuid) @@ -256,6 +257,18 @@ asmlinkage void plat_irq_dispatch(void) return; } +#if defined(CONFIG_PCI_MSI) && defined(CONFIG_CPU_XLP) + /* PCI interrupts need a second level dispatch for MSI bits */ + if (i >= PIC_PCIE_LINK_MSI_IRQ(0) && i <= PIC_PCIE_LINK_MSI_IRQ(3)) { + nlm_dispatch_msi(node, i); + return; + } + if (i >= PIC_PCIE_MSIX_IRQ(0) && i <= PIC_PCIE_MSIX_IRQ(3)) { + nlm_dispatch_msix(node, i); + return; + } + +#endif /* top level irq handling */ do_IRQ(nlm_irq_to_xirq(node, i)); } -- cgit v1.2.3 From 98d4884ca55883e8b16180bd969a8bccaa885c80 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Sat, 21 Dec 2013 16:52:26 +0530 Subject: MIPS: Netlogic: Add cpu to node mapping for XLP9XX XLP9XX has 20 cores per node, opposed to 8 on earlier XLP8XX. Update code that calculates node id from cpu id to handle this. Signed-off-by: Jayachandran C Signed-off-by: John Crispin Patchwork: http://patchwork.linux-mips.org/patch/6283/ --- arch/mips/netlogic/common/irq.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/mips/netlogic/common/irq.c') diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c index 3800bf6551ab..8092bb320618 100644 --- a/arch/mips/netlogic/common/irq.c +++ b/arch/mips/netlogic/common/irq.c @@ -223,7 +223,7 @@ static void nlm_init_node_irqs(int node) continue; nlm_pic_init_irt(nodep->picbase, irt, i, - node * NLM_CPUS_PER_NODE, 0); + node * nlm_threads_per_node(), 0); nlm_setup_pic_irq(node, i, i, irt); } } @@ -232,8 +232,8 @@ void nlm_smp_irq_init(int hwcpuid) { int node, cpu; - node = hwcpuid / NLM_CPUS_PER_NODE; - cpu = hwcpuid % NLM_CPUS_PER_NODE; + node = nlm_cpuid_to_node(hwcpuid); + cpu = hwcpuid % nlm_threads_per_node(); if (cpu == 0 && node != 0) nlm_init_node_irqs(node); -- cgit v1.2.3 From 5fcbdf7cac23fd07f9de30eab760d3a5864f7330 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Sat, 21 Dec 2013 16:52:29 +0530 Subject: MIPS: Netlogic: XLP9XX PIC OF support Support for adding legacy IRQ domain for XLP9XX. The node id of the PIC has to be calulated differently for XLP9XX. Signed-off-by: Jayachandran C Signed-off-by: John Crispin Patchwork: http://patchwork.linux-mips.org/patch/6286/ --- arch/mips/netlogic/common/irq.c | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) (limited to 'arch/mips/netlogic/common/irq.c') diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c index 8092bb320618..5afc4b7fce0f 100644 --- a/arch/mips/netlogic/common/irq.c +++ b/arch/mips/netlogic/common/irq.c @@ -274,8 +274,6 @@ asmlinkage void plat_irq_dispatch(void) } #ifdef CONFIG_OF -static struct irq_domain *xlp_pic_domain; - static const struct irq_domain_ops xlp_pic_irq_domain_ops = { .xlate = irq_domain_xlate_onetwocell, }; @@ -284,8 +282,9 @@ static int __init xlp_of_pic_init(struct device_node *node, struct device_node *parent) { const int n_picirqs = PIC_IRT_LAST_IRQ - PIC_IRQ_BASE + 1; + struct irq_domain *xlp_pic_domain; struct resource res; - int socid, ret; + int socid, ret, bus; /* we need a hack to get the PIC's SoC chip id */ ret = of_address_to_resource(node, 0, &res); @@ -293,7 +292,34 @@ static int __init xlp_of_pic_init(struct device_node *node, pr_err("PIC %s: reg property not found!\n", node->name); return -EINVAL; } - socid = (res.start >> 18) & 0x3; + + if (cpu_is_xlp9xx()) { + bus = (res.start >> 20) & 0xf; + for (socid = 0; socid < NLM_NR_NODES; socid++) { + if (!nlm_node_present(socid)) + continue; + if (nlm_get_node(socid)->socbus == bus) + break; + } + if (socid == NLM_NR_NODES) { + pr_err("PIC %s: Node mapping for bus %d not found!\n", + node->name, bus); + return -EINVAL; + } + } else { + socid = (res.start >> 18) & 0x3; + if (!nlm_node_present(socid)) { + pr_err("PIC %s: node %d does not exist!\n", + node->name, socid); + return -EINVAL; + } + } + + if (!nlm_node_present(socid)) { + pr_err("PIC %s: node %d does not exist!\n", node->name, socid); + return -EINVAL; + } + xlp_pic_domain = irq_domain_add_legacy(node, n_picirqs, nlm_irq_to_xirq(socid, PIC_IRQ_BASE), PIC_IRQ_BASE, &xlp_pic_irq_domain_ops, NULL); @@ -301,8 +327,7 @@ static int __init xlp_of_pic_init(struct device_node *node, pr_err("PIC %s: Creating legacy domain failed!\n", node->name); return -EINVAL; } - pr_info("Node %d: IRQ domain created for PIC@%pa\n", socid, - &res.start); + pr_info("Node %d: IRQ domain created for PIC@%pR\n", socid, &res); return 0; } -- cgit v1.2.3