blob: e9ae7dfab99d3e848e8579702281eacb5d00bd2f [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>
36#include "gicv2_private.h"
37
38/*
39 * Accessor to read the GIC Distributor ITARGETSR corresponding to the
40 * interrupt `id`, 4 interrupt IDs at a time.
41 */
42unsigned int gicd_read_itargetsr(uintptr_t base, unsigned int id)
43{
44 unsigned n = id >> ITARGETSR_SHIFT;
45 return mmio_read_32(base + GICD_ITARGETSR + (n << 2));
46}
47
48/*
49 * Accessor to read the GIC Distributor CPENDSGIR corresponding to the
50 * interrupt `id`, 4 interrupt IDs at a time.
51 */
52unsigned int gicd_read_cpendsgir(uintptr_t base, unsigned int id)
53{
54 unsigned n = id >> CPENDSGIR_SHIFT;
55 return mmio_read_32(base + GICD_CPENDSGIR + (n << 2));
56}
57
58/*
59 * Accessor to read the GIC Distributor SPENDSGIR corresponding to the
60 * interrupt `id`, 4 interrupt IDs at a time.
61 */
62unsigned int gicd_read_spendsgir(uintptr_t base, unsigned int id)
63{
64 unsigned n = id >> SPENDSGIR_SHIFT;
65 return mmio_read_32(base + GICD_SPENDSGIR + (n << 2));
66}
67
68/*
69 * Accessor to write the GIC Distributor ITARGETSR corresponding to the
70 * interrupt `id`, 4 interrupt IDs at a time.
71 */
72void gicd_write_itargetsr(uintptr_t base, unsigned int id, unsigned int val)
73{
74 unsigned n = id >> ITARGETSR_SHIFT;
75 mmio_write_32(base + GICD_ITARGETSR + (n << 2), val);
76}
77
78/*
79 * Accessor to write the GIC Distributor CPENDSGIR corresponding to the
80 * interrupt `id`, 4 interrupt IDs at a time.
81 */
82void gicd_write_cpendsgir(uintptr_t base, unsigned int id, unsigned int val)
83{
84 unsigned n = id >> CPENDSGIR_SHIFT;
85 mmio_write_32(base + GICD_CPENDSGIR + (n << 2), val);
86}
87
88/*
89 * Accessor to write the GIC Distributor SPENDSGIR corresponding to the
90 * interrupt `id`, 4 interrupt IDs at a time.
91 */
92void gicd_write_spendsgir(uintptr_t base, unsigned int id, unsigned int val)
93{
94 unsigned n = id >> SPENDSGIR_SHIFT;
95 mmio_write_32(base + GICD_SPENDSGIR + (n << 2), val);
96}
97
98/*
99 * Accessor to write the GIC Distributor ITARGETSR corresponding to the
100 * interrupt `id`.
101 */
102void gicd_set_itargetsr(uintptr_t base, unsigned int id, unsigned int target)
103{
Soby Mathew73f92992016-01-15 14:05:37 +0000104 mmio_write_8(base + GICD_ITARGETSR + id, target & GIC_TARGET_CPU_MASK);
Soby Mathewe063d3c2015-10-07 09:45:27 +0100105}
106
107/*******************************************************************************
108 * Get the current CPU bit mask from GICD_ITARGETSR0
109 ******************************************************************************/
110unsigned int gicv2_get_cpuif_id(uintptr_t base)
111{
112 unsigned int val;
113
114 val = gicd_read_itargetsr(base, 0);
115 return val & GIC_TARGET_CPU_MASK;
116}
117
118/*******************************************************************************
119 * Helper function to configure the default attributes of SPIs.
120 ******************************************************************************/
121void gicv2_spis_configure_defaults(uintptr_t gicd_base)
122{
123 unsigned int index, num_ints;
124
125 num_ints = gicd_read_typer(gicd_base);
126 num_ints &= TYPER_IT_LINES_NO_MASK;
127 num_ints = (num_ints + 1) << 5;
128
129 /*
130 * Treat all SPIs as G1NS by default. The number of interrupts is
131 * calculated as 32 * (IT_LINES + 1). We do 32 at a time.
132 */
133 for (index = MIN_SPI_ID; index < num_ints; index += 32)
134 gicd_write_igroupr(gicd_base, index, ~0U);
135
136 /* Setup the default SPI priorities doing four at a time */
137 for (index = MIN_SPI_ID; index < num_ints; index += 4)
138 gicd_write_ipriorityr(gicd_base,
139 index,
140 GICD_IPRIORITYR_DEF_VAL);
141
142 /* Treat all SPIs as level triggered by default, 16 at a time */
143 for (index = MIN_SPI_ID; index < num_ints; index += 16)
144 gicd_write_icfgr(gicd_base, index, 0);
145}
146
147/*******************************************************************************
148 * Helper function to configure secure G0 SPIs.
149 ******************************************************************************/
150void gicv2_secure_spis_configure(uintptr_t gicd_base,
151 unsigned int num_ints,
152 const unsigned int *sec_intr_list)
153{
154 unsigned int index, irq_num;
155
156 /* If `num_ints` is not 0, ensure that `sec_intr_list` is not NULL */
157 assert(num_ints ? (uintptr_t)sec_intr_list : 1);
158
159 for (index = 0; index < num_ints; index++) {
160 irq_num = sec_intr_list[index];
161 if (irq_num >= MIN_SPI_ID) {
162 /* Configure this interrupt as a secure interrupt */
163 gicd_clr_igroupr(gicd_base, irq_num);
164
165 /* Set the priority of this interrupt */
Soby Mathew421259e2016-01-15 14:20:57 +0000166 gicd_set_ipriorityr(gicd_base,
Soby Mathewe063d3c2015-10-07 09:45:27 +0100167 irq_num,
168 GIC_HIGHEST_SEC_PRIORITY);
169
170 /* Target the secure interrupts to primary CPU */
171 gicd_set_itargetsr(gicd_base, irq_num,
172 gicv2_get_cpuif_id(gicd_base));
173
174 /* Enable this interrupt */
175 gicd_set_isenabler(gicd_base, irq_num);
176 }
177 }
178
179}
180
181/*******************************************************************************
182 * Helper function to configure secure G0 SGIs and PPIs.
183 ******************************************************************************/
184void gicv2_secure_ppi_sgi_setup(uintptr_t gicd_base,
185 unsigned int num_ints,
186 const unsigned int *sec_intr_list)
187{
188 unsigned int index, irq_num, sec_ppi_sgi_mask = 0;
189
190 /* If `num_ints` is not 0, ensure that `sec_intr_list` is not NULL */
191 assert(num_ints ? (uintptr_t)sec_intr_list : 1);
192
193 /*
194 * Disable all SGIs (imp. def.)/PPIs before configuring them. This is a
195 * more scalable approach as it avoids clearing the enable bits in the
196 * GICD_CTLR.
197 */
198 gicd_write_icenabler(gicd_base, 0, ~0);
199
200 /* Setup the default PPI/SGI priorities doing four at a time */
201 for (index = 0; index < MIN_SPI_ID; index += 4)
202 gicd_write_ipriorityr(gicd_base,
203 index,
204 GICD_IPRIORITYR_DEF_VAL);
205
206 for (index = 0; index < num_ints; index++) {
207 irq_num = sec_intr_list[index];
208 if (irq_num < MIN_SPI_ID) {
209 /* We have an SGI or a PPI. They are Group0 at reset */
210 sec_ppi_sgi_mask |= 1U << irq_num;
211
212 /* Set the priority of this interrupt */
Soby Mathew421259e2016-01-15 14:20:57 +0000213 gicd_set_ipriorityr(gicd_base,
Soby Mathewe063d3c2015-10-07 09:45:27 +0100214 irq_num,
215 GIC_HIGHEST_SEC_PRIORITY);
216 }
217 }
218
219 /*
220 * Invert the bitmask to create a mask for non-secure PPIs and
221 * SGIs. Program the GICD_IGROUPR0 with this bit mask.
222 */
223 gicd_write_igroupr(gicd_base, 0, ~sec_ppi_sgi_mask);
224
225 /* Enable the Group 0 SGIs and PPIs */
226 gicd_write_isenabler(gicd_base, 0, sec_ppi_sgi_mask);
227}