Skip to content

Commit 2b44173

Browse files
stephanosionashif
authored andcommitted
interrupt_controller: gic: Support multiple GIC versions
The current GIC driver implementation only supports the GIC-400, which implements the GICv2 interface. This commit refactors the GIC driver to support multiple GIC versions and adds GICv1 interface support (GICv1 and GICv2 interfaces are very similar). Signed-off-by: Stephanos Ioannidis <[email protected]>
1 parent 11d0f0a commit 2b44173

File tree

3 files changed

+225
-43
lines changed

3 files changed

+225
-43
lines changed

drivers/interrupt_controller/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# SPDX-License-Identifier: Apache-2.0
22

33
zephyr_sources_ifdef(CONFIG_ARCV2_INTERRUPT_UNIT intc_arcv2_irq_unit.c)
4-
zephyr_sources_ifdef(CONFIG_GIC intc_gic_400.c)
4+
zephyr_sources_ifdef(CONFIG_GIC intc_gic.c)
55
zephyr_sources_ifdef(CONFIG_IOAPIC intc_ioapic.c)
66
zephyr_sources_ifdef(CONFIG_LOAPIC intc_loapic.c intc_system_apic.c)
77
zephyr_sources_ifdef(CONFIG_LOAPIC_SPURIOUS_VECTOR intc_loapic_spurious.S)

drivers/interrupt_controller/intc_gic_400.c renamed to drivers/interrupt_controller/intc_gic.c

Lines changed: 25 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,25 @@
11
/*
22
* Copyright (c) 2018 Marvell
33
* Copyright (c) 2018 Lexmark International, Inc.
4+
* Copyright (c) 2019 Stephanos Ioannidis <[email protected]>
45
*
56
* SPDX-License-Identifier: Apache-2.0
67
*/
78

9+
/*
10+
* NOTE: This driver currently implements the GICv1 and GICv2 interfaces. The
11+
* GICv3 interface is not supported.
12+
*/
13+
814
#include <device.h>
915
#include <sw_isr_table.h>
1016
#include <irq_nextlevel.h>
1117
#include <dt-bindings/interrupt-controller/arm-gic.h>
18+
#include <drivers/interrupt_controller/gic.h>
1219

13-
#define DT_GIC_DIST_BASE DT_INST_0_ARM_GIC_BASE_ADDRESS_0
14-
#define DT_GIC_CPU_BASE DT_INST_0_ARM_GIC_BASE_ADDRESS_1
15-
16-
#define GICD_CTRL (DT_GIC_DIST_BASE + 0)
17-
#define GICD_TYPER (DT_GIC_DIST_BASE + 0x4)
18-
#define GICD_IIDR (DT_GIC_DIST_BASE + 0x8)
19-
#define GICD_IGROUPRn (DT_GIC_DIST_BASE + 0x80)
20-
#define GICD_ISENABLERn (DT_GIC_DIST_BASE + 0x100)
21-
#define GICD_ICENABLERn (DT_GIC_DIST_BASE + 0x180)
22-
#define GICD_ISPENDRn (DT_GIC_DIST_BASE + 0x200)
23-
#define GICD_ICPENDRn (DT_GIC_DIST_BASE + 0x280)
24-
#define GICD_ISACTIVERn (DT_GIC_DIST_BASE + 0x300)
25-
#define GICD_ICACTIVERn (DT_GIC_DIST_BASE + 0x380)
26-
#define GICD_IPRIORITYRn (DT_GIC_DIST_BASE + 0x400)
27-
#define GICD_ITARGETSRn (DT_GIC_DIST_BASE + 0x800)
28-
#define GICD_ICFGRn (DT_GIC_DIST_BASE + 0xc00)
29-
#define GICD_SGIR (DT_GIC_DIST_BASE + 0xf00)
30-
31-
#define GICC_CTRL (DT_GIC_CPU_BASE + 0x00)
32-
#define GICC_PMR (DT_GIC_CPU_BASE + 0x04)
33-
#define GICC_BPR (DT_GIC_CPU_BASE + 0x08)
34-
#define GICC_IAR (DT_GIC_CPU_BASE + 0x0c)
35-
#define GICC_EOIR (DT_GIC_CPU_BASE + 0x10)
36-
37-
#define GICC_ENABLE 3
38-
#define GICC_DIS_BYPASS_MASK 0x1e0
39-
40-
#define NO_GIC_INT_PENDING 1023
41-
42-
#define GIC_SPI_INT_BASE 32
43-
44-
#define GIC_INT_TYPE_MASK 0x3
45-
#define GIC_INT_TYPE_EDGE (1 << 1)
20+
#if CONFIG_GIC_VER >= 3
21+
#error "GICv3 and above are not supported"
22+
#endif
4623

