diff options
Diffstat (limited to 'arch/mips/netlogic/common/irq.c')
| -rw-r--r-- | arch/mips/netlogic/common/irq.c | 74 | 
1 files changed, 57 insertions, 17 deletions
diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c index 1c7e3a1b81a..c100b9afa0a 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; @@ -202,37 +203,39 @@ void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *))  	xirq = nlm_irq_to_xirq(node, irq);  	pic_data = irq_get_handler_data(xirq); +	if (WARN_ON(!pic_data)) +		return;  	pic_data->extra_ack = xack;  }  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); +				node * nlm_threads_per_node(), 0); +		nlm_setup_pic_irq(node, i, i, irt);  	} -	nodep->irqmask = irqmask;  }  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); @@ -256,13 +259,23 @@ 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));  }  #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,  }; @@ -271,8 +284,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); @@ -280,7 +294,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); @@ -288,8 +329,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;  }  | 
