blob: 26930769b16cbd70f85b4e1d89e0fb776555005f [file] [log] [blame]
Soby Mathewe063d3c2015-10-07 09:45:27 +01001/*
Jeenu Viswambharandce70b32017-09-22 08:32:09 +01002 * Copyright (c) 2015-2017, 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
Soby Mathewe063d3c2015-10-07 09:45:27 +010075/*******************************************************************************
76 * Get the current CPU bit mask from GICD_ITARGETSR0
77 ******************************************************************************/
78unsigned int gicv2_get_cpuif_id(uintptr_t base)
79{
80 unsigned int val;
81
82 val = gicd_read_itargetsr(base, 0);
83 return val & GIC_TARGET_CPU_MASK;
84}
85
86/*******************************************************************************
87 * Helper function to configure the default attributes of SPIs.
88 ******************************************************************************/
89void gicv2_spis_configure_defaults(uintptr_t gicd_base)
90{
91 unsigned int index, num_ints;
92
93 num_ints = gicd_read_typer(gicd_base);
94 num_ints &= TYPER_IT_LINES_NO_MASK;
95 num_ints = (num_ints + 1) << 5;
96
97 /*
98 * Treat all SPIs as G1NS by default. The number of interrupts is
99 * calculated as 32 * (IT_LINES + 1). We do 32 at a time.
100 */
101 for (index = MIN_SPI_ID; index < num_ints; index += 32)
102 gicd_write_igroupr(gicd_base, index, ~0U);
103
104 /* Setup the default SPI priorities doing four at a time */
105 for (index = MIN_SPI_ID; index < num_ints; index += 4)
106 gicd_write_ipriorityr(gicd_base,
107 index,
108 GICD_IPRIORITYR_DEF_VAL);
109
110 /* Treat all SPIs as level triggered by default, 16 at a time */
111 for (index = MIN_SPI_ID; index < num_ints; index += 16)
112 gicd_write_icfgr(gicd_base, index, 0);
113}
114
115/*******************************************************************************
116 * Helper function to configure secure G0 SPIs.
117 ******************************************************************************/
118void gicv2_secure_spis_configure(uintptr_t gicd_base,
119 unsigned int num_ints,
120 const unsigned int *sec_intr_list)
121{
122 unsigned int index, irq_num;
123
124 /* If `num_ints` is not 0, ensure that `sec_intr_list` is not NULL */
125 assert(num_ints ? (uintptr_t)sec_intr_list : 1);
126
127 for (index = 0; index < num_ints; index++) {
128 irq_num = sec_intr_list[index];
129 if (irq_num >= MIN_SPI_ID) {
130 /* Configure this interrupt as a secure interrupt */
131 gicd_clr_igroupr(gicd_base, irq_num);
132
133 /* Set the priority of this interrupt */
Soby Mathew421259e2016-01-15 14:20:57 +0000134 gicd_set_ipriorityr(gicd_base,
Soby Mathewe063d3c2015-10-07 09:45:27 +0100135 irq_num,
136 GIC_HIGHEST_SEC_PRIORITY);
137
138 /* Target the secure interrupts to primary CPU */
139 gicd_set_itargetsr(gicd_base, irq_num,
140 gicv2_get_cpuif_id(gicd_base));
141
142 /* Enable this interrupt */
143 gicd_set_isenabler(gicd_base, irq_num);
144 }
145 }
146
147}
148
149/*******************************************************************************
150 * Helper function to configure secure G0 SGIs and PPIs.
151 ******************************************************************************/
152void gicv2_secure_ppi_sgi_setup(uintptr_t gicd_base,
153 unsigned int num_ints,
154 const unsigned int *sec_intr_list)
155{
156 unsigned int index, irq_num, sec_ppi_sgi_mask = 0;
157
158 /* If `num_ints` is not 0, ensure that `sec_intr_list` is not NULL */
159 assert(num_ints ? (uintptr_t)sec_intr_list : 1);
160
161 /*
162 * Disable all SGIs (imp. def.)/PPIs before configuring them. This is a
163 * more scalable approach as it avoids clearing the enable bits in the
164 * GICD_CTLR.
165 */
166 gicd_write_icenabler(gicd_base, 0, ~0);
167
168 /* Setup the default PPI/SGI priorities doing four at a time */
169 for (index = 0; index < MIN_SPI_ID; index += 4)
170 gicd_write_ipriorityr(gicd_base,
171 index,
172 GICD_IPRIORITYR_DEF_VAL);
173
174 for (index = 0; index < num_ints; index++) {
175 irq_num = sec_intr_list[index];
176 if (irq_num < MIN_SPI_ID) {
177 /* We have an SGI or a PPI. They are Group0 at reset */
178 sec_ppi_sgi_mask |= 1U << irq_num;
179
180 /* Set the priority of this interrupt */
Soby Mathew421259e2016-01-15 14:20:57 +0000181 gicd_set_ipriorityr(gicd_base,
Soby Mathewe063d3c2015-10-07 09:45:27 +0100182 irq_num,
183 GIC_HIGHEST_SEC_PRIORITY);
184 }
185 }
186
187 /*
188 * Invert the bitmask to create a mask for non-secure PPIs and
189 * SGIs. Program the GICD_IGROUPR0 with this bit mask.
190 */
191 gicd_write_igroupr(gicd_base, 0, ~sec_ppi_sgi_mask);
192
193 /* Enable the Group 0 SGIs and PPIs */
194 gicd_write_isenabler(gicd_base, 0, sec_ppi_sgi_mask);
195}