4724
struct gic_ictl_config {
4825
u32_t isr_table_offset;
@@ -61,7 +38,7 @@ static void gic_dist_init(void)
6138
* Disable the forwarding of pending interrupts
6239
* from the Distributor to the CPU interfaces
6340
*/
64-
sys_write32(0, GICD_CTRL);
41+
sys_write32(0, GICD_CTLR);
6542

6643
/*
6744
* Set all global interrupts to this CPU only.
@@ -88,15 +65,17 @@ static void gic_dist_init(void)
8865
* as these enables are banked registers.
8966
*/
9067
for (i = GIC_SPI_INT_BASE; i < gic_irqs; i += 32) {
68+
#ifndef CONFIG_GIC_V1
9169
sys_write32(0xffffffff, GICD_ICACTIVERn + i / 8);
70+
#endif
9271
sys_write32(0xffffffff, GICD_ICENABLERn + i / 8);
9372
}
9473

9574
/*
9675
* Enable the forwarding of pending interrupts
9776
* from the Distributor to the CPU interfaces
9877
*/
99-
sys_write32(1, GICD_CTRL);
78+
sys_write32(1, GICD_CTLR);
10079
}
10180

10281
static void gic_cpu_init(void)
@@ -108,7 +87,9 @@ static void gic_cpu_init(void)
10887
* Deal with the banked PPI and SGI interrupts - disable all
10988
* PPI interrupts, ensure all SGI interrupts are enabled.
11089
*/
90+
#ifndef CONFIG_GIC_V1
11191
sys_write32(0xffffffff, GICD_ICACTIVERn);
92+
#endif
11293
sys_write32(0xffff0000, GICD_ICENABLERn);
11394
sys_write32(0x0000ffff, GICD_ISENABLERn);
11495

@@ -123,10 +104,12 @@ static void gic_cpu_init(void)
123104
/*
124105
* Enable interrupts and signal them using the IRQ signal.
125106
*/
126-
val = sys_read32(GICC_CTRL);
127-
val &= GICC_DIS_BYPASS_MASK;
128-
val |= GICC_ENABLE;
129-
sys_write32(val, GICC_CTRL);
107+
val = sys_read32(GICC_CTLR);
108+
#ifndef CONFIG_GIC_V1
109+
val &= ~GICC_CTLR_BYPASS_MASK;
110+
#endif
111+
val |= GICC_CTLR_ENABLE_MASK;
112+
sys_write32(val, GICC_CTLR);
130113
}
131114

132115
static void gic_irq_enable(struct device *dev, unsigned int irq)
@@ -168,9 +151,9 @@ static void gic_irq_set_priority(struct device *dev,
168151
int_off = (irq % 16) * 2;
169152

170153
val = sys_read8(GICD_ICFGRn + int_grp);
171-
val &= ~(GIC_INT_TYPE_MASK << int_off);
154+
val &= ~(GICC_ICFGR_MASK << int_off);
172155
if (flags & IRQ_TYPE_EDGE)
173-
val |= (GIC_INT_TYPE_EDGE << int_off);
156+
val |= (GICC_ICFGR_TYPE << int_off);
174157
sys_write8(val, GICD_ICFGRn + int_grp);
175158
}
176159

@@ -184,7 +167,7 @@ static void gic_isr(void *arg)
184167
irq = sys_read32(GICC_IAR);
185168
irq &= 0x3ff;
186169

