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