mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	irqchip: mips-gic: Add device-tree support
Add device-tree support for the MIPS GIC. Update the GIC irqdomain's xlate() callback to handle the three-cell specifier described in the MIPS GIC binding document. Signed-off-by: Andrew Bresticker <abrestic@chromium.org> Acked-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Jason Cooper <jason@lakedaemon.net> Cc: Rob Herring <robh+dt@kernel.org> Cc: Pawel Moll <pawel.moll@arm.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Ian Campbell <ijc+devicetree@hellion.org.uk> Cc: Kumar Gala <galak@codeaurora.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Daniel Lezcano <daniel.lezcano@linaro.org> Cc: John Crispin <blogic@openwrt.org> Cc: David Daney <ddaney.cavm@gmail.com> Cc: Qais Yousef <qais.yousef@imgtec.com> Cc: James Hogan <james.hogan@imgtec.com> Cc: linux-mips@linux-mips.org Cc: devicetree@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/8422/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
		
							parent
							
								
									2ff404005e
								
							
						
					
					
						commit
						a7057270c2
					
				
					 1 changed files with 87 additions and 5 deletions
				
			
		| 
						 | 
				
			
			@ -12,12 +12,18 @@
 | 
			
		|||
#include <linux/interrupt.h>
 | 
			
		||||
#include <linux/irq.h>
 | 
			
		||||
#include <linux/irqchip/mips-gic.h>
 | 
			
		||||
#include <linux/of_address.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/smp.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/mips-cm.h>
 | 
			
		||||
#include <asm/setup.h>
 | 
			
		||||
#include <asm/traps.h>
 | 
			
		||||
 | 
			
		||||
#include <dt-bindings/interrupt-controller/mips-gic.h>
 | 
			
		||||
 | 
			
		||||
#include "irqchip.h"
 | 
			
		||||
 | 
			
		||||
unsigned int gic_present;
 | 
			
		||||
 | 
			
		||||
struct gic_pcpu_mask {
 | 
			
		||||
| 
						 | 
				
			
			@ -662,14 +668,34 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
 | 
			
		|||
	return gic_shared_irq_domain_map(d, virq, hw);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int gic_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
 | 
			
		||||
				const u32 *intspec, unsigned int intsize,
 | 
			
		||||
				irq_hw_number_t *out_hwirq,
 | 
			
		||||
				unsigned int *out_type)
 | 
			
		||||
{
 | 
			
		||||
	if (intsize != 3)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	if (intspec[0] == GIC_SHARED)
 | 
			
		||||
		*out_hwirq = GIC_SHARED_TO_HWIRQ(intspec[1]);
 | 
			
		||||
	else if (intspec[0] == GIC_LOCAL)
 | 
			
		||||
		*out_hwirq = GIC_LOCAL_TO_HWIRQ(intspec[1]);
 | 
			
		||||
	else
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct irq_domain_ops gic_irq_domain_ops = {
 | 
			
		||||
	.map = gic_irq_domain_map,
 | 
			
		||||
	.xlate = irq_domain_xlate_twocell,
 | 
			
		||||
	.xlate = gic_irq_domain_xlate,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void __init gic_init(unsigned long gic_base_addr,
 | 
			
		||||
		     unsigned long gic_addrspace_size, unsigned int cpu_vec,
 | 
			
		||||
		     unsigned int irqbase)
 | 
			
		||||
static void __init __gic_init(unsigned long gic_base_addr,
 | 
			
		||||
			      unsigned long gic_addrspace_size,
 | 
			
		||||
			      unsigned int cpu_vec, unsigned int irqbase,
 | 
			
		||||
			      struct device_node *node)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int gicconfig;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -695,7 +721,7 @@ void __init gic_init(unsigned long gic_base_addr,
 | 
			
		|||
					gic_irq_dispatch);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	gic_irq_domain = irq_domain_add_simple(NULL, GIC_NUM_LOCAL_INTRS +
 | 
			
		||||
	gic_irq_domain = irq_domain_add_simple(node, GIC_NUM_LOCAL_INTRS +
 | 
			
		||||
					       gic_shared_intrs, irqbase,
 | 
			
		||||
					       &gic_irq_domain_ops, NULL);
 | 
			
		||||
	if (!gic_irq_domain)
 | 
			
		||||
| 
						 | 
				
			
			@ -705,3 +731,59 @@ void __init gic_init(unsigned long gic_base_addr,
 | 
			
		|||
 | 
			
		||||
	gic_ipi_init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __init gic_init(unsigned long gic_base_addr,
 | 
			
		||||
		     unsigned long gic_addrspace_size,
 | 
			
		||||
		     unsigned int cpu_vec, unsigned int irqbase)
 | 
			
		||||
{
 | 
			
		||||
	__gic_init(gic_base_addr, gic_addrspace_size, cpu_vec, irqbase, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int __init gic_of_init(struct device_node *node,
 | 
			
		||||
			      struct device_node *parent)
 | 
			
		||||
{
 | 
			
		||||
	struct resource res;
 | 
			
		||||
	unsigned int cpu_vec, i = 0, reserved = 0;
 | 
			
		||||
	phys_addr_t gic_base;
 | 
			
		||||
	size_t gic_len;
 | 
			
		||||
 | 
			
		||||
	/* Find the first available CPU vector. */
 | 
			
		||||
	while (!of_property_read_u32_index(node, "mti,reserved-cpu-vectors",
 | 
			
		||||
					   i++, &cpu_vec))
 | 
			
		||||
		reserved |= BIT(cpu_vec);
 | 
			
		||||
	for (cpu_vec = 2; cpu_vec < 8; cpu_vec++) {
 | 
			
		||||
		if (!(reserved & BIT(cpu_vec)))
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	if (cpu_vec == 8) {
 | 
			
		||||
		pr_err("No CPU vectors available for GIC\n");
 | 
			
		||||
		return -ENODEV;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (of_address_to_resource(node, 0, &res)) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * Probe the CM for the GIC base address if not specified
 | 
			
		||||
		 * in the device-tree.
 | 
			
		||||
		 */
 | 
			
		||||
		if (mips_cm_present()) {
 | 
			
		||||
			gic_base = read_gcr_gic_base() &
 | 
			
		||||
				~CM_GCR_GIC_BASE_GICEN_MSK;
 | 
			
		||||
			gic_len = 0x20000;
 | 
			
		||||
		} else {
 | 
			
		||||
			pr_err("Failed to get GIC memory range\n");
 | 
			
		||||
			return -ENODEV;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		gic_base = res.start;
 | 
			
		||||
		gic_len = resource_size(&res);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (mips_cm_present())
 | 
			
		||||
		write_gcr_gic_base(gic_base | CM_GCR_GIC_BASE_GICEN_MSK);
 | 
			
		||||
	gic_present = true;
 | 
			
		||||
 | 
			
		||||
	__gic_init(gic_base, gic_len, cpu_vec, 0, node);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
IRQCHIP_DECLARE(mips_gic, "mti,gic", gic_of_init);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue