Created
August 19, 2015 08:26
-
-
Save pelwell/d41ec7fb7db4d1136eb5 to your computer and use it in GitHub Desktop.
BCM2708: Use upstream interrupt driver on all Pi1's
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 104951f582f52e7b391b4bcea3ebaa13e28a7a8a 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 | 55 ++++++++++++++++++++++++++++ | |
arch/arm/mach-bcm2708/bcm2708.c | 6 ++- | |
drivers/irqchip/Makefile | 1 + | |
drivers/irqchip/irq-bcm2835.c | 3 +- | |
drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 9 +++-- | |
8 files changed, 73 insertions(+), 8 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 d1c3bdf..4077eae 100644 | |
--- a/arch/arm/boot/dts/bcm2708_common.dtsi | |
+++ b/arch/arm/boot/dts/bcm2708_common.dtsi | |
@@ -66,7 +66,7 @@ | |
brcm,dma-channel-mask = <0x7f35>; | |
}; | |
- 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..d98c7d0 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,46 @@ 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); | |
+ } | |
+} | |
+ | |
+#endif | |
+ | |
/** | |
* armctrl_init - initialise a vectored interrupt controller | |
* @base: iomem base address | |
@@ -308,6 +360,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/irqchip/irq-bcm2835.c b/drivers/irqchip/irq-bcm2835.c | |
index b1178d4..31b3f7c 100644 | |
--- a/drivers/irqchip/irq-bcm2835.c | |
+++ b/drivers/irqchip/irq-bcm2835.c | |
@@ -78,7 +78,6 @@ | |
#define NR_BANKS 3 | |
#define IRQS_PER_BANK 32 | |
#define NUMBER_IRQS MAKE_HWIRQ(NR_BANKS, 0) | |
-#define FIQ_START (NR_IRQS_BANK0 + MAKE_HWIRQ(NR_BANKS - 1, 0)) | |
static int reg_pending[] __initconst = { 0x00, 0x04, 0x08 }; | |
static int reg_enable[] __initconst = { 0x18, 0x10, 0x14 }; | |
@@ -209,7 +208,7 @@ static int __init armctrl_of_init(struct device_node *node, | |
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | |
} | |
} | |
- init_FIQ(FIQ_START); | |
+ init_FIQ(NUMBER_IRQS); | |
return 0; | |
} | |
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..ca671b7 100644 | |
--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | |
+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | |
@@ -444,12 +444,13 @@ static void hcd_init_fiq(void *cookie) | |
else | |
DWC_WARN("MPHI periph has NOT been enabled"); | |
#endif | |
+#ifdef CONFIG_MULTI_IRQ_HANDLER | |
// Enable FIQ interrupt from USB peripheral | |
-#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 | |
#endif | |
+ enable_fiq(INTERRUPT_VC_USB); | |
local_fiq_enable(); | |
} | |
-- | |
1.9.1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment