tree: drop last paragraph of GPL copyright header
[coreboot.git] / src / drivers / gic / gic.c
blob622aaff486c52aa113868c91f2ecf07a633d7f6d
1 /*
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.
16 #include <arch/cpu.h>
17 #include <arch/io.h>
18 #include <console/console.h>
19 #include <gic.h>
20 #include "gic.h"
22 enum {
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,
31 struct gic {
32 struct gicd_mmio *gicd;
33 struct gicc_mmio *gicc;
34 size_t num_interrupts;
35 unsigned int version;
36 unsigned int security_extensions;
39 static struct gic *gic_get(void)
41 static struct gic gic;
43 if (gic.gicd == NULL) {
44 uint32_t typer;
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" : "",
56 gic.gicd, gic.gicc);
59 return &gic;
62 static inline uint32_t gic_read(uint32_t *base)
64 return read32(base);
67 static inline void gic_write(uint32_t *base, uint32_t val)
69 write32(base, val);
72 static void gic_write_regs(uint32_t *base, size_t num_regs, uint32_t val)
74 size_t i;
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,
81 uint32_t val)
83 /* 1st 32 interrupts are banked per CPU. */
84 gic_write_regs(base, 32 / interrupts_per_reg, val);
87 void gic_init(void)
89 struct gic *gic;
90 struct gicd_mmio *gicd;
91 struct gicc_mmio *gicc;
92 uint32_t cpu_mask;
94 gic = gic_get();
95 gicd = gic->gicd;
96 gicc = gic->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);
116 return;
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)
129 struct gic *gic;
130 struct gicc_mmio *gicc;
132 gic = gic_get();
133 gicc = gic->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
141 * was disabled.
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)
150 struct gic *gic;
151 struct gicc_mmio *gicc;
153 gic = gic_get();
154 gicc = gic->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);