Last active
August 29, 2015 14:27
-
-
Save pelwell/8ad7c6710eed7d44ab41 to your computer and use it in GitHub Desktop.
BCM2708: Use upstream interrupt driver on all Pi1's (Take 2)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From f27eee8d093a553d7249a9d8e4231f1f0f781c6e Mon Sep 17 00:00:00 2001 | |
From: Phil Elwell <[email protected]> | |
Date: Wed, 19 Aug 2015 08:49:11 +0100 | |
Subject: [PATCH] BCM2708: Use upstream interrupt driver on all Pi1's | |
Although the aim is to delete the old armctrl driver, that can't happen | |
while non-DT configurations are still supported. This commit enables | |
use of the new FIQ-enabled upstream irqchip driver when DT is enabled | |
on all BCM2835-based RPi platforms (Models A, B, A+, B+ & CM). | |
BCM2836-based platforms (Pi 2) will get the same treatment at a later | |
date, unless non-DT support has already been withdrawn. | |
--- | |
arch/arm/Kconfig | 1 + | |
arch/arm/boot/dts/bcm2708.dtsi | 4 ++ | |
arch/arm/boot/dts/bcm2708_common.dtsi | 2 +- | |
arch/arm/mach-bcm2708/armctrl.c | 68 ++++++++++++++++++++++++++++ | |
arch/arm/mach-bcm2708/bcm2708.c | 6 ++- | |
drivers/irqchip/Makefile | 1 + | |
drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 5 +- | |
7 files changed, 84 insertions(+), 3 deletions(-) | |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig | |
index 10fede1..8d35327 100644 | |
--- a/arch/arm/Kconfig | |
+++ b/arch/arm/Kconfig | |
@@ -330,6 +330,7 @@ config ARCH_BCM2708 | |
select GENERIC_CLOCKEVENTS | |
select ARM_ERRATA_411920 | |
select MACH_BCM2708 | |
+ select MULTI_IRQ_HANDLER | |
select VC4 | |
select FIQ | |
help | |
diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi | |
index 57d4c56..b5b54ce 100644 | |
--- a/arch/arm/boot/dts/bcm2708.dtsi | |
+++ b/arch/arm/boot/dts/bcm2708.dtsi | |
@@ -24,3 +24,7 @@ | |
}; | |
}; | |
}; | |
+ | |
+&intc { | |
+ compatible = "brcm,bcm2835-armctrl-ic"; | |
+}; | |
diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi | |
index f096f45..0420ebcb 100644 | |
--- a/arch/arm/boot/dts/bcm2708_common.dtsi | |
+++ b/arch/arm/boot/dts/bcm2708_common.dtsi | |
@@ -65,7 +65,7 @@ | |
brcm,dma-channel-mask = <0x0f35>; | |
}; | |
- intc: interrupt-controller { | |
+ intc: interrupt-controller@7e00b200 { | |
compatible = "brcm,bcm2708-armctrl-ic"; | |
reg = <0x7e00b200 0x200>; | |
interrupt-controller; | |
diff --git a/arch/arm/mach-bcm2708/armctrl.c b/arch/arm/mach-bcm2708/armctrl.c | |
index 0429225..16c6746 100644 | |
--- a/arch/arm/mach-bcm2708/armctrl.c | |
+++ b/arch/arm/mach-bcm2708/armctrl.c | |
@@ -26,10 +26,22 @@ | |
#include <linux/irqdomain.h> | |
#include <linux/of.h> | |
+#include <asm/exception.h> | |
#include <asm/mach/irq.h> | |
#include <mach/hardware.h> | |
#include "armctrl.h" | |
+/* Mask out shortcut interrupts where they also appear in the regular bank */ | |
+#define BANK0_HWIRQ 0x001ffcff | |
+#define BANK1_HWIRQ BIT(8) | |
+#define BANK2_HWIRQ BIT(9) | |
+#define BANK0_VALID_MASK \ | |
+ (BANK0_HWIRQ + BANK1_HWIRQ + BANK2_HWIRQ) | |
+#define BANK1_VALID_MASK \ | |
+ (~(BIT(7) | BIT(9) | BIT(10) | BIT(18) | BIT(19))) | |
+#define BANK2_VALID_MASK \ | |
+ (~(BIT(21) | BIT(22) | BIT(23) | BIT(24) | BIT(25) | BIT(30))) | |
+ | |
/* For support of kernels >= 3.0 assume only one VIC for now*/ | |
static unsigned int remap_irqs[(INTERRUPT_ARASANSDIO + 1) - INTERRUPT_JPEG] = { | |
INTERRUPT_VC_JPEG, | |
@@ -285,6 +297,59 @@ static struct irq_chip armctrl_chip = { | |
.irq_set_wake = armctrl_set_wake, | |
}; | |
+#ifdef CONFIG_MULTI_IRQ_HANDLER | |
+ | |
+static void __exception_irq_entry armctrl_handle_irq( | |
+ struct pt_regs *regs) | |
+{ | |
+ u32 stat; | |
+ | |
+ while ((stat = readl_relaxed(__io_address(ARM_IRQ_PEND0)) & | |
+ BANK0_VALID_MASK)) { | |
+ u32 stat2; | |
+ u32 irq; | |
+ | |
+ if (stat & BANK0_HWIRQ) { | |
+ irq = ARM_IRQ0_BASE + ffs(stat & BANK0_HWIRQ) - 1; | |
+ } else if (stat & BANK1_HWIRQ) { | |
+ stat2 = readl_relaxed(__io_address(ARM_IRQ_PEND1)) & | |
+ BANK1_VALID_MASK; | |
+ if (stat2) | |
+ irq = ARM_IRQ1_BASE + | |
+ ffs(stat2 & BANK1_VALID_MASK) - 1; | |
+ else | |
+ continue; | |
+ } else if (stat & BANK2_HWIRQ) { | |
+ stat2 = readl_relaxed(__io_address(ARM_IRQ_PEND2)) & | |
+ BANK2_VALID_MASK; | |
+ if (stat2) | |
+ irq = ARM_IRQ2_BASE + | |
+ ffs(stat2 & BANK2_VALID_MASK) - 1; | |
+ else | |
+ continue; | |
+ } else { | |
+ BUG(); | |
+ } | |
+ | |
+ handle_IRQ(irq, regs); | |
+ } | |
+} | |
+ | |
+/* This function forces the interrupt numbers to be allocated sequentially, | |
+ * instead of with gaps due to the sparse BANK0, to make the offset from | |
+ * IRQs and FIQs constant (and equal to FIQ_START). | |
+ */ | |
+unsigned int arch_dynirq_lower_bound(unsigned int from) | |
+{ | |
+ if (from < 24) | |
+ return from + 24; | |
+ else if (from >= 104) | |
+ return from - 24; | |
+ return from; | |
+} | |
+ | |
+#endif | |
+ | |
/** | |
* armctrl_init - initialise a vectored interrupt controller | |
* @base: iomem base address | |
@@ -308,6 +373,9 @@ int __init armctrl_init(void __iomem * base, unsigned int irq_start, | |
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | |
} | |
+#ifdef CONFIG_MULTI_IRQ_HANDLER | |
+ set_handle_irq(armctrl_handle_irq); | |
+#endif | |
armctrl_pm_register(base, irq_start, resume_sources); | |
init_FIQ(FIQ_START); | |
armctrl_dt_init(); | |
diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c | |
index 39cb7bc..5ad4826 100644 | |
--- a/arch/arm/mach-bcm2708/bcm2708.c | |
+++ b/arch/arm/mach-bcm2708/bcm2708.c | |
@@ -25,6 +25,7 @@ | |
#include <linux/platform_device.h> | |
#include <linux/syscore_ops.h> | |
#include <linux/interrupt.h> | |
+#include <linux/irqchip.h> | |
#include <linux/amba/bus.h> | |
#include <linux/amba/clcd.h> | |
#include <linux/clk-provider.h> | |
@@ -101,7 +102,10 @@ static void __init bcm2708_init_led(void); | |
void __init bcm2708_init_irq(void) | |
{ | |
- armctrl_init(__io_address(ARMCTRL_IC_BASE), 0, 0, 0); | |
+ if (of_have_populated_dt()) | |
+ irqchip_init(); | |
+ else | |
+ armctrl_init(__io_address(ARMCTRL_IC_BASE), 0, 0, 0); | |
} | |
static struct map_desc bcm2708_io_desc[] __initdata = { | |
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile | |
index b8d4e96..e5e2447 100644 | |
--- a/drivers/irqchip/Makefile | |
+++ b/drivers/irqchip/Makefile | |
@@ -1,6 +1,7 @@ | |
obj-$(CONFIG_IRQCHIP) += irqchip.o | |
obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o | |
+obj-$(CONFIG_ARCH_BCM2708) += irq-bcm2835.o | |
obj-$(CONFIG_ARCH_EXYNOS) += exynos-combiner.o | |
obj-$(CONFIG_ARCH_HIP04) += irq-hip04.o | |
obj-$(CONFIG_ARCH_MMP) += irq-mmp.o | |
diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | |
index 5c83309..7d9e82d 100644 | |
--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | |
+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | |
@@ -448,7 +448,10 @@ static void hcd_init_fiq(void *cookie) | |
#ifdef CONFIG_ARCH_BCM2835 | |
enable_fiq(platform_get_irq(otg_dev->os_dep.platformdev, 1)); | |
#else | |
- enable_fiq(INTERRUPT_VC_USB); | |
+ if (otg_dev->os_dep.platformdev->dev.of_node) | |
+ enable_fiq(platform_get_irq(otg_dev->os_dep.platformdev, 1)); | |
+ else | |
+ enable_fiq(INTERRUPT_VC_USB); | |
#endif | |
local_fiq_enable(); | |
} | |
-- | |
1.9.1 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment