blob: e85dbc13d61a6b3d24905049e4fc70a51a8d3582 [file] [log] [blame]
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +05301/*
2 * Copyright (c) 2019, Arm Limited. All rights reserved.
Varun Wadekar7ef3c7e2022-05-06 13:18:49 +01003 * Copyright (c) 2022, NVIDIA Corporation. All rights reserved.
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +05304 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8/*
9 * GIC-600 driver extension for multichip setup
10 */
11
12#include <assert.h>
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +053013
Max Shvetsov0ac39412019-11-19 11:01:26 +000014#include <common/debug.h>
Andre Przywara9e1dc682021-05-18 15:46:58 +010015#include <drivers/arm/arm_gicv3_common.h>
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +053016#include <drivers/arm/gic600_multichip.h>
Max Shvetsov0ac39412019-11-19 11:01:26 +000017#include <drivers/arm/gicv3.h>
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +053018
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +053019#include "../common/gic_common_private.h"
Max Shvetsov0ac39412019-11-19 11:01:26 +000020#include "gic600_multichip_private.h"
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +053021
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +053022/*******************************************************************************
23 * GIC-600 multichip operation related helper functions
24 ******************************************************************************/
25static void gicd_dchipr_wait_for_power_update_progress(uintptr_t base)
26{
27 unsigned int retry = GICD_PUP_UPDATE_RETRIES;
28
29 while ((read_gicd_dchipr(base) & GICD_DCHIPR_PUP_BIT) != 0U) {
30 if (retry-- == 0) {
31 ERROR("GIC-600 connection to Routing Table Owner timed "
32 "out\n");
33 panic();
34 }
35 }
36}
37
38/*******************************************************************************
39 * Sets up the routing table owner.
40 ******************************************************************************/
41static void set_gicd_dchipr_rt_owner(uintptr_t base, unsigned int rt_owner)
42{
43 /*
44 * Ensure that Group enables in GICD_CTLR are disabled and no pending
45 * register writes to GICD_CTLR.
46 */
47 if ((gicd_read_ctlr(base) &
48 (CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1S_BIT |
49 CTLR_ENABLE_G1NS_BIT | GICD_CTLR_RWP_BIT)) != 0) {
50 ERROR("GICD_CTLR group interrupts are either enabled or have "
51 "pending writes. Cannot set RT owner.\n");
52 panic();
53 }
54
55 /* Poll till PUP is zero before intiating write */
56 gicd_dchipr_wait_for_power_update_progress(base);
57
58 write_gicd_dchipr(base, read_gicd_dchipr(base) |
59 (rt_owner << GICD_DCHIPR_RT_OWNER_SHIFT));
60
61 /* Poll till PUP is zero to ensure write is complete */
62 gicd_dchipr_wait_for_power_update_progress(base);
63}
64
65/*******************************************************************************
66 * Configures the Chip Register to make connections to GICDs on
67 * a multichip platform.
68 ******************************************************************************/
69static void set_gicd_chipr_n(uintptr_t base,
70 unsigned int chip_id,
71 uint64_t chip_addr,
72 unsigned int spi_id_min,
73 unsigned int spi_id_max)
74{
75 unsigned int spi_block_min, spi_blocks;
Andre Przywara9e1dc682021-05-18 15:46:58 +010076 unsigned int gicd_iidr_val = gicd_read_iidr(base);
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +053077 uint64_t chipr_n_val;
78
79 /*
80 * Ensure that group enables in GICD_CTLR are disabled and no pending
81 * register writes to GICD_CTLR.
82 */
83 if ((gicd_read_ctlr(base) &
84 (CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1S_BIT |
85 CTLR_ENABLE_G1NS_BIT | GICD_CTLR_RWP_BIT)) != 0) {
86 ERROR("GICD_CTLR group interrupts are either enabled or have "
87 "pending writes. Cannot set CHIPR register.\n");
88 panic();
89 }
90
91 /*
92 * spi_id_min and spi_id_max of value 0 is used to intidicate that the
93 * chip doesn't own any SPI block. Re-assign min and max values as SPI
94 * id starts from 32.
95 */
96 if (spi_id_min == 0 && spi_id_max == 0) {
97 spi_id_min = GIC600_SPI_ID_MIN;
98 spi_id_max = GIC600_SPI_ID_MIN;
99 }
100
Andre Przywara9e1dc682021-05-18 15:46:58 +0100101 switch ((gicd_iidr_val & IIDR_MODEL_MASK)) {
102 case IIDR_MODEL_ARM_GIC_600:
Varun Wadekar7ef3c7e2022-05-06 13:18:49 +0100103 spi_block_min = SPI_BLOCK_MIN_VALUE(spi_id_min);
104 spi_blocks = SPI_BLOCKS_VALUE(spi_id_min, spi_id_max);
105
Andre Przywara9e1dc682021-05-18 15:46:58 +0100106 chipr_n_val = GICD_CHIPR_VALUE_GIC_600(chip_addr,
107 spi_block_min,
108 spi_blocks);
109 break;
110 case IIDR_MODEL_ARM_GIC_700:
Varun Wadekar7ef3c7e2022-05-06 13:18:49 +0100111 /* Calculate the SPI_ID_MIN value for ESPI */
112 if (spi_id_min >= GIC700_ESPI_ID_MIN) {
113 spi_block_min = ESPI_BLOCK_MIN_VALUE(spi_id_min);
114 spi_block_min += SPI_BLOCKS_VALUE(GIC700_SPI_ID_MIN,
115 GIC700_SPI_ID_MAX);
116 } else {
117 spi_block_min = SPI_BLOCK_MIN_VALUE(spi_id_min);
118 }
119
120 /* Calculate the total number of blocks */
121 spi_blocks = SPI_BLOCKS_VALUE(spi_id_min, spi_id_max);
122
Andre Przywara9e1dc682021-05-18 15:46:58 +0100123 chipr_n_val = GICD_CHIPR_VALUE_GIC_700(chip_addr,
124 spi_block_min,
125 spi_blocks);
126 break;
127 default:
128 ERROR("Unsupported GIC model 0x%x for multichip setup.\n",
129 gicd_iidr_val);
130 panic();
131 break;
132 }
133 chipr_n_val |= GICD_CHIPRx_SOCKET_STATE;
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +0530134
135 /*
136 * Wait for DCHIPR.PUP to be zero before commencing writes to
137 * GICD_CHIPRx.
138 */
139 gicd_dchipr_wait_for_power_update_progress(base);
140
141 /*
142 * Assign chip addr, spi min block, number of spi blocks and bring chip
143 * online by setting SocketState.
144 */
145 write_gicd_chipr_n(base, chip_id, chipr_n_val);
146
147 /*
148 * Poll until DCHIP.PUP is zero to verify connection to rt_owner chip
149 * is complete.
150 */
151 gicd_dchipr_wait_for_power_update_progress(base);
152
153 /*
154 * Ensure that write to GICD_CHIPRx is successful and the chip_n came
155 * online.
156 */
157 if (read_gicd_chipr_n(base, chip_id) != chipr_n_val) {
158 ERROR("GICD_CHIPR%u write failed\n", chip_id);
159 panic();
160 }
161
162 /* Ensure that chip is in consistent state */
163 if (((read_gicd_chipsr(base) & GICD_CHIPSR_RTS_MASK) >>
164 GICD_CHIPSR_RTS_SHIFT) !=
165 GICD_CHIPSR_RTS_STATE_CONSISTENT) {
166 ERROR("Chip %u routing table is not in consistent state\n",
167 chip_id);
168 panic();
169 }
170}
171
172/*******************************************************************************
173 * Validates the GIC-600 Multichip data structure passed by the platform.
174 ******************************************************************************/
175static void gic600_multichip_validate_data(
176 struct gic600_multichip_data *multichip_data)
177{
178 unsigned int i, spi_id_min, spi_id_max, blocks_of_32;
179 unsigned int multichip_spi_blocks = 0;
180
181 assert(multichip_data != NULL);
182
183 if (multichip_data->chip_count > GIC600_MAX_MULTICHIP) {
184 ERROR("GIC-600 Multichip count should not exceed %d\n",
185 GIC600_MAX_MULTICHIP);
186 panic();
187 }
188
189 for (i = 0; i < multichip_data->chip_count; i++) {
190 spi_id_min = multichip_data->spi_ids[i][SPI_MIN_INDEX];
191 spi_id_max = multichip_data->spi_ids[i][SPI_MAX_INDEX];
192
193 if ((spi_id_min != 0) || (spi_id_max != 0)) {
194
195 /* SPI IDs range check */
196 if (!(spi_id_min >= GIC600_SPI_ID_MIN) ||
197 !(spi_id_max < GIC600_SPI_ID_MAX) ||
198 !(spi_id_min <= spi_id_max) ||
199 !((spi_id_max - spi_id_min + 1) % 32 == 0)) {
200 ERROR("Invalid SPI IDs {%u, %u} passed for "
201 "Chip %u\n", spi_id_min,
202 spi_id_max, i);
203 panic();
204 }
205
206 /* SPI IDs overlap check */
207 blocks_of_32 = BLOCKS_OF_32(spi_id_min, spi_id_max);
208 if ((multichip_spi_blocks & blocks_of_32) != 0) {
209 ERROR("SPI IDs of Chip %u overlapping\n", i);
210 panic();
211 }
212 multichip_spi_blocks |= blocks_of_32;
213 }
214 }
215}
216
217/*******************************************************************************
Varun Wadekar7ef3c7e2022-05-06 13:18:49 +0100218 * Validates the GIC-700 Multichip data structure passed by the platform.
219 ******************************************************************************/
220static void gic700_multichip_validate_data(
221 struct gic600_multichip_data *multichip_data)
222{
223 unsigned int i, spi_id_min, spi_id_max, blocks_of_32;
224 unsigned int multichip_spi_blocks = 0U, multichip_espi_blocks = 0U;
225
226 assert(multichip_data != NULL);
227
228 if (multichip_data->chip_count > GIC600_MAX_MULTICHIP) {
229 ERROR("GIC-700 Multichip count (%u) should not exceed %u\n",
230 multichip_data->chip_count, GIC600_MAX_MULTICHIP);
231 panic();
232 }
233
234 for (i = 0U; i < multichip_data->chip_count; i++) {
235 spi_id_min = multichip_data->spi_ids[i][SPI_MIN_INDEX];
236 spi_id_max = multichip_data->spi_ids[i][SPI_MAX_INDEX];
237
238 if ((spi_id_min == 0U) || (spi_id_max == 0U)) {
239 continue;
240 }
241
242 /* MIN SPI ID check */
243 if ((spi_id_min < GIC700_SPI_ID_MIN) ||
244 ((spi_id_min >= GIC700_SPI_ID_MAX) &&
245 (spi_id_min < GIC700_ESPI_ID_MIN))) {
246 ERROR("Invalid MIN SPI ID {%u} passed for "
247 "Chip %u\n", spi_id_min, i);
248 panic();
249 }
250
251 if ((spi_id_min > spi_id_max) ||
252 ((spi_id_max - spi_id_min + 1) % 32 != 0)) {
253 ERROR("Unaligned SPI IDs {%u, %u} passed for "
254 "Chip %u\n", spi_id_min,
255 spi_id_max, i);
256 panic();
257 }
258
259 /* ESPI IDs range check */
260 if ((spi_id_min >= GIC700_ESPI_ID_MIN) &&
261 (spi_id_max > GIC700_ESPI_ID_MAX)) {
262 ERROR("Invalid ESPI IDs {%u, %u} passed for "
263 "Chip %u\n", spi_id_min,
264 spi_id_max, i);
265 panic();
266
267 }
268
269 /* SPI IDs range check */
270 if (((spi_id_min < GIC700_SPI_ID_MAX) &&
271 (spi_id_max > GIC700_SPI_ID_MAX))) {
272 ERROR("Invalid SPI IDs {%u, %u} passed for "
273 "Chip %u\n", spi_id_min,
274 spi_id_max, i);
275 panic();
276 }
277
278 /* SPI IDs overlap check */
279 if (spi_id_max < GIC700_SPI_ID_MAX) {
280 blocks_of_32 = BLOCKS_OF_32(spi_id_min, spi_id_max);
281 if ((multichip_spi_blocks & blocks_of_32) != 0) {
282 ERROR("SPI IDs of Chip %u overlapping\n", i);
283 panic();
284 }
285 multichip_spi_blocks |= blocks_of_32;
286 }
287
288 /* ESPI IDs overlap check */
289 if (spi_id_max > GIC700_ESPI_ID_MIN) {
290 blocks_of_32 = BLOCKS_OF_32(spi_id_min - GIC700_ESPI_ID_MIN,
291 spi_id_max - GIC700_ESPI_ID_MIN);
292 if ((multichip_espi_blocks & blocks_of_32) != 0) {
293 ERROR("SPI IDs of Chip %u overlapping\n", i);
294 panic();
295 }
296 multichip_espi_blocks |= blocks_of_32;
297 }
298 }
299}
300
301/*******************************************************************************
302 * Intialize GIC-600 and GIC-700 Multichip operation.
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +0530303 ******************************************************************************/
304void gic600_multichip_init(struct gic600_multichip_data *multichip_data)
305{
306 unsigned int i;
Varun Wadekar7ef3c7e2022-05-06 13:18:49 +0100307 uint32_t gicd_iidr_val = gicd_read_iidr(multichip_data->rt_owner_base);
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +0530308
Varun Wadekar7ef3c7e2022-05-06 13:18:49 +0100309 if ((gicd_iidr_val & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) {
310 gic600_multichip_validate_data(multichip_data);
311 }
312
313 if ((gicd_iidr_val & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_700) {
314 gic700_multichip_validate_data(multichip_data);
315 }
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +0530316
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +0530317 /*
318 * Ensure that G0/G1S/G1NS interrupts are disabled. This also ensures
319 * that GIC-600 Multichip configuration is done first.
320 */
321 if ((gicd_read_ctlr(multichip_data->rt_owner_base) &
322 (CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1S_BIT |
323 CTLR_ENABLE_G1NS_BIT | GICD_CTLR_RWP_BIT)) != 0) {
324 ERROR("GICD_CTLR group interrupts are either enabled or have "
325 "pending writes.\n");
326 panic();
327 }
328
329 /* Ensure that the routing table owner is in disconnected state */
330 if (((read_gicd_chipsr(multichip_data->rt_owner_base) &
331 GICD_CHIPSR_RTS_MASK) >> GICD_CHIPSR_RTS_SHIFT) !=
332 GICD_CHIPSR_RTS_STATE_DISCONNECTED) {
333 ERROR("GIC-600 routing table owner is not in disconnected "
334 "state to begin multichip configuration\n");
335 panic();
336 }
337
338 /* Initialize the GICD which is marked as routing table owner first */
339 set_gicd_dchipr_rt_owner(multichip_data->rt_owner_base,
340 multichip_data->rt_owner);
341
342 set_gicd_chipr_n(multichip_data->rt_owner_base, multichip_data->rt_owner,
343 multichip_data->chip_addrs[multichip_data->rt_owner],
344 multichip_data->
345 spi_ids[multichip_data->rt_owner][SPI_MIN_INDEX],
346 multichip_data->
347 spi_ids[multichip_data->rt_owner][SPI_MAX_INDEX]);
348
349 for (i = 0; i < multichip_data->chip_count; i++) {
350 if (i == multichip_data->rt_owner)
351 continue;
352
353 set_gicd_chipr_n(multichip_data->rt_owner_base, i,
354 multichip_data->chip_addrs[i],
355 multichip_data->spi_ids[i][SPI_MIN_INDEX],
356 multichip_data->spi_ids[i][SPI_MAX_INDEX]);
357 }
358}