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/d41ec7fb7db4d1136eb5 to your computer and use it in GitHub Desktop.
Save pelwell/d41ec7fb7db4d1136eb5 to your computer and use it in GitHub Desktop.
BCM2708: Use upstream interrupt driver on all Pi1's
From 104951f582f52e7b391b4bcea3ebaa13e28a7a8a 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 | 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