aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/brcm2708/patches-4.14/950-0169-irqchip-irq-bcm2836-Remove-regmap-and-syscon-use.patch
blob: cfc48364ff483ef0a265fea252b727e4d13bd693 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
From bb79a484a01f8f3645bd9b8fc6b15ea0ba961589 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Tue, 23 Jan 2018 16:52:45 +0000
Subject: [PATCH 169/454] irqchip: irq-bcm2836: Remove regmap and syscon use

The syscon node defines a register range that duplicates that used by
the local_intc node on bcm2836/7. Since irq-bcm2835 and irq-bcm2836 are
built in and always present together (both drivers are enabled by
CONFIG_ARCH_BCM2835), it is possible to replace the syscon usage with a
global variable that simplifies the code. Doing so does lose the
locking provided by regmap, but as only one side is using the regmap
interface (irq-bcm2835 uses readl and write) there is no loss of
atomicity.

See: https://github.com/raspberrypi/firmware/issues/926

Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
 arch/arm/boot/dts/bcm2709.dtsi |  5 -----
 arch/arm/boot/dts/bcm2710.dtsi |  5 -----
 drivers/irqchip/irq-bcm2835.c  | 32 ++++++++++++--------------------
 drivers/irqchip/irq-bcm2836.c  |  5 +++++
 4 files changed, 17 insertions(+), 30 deletions(-)

--- a/arch/arm/boot/dts/bcm2709.dtsi
+++ b/arch/arm/boot/dts/bcm2709.dtsi
@@ -6,11 +6,6 @@
 	soc {
 		ranges = <0x7e000000 0x3f000000 0x01000000>,
 		         <0x40000000 0x40000000 0x00040000>;
-
-		syscon@40000000 {
-			compatible = "brcm,bcm2836-arm-local", "syscon";
-			reg = <0x40000000 0x100>;
-		};
 	};
 
 	__overrides__ {
--- a/arch/arm/boot/dts/bcm2710.dtsi
+++ b/arch/arm/boot/dts/bcm2710.dtsi
@@ -16,11 +16,6 @@
 			interrupt-parent = <&local_intc>;
 			interrupts = <9>;
 		};
-
-		syscon@40000000 {
-			compatible = "brcm,bcm2836-arm-local", "syscon";
-			reg = <0x40000000 0x100>;
-		};
 	};
 
 	__overrides__ {
--- a/drivers/irqchip/irq-bcm2835.c
+++ b/drivers/irqchip/irq-bcm2835.c
@@ -50,8 +50,6 @@
 #include <linux/of_irq.h>
 #include <linux/irqchip.h>
 #include <linux/irqdomain.h>
-#include <linux/mfd/syscon.h>
-#include <linux/regmap.h>
 
 #include <asm/exception.h>
 #ifndef CONFIG_ARM64
@@ -103,7 +101,7 @@ struct armctrl_ic {
 	void __iomem *enable[NR_BANKS];
 	void __iomem *disable[NR_BANKS];
 	struct irq_domain *domain;
-	struct regmap *local_regmap;
+	void __iomem *local_base;
 };
 
 static struct armctrl_ic intc __read_mostly;
@@ -140,24 +138,20 @@ static void armctrl_unmask_irq(struct ir
 	if (d->hwirq >= NUMBER_IRQS) {
 		if (num_online_cpus() > 1) {
 			unsigned int data;
-			int ret;
 
-			if (!intc.local_regmap) {
-				pr_err("FIQ is disabled due to missing regmap\n");
+			if (!intc.local_base) {
+				pr_err("FIQ is disabled due to missing arm_local_intc\n");
 				return;
 			}
 
-			ret = regmap_read(intc.local_regmap,
-					  ARM_LOCAL_GPU_INT_ROUTING, &data);
-			if (ret) {
-				pr_err("Failed to read int routing %d\n", ret);
-				return;
-			}
+			data = readl_relaxed(intc.local_base +
+					     ARM_LOCAL_GPU_INT_ROUTING);
 
 			data &= ~0xc;
 			data |= (1 << 2);
-			regmap_write(intc.local_regmap,
-				     ARM_LOCAL_GPU_INT_ROUTING, data);
+			writel_relaxed(data,
+				       intc.local_base +
+				       ARM_LOCAL_GPU_INT_ROUTING);
 		}
 
 		writel_relaxed(REG_FIQ_ENABLE | hwirq_to_fiq(d->hwirq),
@@ -256,12 +250,10 @@ static int __init armctrl_of_init(struct
 	}
 
 	if (is_2836) {
-		intc.local_regmap =
-			syscon_regmap_lookup_by_compatible("brcm,bcm2836-arm-local");
-		if (IS_ERR(intc.local_regmap)) {
-			pr_err("Failed to get local register map. FIQ is disabled for cpus > 1\n");
-			intc.local_regmap = NULL;
-		}
+		extern void __iomem * __attribute__((weak)) arm_local_intc;
+		intc.local_base = arm_local_intc;
+		if (!intc.local_base)
+			pr_err("Failed to get local intc base. FIQ is disabled for cpus > 1\n");
 	}
 
 	/* Make a duplicate irq range which is used to enable FIQ */
--- a/drivers/irqchip/irq-bcm2836.c
+++ b/drivers/irqchip/irq-bcm2836.c
@@ -83,6 +83,9 @@ struct bcm2836_arm_irqchip_intc {
 
 static struct bcm2836_arm_irqchip_intc intc  __read_mostly;
 
+void __iomem *arm_local_intc;
+EXPORT_SYMBOL_GPL(arm_local_intc);
+
 static void bcm2836_arm_irqchip_mask_per_cpu_irq(unsigned int reg_offset,
 						 unsigned int bit,
 						 int cpu)
@@ -310,6 +313,8 @@ static int __init bcm2836_arm_irqchip_l1
 		panic("%pOF: unable to map local interrupt registers\n", node);
 	}
 
+	arm_local_intc = intc.base;
+
 	bcm2835_init_local_timer_frequency();
 
 	intc.domain = irq_domain_add_linear(node, LAST_IRQ + 1,