From b81137bc437c969465a070dfbced506d981efd12 Mon Sep 17 00:00:00 2001 From: Brandon Perez Date: Tue, 14 Jul 2015 11:07:24 -0400 Subject: [PATCH 2/6] This commit enables the kernel to accept a static crossbar mapping from the bootloader, where the mapping of peripherals to IRQ lines is handled by the bootloader. Due to the large number of peripheral interrupts on the J6/DRA72x boards, there is a crossbar to route peripheral devices to SPI lines on the GIC. Normally, the mapping and configuration of the crossbar registers (which perform the mapping) is handled in a pseudo-dynamic manner by the kernel. The kernel maps interrupts from devices as drivers request the interrupts from the kernel. Naturally, with a given configuration, the mapping is always the same (and thus static), but this allows for flexibility with adding and removing devices. Due to the difficultly of performing this pseudo-dynamic mapping while the kernel is virtualized by Xen, a static mapping is used. In this case, the kernel does not attempt to map IRQ's, and simply discovers the crossbar configuration from the registers. This feature is enabled by CONFIG_DRA7_CROSSBAR_STATIC_MAPPING. For now, this is simply present in the irqchip.c file, but will eventually be integrated as a full config option. --- arch/arm/boot/dts/dra7.dtsi | 1 + drivers/irqchip/irq-crossbar.c | 36 ++++++++++++++++++++++++------------ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index 6b69496..0f99bfa 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -384,6 +384,7 @@ uart1: serial@4806a000 { compatible = "ti,omap4-uart"; reg = <0x4806a000 0x100>; + interrupts = ; interrupts-extended = <&gic GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; ti,hwmods = "uart1"; clock-frequency = <48000000>; diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c index 85c2985..4d58650 100644 --- a/drivers/irqchip/irq-crossbar.c +++ b/drivers/irqchip/irq-crossbar.c @@ -22,6 +22,9 @@ #define IRQ_SKIP -3 #define GIC_IRQ_START 32 +// FIXME: +#define CONFIG_DRA7_CROSSBAR_STATIC_MAPPING + /** * struct crossbar_device - crossbar device description * @int_max: maximum number of supported interrupts @@ -100,10 +103,11 @@ static inline bool needs_crossbar_write(irq_hw_number_t hw) static int crossbar_domain_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) { - if (needs_crossbar_write(hw)) - cb->write(hw - GIC_IRQ_START, cb->irq_map[hw - GIC_IRQ_START]); - - return 0; +#ifndef CONFIG_DRA7_CROSSBAR_STATIC_MAPPING + if (needs_crossbar_write(hw)) + cb->write(hw - GIC_IRQ_START, cb->irq_map[hw - GIC_IRQ_START]); +#endif + return 0; } /** @@ -284,14 +288,22 @@ static int __init crossbar_of_init(struct device_node *node) } of_property_read_u32(node, "ti,irqs-safe-map", &cb->safe_map); - /* Initialize the crossbar with safe map to start with */ - for (i = 0; i < max; i++) { - if (cb->irq_map[i] == IRQ_RESERVED || - cb->irq_map[i] == IRQ_SKIP) - continue; - - cb->write(i, cb->safe_map); - } +#ifndef CONFIG_DRA7_CROSSBAR_STATIC_MAPPING + /* Initialize the crossbar with safe map to start with */ + for (i = 0; i < max; i++) { + if (cb->irq_map[i] == IRQ_RESERVED || cb->irq_map[i] == IRQ_SKIP) + continue; + + cb->write(i, cb->safe_map); + } +#else + // Override the mapping with the default mapping given by the bootloader + for (i = 0; i < max; i++) { + if (cb->irq_map[i] != IRQ_RESERVED) { + cb->irq_map[i] = readw(cb->crossbar_base + cb->register_offsets[i]); + } + } +#endif register_routable_domain_ops(&routable_irq_domain_ops); return 0; -- 1.7.9.5