blob: b60a5cd9b85731181cf7fced24c8ce0a9e2ff498 [file] [log] [blame]
Soby Mathewe063d3c2015-10-07 09:45:27 +01001/*
Soby Mathew73f92992016-01-15 14:05:37 +00002 * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
Soby Mathewe063d3c2015-10-07 09:45:27 +01003 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of ARM nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific
16 * prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <arch.h>
32#include <arch_helpers.h>
33#include <assert.h>
34#include <debug.h>
35#include <gic_common.h>
Soby Mathew50f6fe42016-02-01 17:59:22 +000036#include "../common/gic_common_private.h"
Soby Mathewe063d3c2015-10-07 09:45:27 +010037#include "gicv2_private.h"
38
39/*
40 * Accessor to read the GIC Distributor ITARGETSR corresponding to the
41 * interrupt `id`, 4 interrupt IDs at a time.
42 */
43unsigned int gicd_read_itargetsr(uintptr_t base, unsigned int id)
44{
45 unsigned n = id >> ITARGETSR_SHIFT;
46 return mmio_read_32(base + GICD_ITARGETSR + (n << 2));
47}
48
49/*
50 * Accessor to read the GIC Distributor CPENDSGIR corresponding to the
51 * interrupt `id`, 4 interrupt IDs at a time.
52 */
53unsigned int gicd_read_cpendsgir(uintptr_t base, unsigned int id)
54{
55 unsigned n = id >> CPENDSGIR_SHIFT;
56 return mmio_read_32(base + GICD_CPENDSGIR + (n << 2));
57}
58
59/*
60 * Accessor to read the GIC Distributor SPENDSGIR corresponding to the
61 * interrupt `id`, 4 interrupt IDs at a time.
62 */
63unsigned int gicd_read_spendsgir(uintptr_t base, unsigned int id)
64{
65 unsigned n = id >> SPENDSGIR_SHIFT;
66 return mmio_read_32(base + GICD_SPENDSGIR + (n << 2));
67}
68
69/*
70 * Accessor to write the GIC Distributor ITARGETSR corresponding to the
71 * interrupt `id`, 4 interrupt IDs at a time.
72 */
73void gicd_write_itargetsr(uintptr_t base, unsigned int id, unsigned int val)
74{
75 unsigned n = id >> ITARGETSR_SHIFT;
76 mmio_write_32(base + GICD_ITARGETSR + (n << 2), val);
77}
78
79/*
80 * Accessor to write the GIC Distributor CPENDSGIR corresponding to the
81 * interrupt `id`, 4 interrupt IDs at a time.
82 */
83void gicd_write_cpendsgir(uintptr_t base, unsigned int id, unsigned int val)
84{
85 unsigned n = id >> CPENDSGIR_SHIFT;
86 mmio_write_32(base + GICD_CPENDSGIR + (n << 2), val);
87}
88
89/*
90 * Accessor to write the GIC Distributor SPENDSGIR corresponding to the
91 * interrupt `id`, 4 interrupt IDs at a time.
92 */
93void gicd_write_spendsgir(uintptr_t base, unsigned int id, unsigned int val)
94{
95 unsigned n = id >> SPENDSGIR_SHIFT;
96 mmio_write_32(base + GICD_SPENDSGIR + (n << 2), val);
97}
98
99/*
100 * Accessor to write the GIC Distributor ITARGETSR corresponding to the
101 * interrupt `id`.
102 */
103void gicd_set_itargetsr(uintptr_t base, unsigned int id, unsigned int target)
104{
Soby Mathew73f92992016-01-15 14:05:37 +0000105 mmio_write_8(base + GICD_ITARGETSR + id, target & GIC_TARGET_CPU_MASK);
Soby Mathewe063d3c2015-10-07 09:45:27 +0100106}
107
108/*******************************************************************************
109 * Get the current CPU bit mask from GICD_ITARGETSR0
110 ******************************************************************************/
111unsigned int gicv2_get_cpuif_id(uintptr_t base)
112{
113 unsigned int val;
114
115 val = gicd_read_itargetsr(base, 0);
116 return val & GIC_TARGET_CPU_MASK;
117}
118
119/*******************************************************************************
120 * Helper function to configure the default attributes of SPIs.
121 ******************************************************************************/
122void gicv2_spis_configure_defaults(uintptr_t gicd_base)
123{
124 unsigned int index, num_ints;
125
126 num_ints = gicd_read_typer(gicd_base);
127 num_ints &= TYPER_IT_LINES_NO_MASK;
128 num_ints = (num_ints + 1) << 5;
129
130 /*
131 * Treat all SPIs as G1NS by default. The number of interrupts is
132 * calculated as 32 * (IT_LINES + 1). We do 32 at a time.
133 */
134 for (index = MIN_SPI_ID; index < num_ints; index += 32)
135 gicd_write_igroupr(gicd_base, index, ~0U);
136
137 /* Setup the default SPI priorities doing four at a time */
138 for (index = MIN_SPI_ID; index < num_ints; index += 4)
139 gicd_write_ipriorityr(gicd_base,
140 index,
141 GICD_IPRIORITYR_DEF_VAL);
142
143 /* Treat all SPIs as level triggered by default, 16 at a time */
144 for (index = MIN_SPI_ID; index < num_ints; index += 16)
145 gicd_write_icfgr(gicd_base, index, 0);
146}
147
148/*******************************************************************************
149 * Helper function to configure secure G0 SPIs.
150 ******************************************************************************/
151void gicv2_secure_spis_configure(uintptr_t gicd_base,
152 unsigned int num_ints,
153 const unsigned int *sec_intr_list)
154{
155 unsigned int index, irq_num;
156
157 /* If `num_ints` is not 0, ensure that `sec_intr_list` is not NULL */
158 assert(num_ints ? (uintptr_t)sec_intr_list : 1);
159
160 for (index = 0; index < num_ints; index++) {
161 irq_num = sec_intr_list[index];
162 if (irq_num >= MIN_SPI_ID) {
163 /* Configure this interrupt as a secure interrupt */
164 gicd_clr_igroupr(gicd_base, irq_num);
165
166 /* Set the priority of this interrupt */
Soby Mathew421259e2016-01-15 14:20:57 +0000167 gicd_set_ipriorityr(gicd_base,
Soby Mathewe063d3c2015-10-07 09:45:27 +0100168 irq_num,
169 GIC_HIGHEST_SEC_PRIORITY);
170
171 /* Target the secure interrupts to primary CPU */
172 gicd_set_itargetsr(gicd_base, irq_num,
173 gicv2_get_cpuif_id(gicd_base));
174
175 /* Enable this interrupt */
176 gicd_set_isenabler(gicd_base, irq_num);
177 }
178 }
179
180}
181
182/*******************************************************************************
183 * Helper function to configure secure G0 SGIs and PPIs.
184 ******************************************************************************/
185void gicv2_secure_ppi_sgi_setup(uintptr_t gicd_base,
186 unsigned int num_ints,
187 const unsigned int *sec_intr_list)
188{
189 unsigned int index, irq_num, sec_ppi_sgi_mask = 0;
190
191 /* If `num_ints` is not 0, ensure that `sec_intr_list` is not NULL */
192 assert(num_ints ? (uintptr_t)sec_intr_list : 1);
193
194 /*
195 * Disable all SGIs (imp. def.)/PPIs before configuring them. This is a
196 * more scalable approach as it avoids clearing the enable bits in the
197 * GICD_CTLR.
198 */
199 gicd_write_icenabler(gicd_base, 0, ~0);
200
201 /* Setup the default PPI/SGI priorities doing four at a time */
202 for (index = 0; index < MIN_SPI_ID; index += 4)
203 gicd_write_ipriorityr(gicd_base,
204 index,
205 GICD_IPRIORITYR_DEF_VAL);
206
207 for (index = 0; index < num_ints; index++) {
208 irq_num = sec_intr_list[index];
209 if (irq_num < MIN_SPI_ID) {
210 /* We have an SGI or a PPI. They are Group0 at reset */
211 sec_ppi_sgi_mask |= 1U << irq_num;
212
213 /* Set the priority of this interrupt */
Soby Mathew421259e2016-01-15 14:20:57 +0000214 gicd_set_ipriorityr(gicd_base,
Soby Mathewe063d3c2015-10-07 09:45:27 +0100215 irq_num,
216 GIC_HIGHEST_SEC_PRIORITY);
217 }
218 }
219
220 /*
221 * Invert the bitmask to create a mask for non-secure PPIs and
222 * SGIs. Program the GICD_IGROUPR0 with this bit mask.
223 */
224 gicd_write_igroupr(gicd_base, 0, ~sec_ppi_sgi_mask);
225
226 /* Enable the Group 0 SGIs and PPIs */
227 gicd_write_isenabler(gicd_base, 0, sec_ppi_sgi_mask);
228}