187-
if (irq == NO_GIC_INT_PENDING) {
170+
if (irq == GICC_IAR_SPURIOUS) {
188171
printk("gic: Invalid interrupt\n");
189172
return;
190173
}
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
/*
2+
* Copyright (c) 2019 Stephanos Ioannidis <[email protected]>
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef ZEPHYR_INCLUDE_DRIVERS_GIC_H_
8+
#define ZEPHYR_INCLUDE_DRIVERS_GIC_H_
9+
10+
#include <arch/cpu.h>
11+
12+
/*
13+
* GIC Register Interface Base Addresses
14+
*/
15+
16+
#define GIC_DIST_BASE DT_INST_0_ARM_GIC_BASE_ADDRESS_0
17+
#define GIC_CPU_BASE DT_INST_0_ARM_GIC_BASE_ADDRESS_1
18+
19+
/*
20+
* GIC Distributor Interface
21+
*/
22+
23+
/*
24+
* 0x000 Distributor Control Register
25+
* v1 ICDDCR
26+
* v2/v3 GICD_CTLR
27+
*/
28+
#define GICD_CTLR (GIC_DIST_BASE + 0x0)
29+
30+
/*
31+
* 0x004 Interrupt Controller Type Register
32+
* v1 ICDICTR
33+
* v2/v3 GICD_TYPER
34+
*/
35+
#define GICD_TYPER (GIC_DIST_BASE + 0x4)
36+
37+
/*
38+
* 0x008 Distributor Implementer Identification Register
39+
* v1 ICDIIDR
40+
* v2/v3 GICD_IIDR
41+
*/
42+
#define GICD_IIDR (GIC_DIST_BASE + 0x8)
43+
44+
/*
45+
* 0x080 Interrupt Group Registers
46+
* v1 ICDISRn
47+
* v2/v3 GICD_IGROUPRn
48+
*/
49+
#define GICD_IGROUPRn (GIC_DIST_BASE + 0x80)
50+
51+
/*
52+
* 0x100 Interrupt Set-Enable Reigsters
53+
* v1 ICDISERn
54+
* v2/v3 GICD_ISENABLERn
55+
*/
56+
#define GICD_ISENABLERn (GIC_DIST_BASE + 0x100)
57+
58+
/*
59+
* 0x180 Interrupt Clear-Enable Registers
60+
* v1 ICDICERn
61+
* v2/v3 GICD_ICENABLERn
62+
*/
63+
#define GICD_ICENABLERn (GIC_DIST_BASE + 0x180)
64+
65+
/*
66+
* 0x200 Interrupt Set-Pending Registers
67+
* v1 ICDISPRn
68+
* v2/v3 GICD_ISPENDRn
69+
*/
70+
#define GICD_ISPENDRn (GIC_DIST_BASE + 0x200)
71+
72+
/*
73+
* 0x280 Interrupt Clear-Pending Registers
74+
* v1 ICDICPRn
75+
* v2/v3 GICD_ICPENDRn
76+
*/
77+
#define GICD_ICPENDRn (GIC_DIST_BASE + 0x280)
78+
79+
/*
80+
* 0x300 Interrupt Set-Active Registers
81+
* v1 ICDABRn
82+
* v2/v3 GICD_ISACTIVERn
83+
*/
84+
#define GICD_ISACTIVERn (GIC_DIST_BASE + 0x300)
85+
86+
#if CONFIG_GIC_VER >= 2
87+
/*
88+
* 0x380 Interrupt Clear-Active Registers
89+
* v2/v3 GICD_ICACTIVERn
90+
*/
91+
#define GICD_ICACTIVERn (GIC_DIST_BASE + 0x380)
92+
#endif
93+
94+
/*
95+
* 0x400 Interrupt Priority Registers
96+
* v1 ICDIPRn
97+
* v2/v3 GICD_IPRIORITYRn
98+
*/
99+
#define GICD_IPRIORITYRn (GIC_DIST_BASE + 0x400)
100+
101+
/*
102+
* 0x800 Interrupt Processor Targets Registers
103+
* v1 ICDIPTRn
104+
* v2/v3 GICD_ITARGETSRn
105+
*/
106+
#define GICD_ITARGETSRn (GIC_DIST_BASE + 0x800)
107+
108+
/*
109+
* 0xC00 Interrupt Configuration Registers
110+
* v1 ICDICRn
111+
* v2/v3 GICD_ICFGRn
112+
*/
113+
#define GICD_ICFGRn (GIC_DIST_BASE + 0xc00)
114+
115+
/*
116+
* 0xF00 Software Generated Interrupt Register
117+
* v1 ICDSGIR
118+
* v2/v3 GICD_SGIR
119+
*/
120+
#define GICD_SGIR (GIC_DIST_BASE + 0xf00)
121+
122+
/*
123+
* GIC CPU Interface
124+
*/
125+
126+
#if CONFIG_GIC_VER <= 2
127+
128+
/*
129+
* 0x0000 CPU Interface Control Register
130+
* v1 ICCICR
131+
* v2/v3 GICC_CTLR
132+
*/
133+
#define GICC_CTLR (GIC_CPU_BASE + 0x0)
134+
135+
/*
136+
* 0x0004 Interrupt Priority Mask Register
137+
* v1 ICCPMR
138+
* v2/v3 GICC_PMR
139+
*/
140+
#define GICC_PMR (GIC_CPU_BASE + 0x4)
141+
142+
/*
143+
* 0x0008 Binary Point Register
144+
* v1 ICCBPR
145+
* v2/v3 GICC_BPR
146+
*/
147+
#define GICC_BPR (GIC_CPU_BASE + 0x8)
148+
149+
/*
150+
* 0x000C Interrupt Acknowledge Register
151+
* v1 ICCIAR
152+
* v2/v3 GICC_IAR
153+
*/
154+
#define GICC_IAR (GIC_CPU_BASE + 0xc)
155+
156+
/*
157+
* 0x0010 End of Interrupt Register
158+
* v1 ICCEOIR
159+
* v2/v3 GICC_EOIR
160+
*/
161+
#define GICC_EOIR (GIC_CPU_BASE + 0x10)
162+
163+
164+
/*
165+
* Helper Constants
166+
*/
167+
168+
#define GIC_SPI_INT_BASE 32
169+
170+
/* GICC_CTLR */
171+
#define GICC_CTLR_ENABLEGRP0 BIT(0)
172+
#define GICC_CTLR_ENABLEGRP1 BIT(1)
173+
174+
#define GICC_CTLR_ENABLE_MASK (GICC_CTLR_ENABLEGRP0 | GICC_CTLR_ENABLEGRP1)
175+
176+
#if defined(CONFIG_GIC_V2)
177+
178+
#define GICC_CTLR_FIQBYPDISGRP0 BIT(5)
179+
#define GICC_CTLR_IRQBYPDISGRP0 BIT(6)
180+
#define GICC_CTLR_FIQBYPDISGRP1 BIT(7)
181+
#define GICC_CTLR_IRQBYPDISGRP1 BIT(8)
182+
183+
#define GICC_CTLR_BYPASS_MASK (GICC_CTLR_FIQBYPDISGRP0 | \
184+
GICC_CTLR_IRQBYPDISGRP1 | \
185+
GICC_CTLR_FIQBYPDISGRP1 | \
186+
GICC_CTLR_IRQBYPDISGRP1)
187+
188+
#endif /* CONFIG_GIC_V2 */
189+
190+
/* GICC_IAR */
191+
#define GICC_IAR_SPURIOUS 1023
192+
193+
/* GICC_ICFGR */
194+
#define GICC_ICFGR_MASK BIT_MASK(2)
195+
#define GICC_ICFGR_TYPE BIT(1)
196+
197+
#endif /* CONFIG_GIC_VER <= 2 */
198+
199+
#endif /* ZEPHYR_INCLUDE_DRIVERS_GIC_H_ */

0 commit comments

Comments
 (0)