Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pelwell/8ad7c6710eed7d44ab41 to your computer and use it in GitHub Desktop.
Save pelwell/8ad7c6710eed7d44ab41 to your computer and use it in GitHub Desktop.
BCM2708: Use upstream interrupt driver on all Pi1's (Take 2)
From f27eee8d093a553d7249a9d8e4231f1f0f781c6e Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
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