2 * This file is part of the coreboot project.
4 * Copyright 2014 Google Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
18 #include <console/console.h>
23 ENABLE_GRP0
= 0x1 << 0,
24 ENABLE_GRP1
= 0x1 << 1,
25 FIQ_BYP_DIS_GRP0
= 0x1 << 5,
26 IRQ_BYP_DIS_GRP0
= 0x1 << 6,
27 FIQ_BYP_DIS_GRP1
= 0x1 << 7,
28 IRQ_BYP_DIS_GRP1
= 0x1 << 8,
32 struct gicd_mmio
*gicd
;
33 struct gicc_mmio
*gicc
;
34 size_t num_interrupts
;
36 unsigned int security_extensions
;
39 static struct gic
*gic_get(void)
41 static struct gic gic
;
43 if (gic
.gicd
== NULL
) {
46 gic
.gicd
= gicd_base();
47 gic
.gicc
= gicc_base();
48 typer
= read32(&gic
.gicd
->typer
);
49 gic
.num_interrupts
= 32 * ((typer
& 0x1f) + 1);
50 gic
.security_extensions
= !!(typer
& (1 << 10));
51 gic
.version
= (read32(&gic
.gicd
->icpidr2
) & 0xf0) >> 4;
53 printk(BIOS_DEBUG
, "GICv%d - %zu ints %s GICD=%p GICC=%p\n",
54 gic
.version
, gic
.num_interrupts
,
55 gic
.security_extensions
? "SecExtn" : "",
62 static inline uint32_t gic_read(uint32_t *base
)
67 static inline void gic_write(uint32_t *base
, uint32_t val
)
72 static void gic_write_regs(uint32_t *base
, size_t num_regs
, uint32_t val
)
76 for (i
= 0; i
< num_regs
; i
++)
77 gic_write(base
++, val
);
80 static void gic_write_banked_regs(uint32_t *base
, size_t interrupts_per_reg
,
83 /* 1st 32 interrupts are banked per CPU. */
84 gic_write_regs(base
, 32 / interrupts_per_reg
, val
);
90 struct gicd_mmio
*gicd
;
91 struct gicc_mmio
*gicc
;
98 /* Enable Group 0 and Group 1 in GICD -- banked regs. */
99 gic_write(&gicd
->ctlr
, ENABLE_GRP0
| ENABLE_GRP1
);
101 /* Enable Group 0 and Group 1 in GICC and enable all priroity levels. */
102 gic_write(&gicc
->ctlr
, ENABLE_GRP0
| ENABLE_GRP1
);
103 gic_write(&gicc
->pmr
, 1 << 7);
105 cpu_mask
= 1 << smp_processor_id();
106 cpu_mask
|= cpu_mask
<< 8;
107 cpu_mask
|= cpu_mask
<< 16;
109 /* Only write banked registers for secondary CPUs. */
110 if (smp_processor_id()) {
111 gic_write_banked_regs(&gicd
->itargetsr
[0], 4, cpu_mask
);
112 /* Put interrupts into Group 1. */
113 gic_write_banked_regs(&gicd
->igroupr
[0], 32, ~0x0);
114 /* Allow Non-secure access to everything. */
115 gic_write_banked_regs(&gicd
->nsacr
[0], 16, ~0x0);
119 /* All interrupts routed to processors that execute this function. */
120 gic_write_regs(&gicd
->itargetsr
[0], gic
->num_interrupts
/ 4, cpu_mask
);
121 /* Put all interrupts into Gropup 1. */
122 gic_write_regs(&gicd
->igroupr
[0], gic
->num_interrupts
/ 32, ~0x0);
123 /* Allow Non-secure access to everything. */
124 gic_write_regs(&gicd
->nsacr
[0], gic
->num_interrupts
/ 16, ~0x0);
127 void gic_disable(void)
130 struct gicc_mmio
*gicc
;
135 /* Disable secure, non-secure interrupts. */
136 uint32_t val
= gic_read(&gicc
->ctlr
);
137 val
&= ~(ENABLE_GRP0
| ENABLE_GRP1
);
139 * Enable the IRQ/FIQ BypassDisable bits to bypass the IRQs.
140 * So the CPU can wake up from power gating state when the GIC
143 val
|= FIQ_BYP_DIS_GRP0
| IRQ_BYP_DIS_GRP0
|
144 FIQ_BYP_DIS_GRP1
| IRQ_BYP_DIS_GRP1
;
145 gic_write(&gicc
->ctlr
, val
);
148 void gic_enable(void)
151 struct gicc_mmio
*gicc
;
156 /* Enable secure, non-secure interrupts. */
157 uint32_t val
= gic_read(&gicc
->ctlr
);
158 val
|= (ENABLE_GRP0
| ENABLE_GRP1
);
159 gic_write(&gicc
->ctlr
, val
);