blob: 5e44aa95c1f98f3150b9ae367a769507469896ba [file] [log] [blame]
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +05301/*
Harrison Mutai53aa28c2024-03-20 11:38:07 +00002 * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
Varun Wadekar61286d22023-03-08 16:47:38 +00003 * Copyright (c) 2022-2023, 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
Varun Wadekar61286d22023-03-08 16:47:38 +000022static struct gic600_multichip_data *plat_gic_multichip_data;
23
24/*******************************************************************************
25 * Retrieve the address of the chip owner for a given SPI ID
26 ******************************************************************************/
27uintptr_t gic600_multichip_gicd_base_for_spi(uint32_t spi_id)
28{
29 unsigned int i;
30
31 /* Find the multichip instance */
32 for (i = 0U; i < GIC600_MAX_MULTICHIP; i++) {
33 if ((spi_id <= plat_gic_multichip_data->spi_ids[i].spi_id_max) &&
34 (spi_id >= plat_gic_multichip_data->spi_ids[i].spi_id_min)) {
35 break;
36 }
37 }
38
39 /* Ensure that plat_gic_multichip_data contains valid values */
40 assert(i < GIC600_MAX_MULTICHIP);
41
42 return plat_gic_multichip_data->spi_ids[i].gicd_base;
43}
44
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +053045/*******************************************************************************
46 * GIC-600 multichip operation related helper functions
47 ******************************************************************************/
48static void gicd_dchipr_wait_for_power_update_progress(uintptr_t base)
49{
50 unsigned int retry = GICD_PUP_UPDATE_RETRIES;
51
52 while ((read_gicd_dchipr(base) & GICD_DCHIPR_PUP_BIT) != 0U) {
Varun Wadekar61286d22023-03-08 16:47:38 +000053 if (retry-- == 0U) {
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +053054 ERROR("GIC-600 connection to Routing Table Owner timed "
55 "out\n");
56 panic();
57 }
58 }
59}
60
61/*******************************************************************************
62 * Sets up the routing table owner.
63 ******************************************************************************/
64static void set_gicd_dchipr_rt_owner(uintptr_t base, unsigned int rt_owner)
65{
66 /*
67 * Ensure that Group enables in GICD_CTLR are disabled and no pending
68 * register writes to GICD_CTLR.
69 */
70 if ((gicd_read_ctlr(base) &
71 (CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1S_BIT |
72 CTLR_ENABLE_G1NS_BIT | GICD_CTLR_RWP_BIT)) != 0) {
73 ERROR("GICD_CTLR group interrupts are either enabled or have "
74 "pending writes. Cannot set RT owner.\n");
75 panic();
76 }
77
Harrison Mutai53aa28c2024-03-20 11:38:07 +000078 /* Poll till PUP is zero before initiating write */
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +053079 gicd_dchipr_wait_for_power_update_progress(base);
80
81 write_gicd_dchipr(base, read_gicd_dchipr(base) |
82 (rt_owner << GICD_DCHIPR_RT_OWNER_SHIFT));
83
84 /* Poll till PUP is zero to ensure write is complete */
85 gicd_dchipr_wait_for_power_update_progress(base);
86}
87
88/*******************************************************************************
89 * Configures the Chip Register to make connections to GICDs on
90 * a multichip platform.
91 ******************************************************************************/
92static void set_gicd_chipr_n(uintptr_t base,
93 unsigned int chip_id,
94 uint64_t chip_addr,
95 unsigned int spi_id_min,
96 unsigned int spi_id_max)
97{
98 unsigned int spi_block_min, spi_blocks;
Andre Przywara9e1dc682021-05-18 15:46:58 +010099 unsigned int gicd_iidr_val = gicd_read_iidr(base);
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +0530100 uint64_t chipr_n_val;
101
102 /*
103 * Ensure that group enables in GICD_CTLR are disabled and no pending
104 * register writes to GICD_CTLR.
105 */
106 if ((gicd_read_ctlr(base) &
107 (CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1S_BIT |
108 CTLR_ENABLE_G1NS_BIT | GICD_CTLR_RWP_BIT)) != 0) {
109 ERROR("GICD_CTLR group interrupts are either enabled or have "
110 "pending writes. Cannot set CHIPR register.\n");
111 panic();
112 }
113
114 /*
115 * spi_id_min and spi_id_max of value 0 is used to intidicate that the
116 * chip doesn't own any SPI block. Re-assign min and max values as SPI
117 * id starts from 32.
118 */
119 if (spi_id_min == 0 && spi_id_max == 0) {
120 spi_id_min = GIC600_SPI_ID_MIN;
121 spi_id_max = GIC600_SPI_ID_MIN;
122 }
123
Andre Przywara9e1dc682021-05-18 15:46:58 +0100124 switch ((gicd_iidr_val & IIDR_MODEL_MASK)) {
125 case IIDR_MODEL_ARM_GIC_600:
Varun Wadekar7ef3c7e2022-05-06 13:18:49 +0100126 spi_block_min = SPI_BLOCK_MIN_VALUE(spi_id_min);
127 spi_blocks = SPI_BLOCKS_VALUE(spi_id_min, spi_id_max);
128
Andre Przywara9e1dc682021-05-18 15:46:58 +0100129 chipr_n_val = GICD_CHIPR_VALUE_GIC_600(chip_addr,
130 spi_block_min,
131 spi_blocks);
132 break;
133 case IIDR_MODEL_ARM_GIC_700:
Varun Wadekar7ef3c7e2022-05-06 13:18:49 +0100134 /* Calculate the SPI_ID_MIN value for ESPI */
135 if (spi_id_min >= GIC700_ESPI_ID_MIN) {
136 spi_block_min = ESPI_BLOCK_MIN_VALUE(spi_id_min);
137 spi_block_min += SPI_BLOCKS_VALUE(GIC700_SPI_ID_MIN,
138 GIC700_SPI_ID_MAX);
139 } else {
140 spi_block_min = SPI_BLOCK_MIN_VALUE(spi_id_min);
141 }
142
143 /* Calculate the total number of blocks */
144 spi_blocks = SPI_BLOCKS_VALUE(spi_id_min, spi_id_max);
145
Andre Przywara9e1dc682021-05-18 15:46:58 +0100146 chipr_n_val = GICD_CHIPR_VALUE_GIC_700(chip_addr,
147 spi_block_min,
148 spi_blocks);
149 break;
150 default:
151 ERROR("Unsupported GIC model 0x%x for multichip setup.\n",
152 gicd_iidr_val);
153 panic();
154 break;
155 }
156 chipr_n_val |= GICD_CHIPRx_SOCKET_STATE;
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +0530157
158 /*
159 * Wait for DCHIPR.PUP to be zero before commencing writes to
160 * GICD_CHIPRx.
161 */
162 gicd_dchipr_wait_for_power_update_progress(base);
163
164 /*
165 * Assign chip addr, spi min block, number of spi blocks and bring chip
166 * online by setting SocketState.
167 */
168 write_gicd_chipr_n(base, chip_id, chipr_n_val);
169
170 /*
171 * Poll until DCHIP.PUP is zero to verify connection to rt_owner chip
172 * is complete.
173 */
174 gicd_dchipr_wait_for_power_update_progress(base);
175
176 /*
177 * Ensure that write to GICD_CHIPRx is successful and the chip_n came
178 * online.
179 */
180 if (read_gicd_chipr_n(base, chip_id) != chipr_n_val) {
181 ERROR("GICD_CHIPR%u write failed\n", chip_id);
182 panic();
183 }
184
185 /* Ensure that chip is in consistent state */
186 if (((read_gicd_chipsr(base) & GICD_CHIPSR_RTS_MASK) >>
187 GICD_CHIPSR_RTS_SHIFT) !=
188 GICD_CHIPSR_RTS_STATE_CONSISTENT) {
189 ERROR("Chip %u routing table is not in consistent state\n",
190 chip_id);
191 panic();
192 }
193}
194
195/*******************************************************************************
196 * Validates the GIC-600 Multichip data structure passed by the platform.
197 ******************************************************************************/
198static void gic600_multichip_validate_data(
199 struct gic600_multichip_data *multichip_data)
200{
201 unsigned int i, spi_id_min, spi_id_max, blocks_of_32;
202 unsigned int multichip_spi_blocks = 0;
203
204 assert(multichip_data != NULL);
205
206 if (multichip_data->chip_count > GIC600_MAX_MULTICHIP) {
207 ERROR("GIC-600 Multichip count should not exceed %d\n",
208 GIC600_MAX_MULTICHIP);
209 panic();
210 }
211
Varun Wadekar61286d22023-03-08 16:47:38 +0000212 for (i = 0U; i < multichip_data->chip_count; i++) {
213 spi_id_min = multichip_data->spi_ids[i].spi_id_min;
214 spi_id_max = multichip_data->spi_ids[i].spi_id_max;
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +0530215
Varun Wadekar61286d22023-03-08 16:47:38 +0000216 if ((spi_id_min != 0U) || (spi_id_max != 0U)) {
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +0530217
218 /* SPI IDs range check */
219 if (!(spi_id_min >= GIC600_SPI_ID_MIN) ||
sahild71693e2023-06-06 11:20:57 +0530220 !(spi_id_max <= GIC600_SPI_ID_MAX) ||
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +0530221 !(spi_id_min <= spi_id_max) ||
222 !((spi_id_max - spi_id_min + 1) % 32 == 0)) {
223 ERROR("Invalid SPI IDs {%u, %u} passed for "
224 "Chip %u\n", spi_id_min,
225 spi_id_max, i);
226 panic();
227 }
228
229 /* SPI IDs overlap check */
230 blocks_of_32 = BLOCKS_OF_32(spi_id_min, spi_id_max);
231 if ((multichip_spi_blocks & blocks_of_32) != 0) {
232 ERROR("SPI IDs of Chip %u overlapping\n", i);
233 panic();
234 }
235 multichip_spi_blocks |= blocks_of_32;
236 }
237 }
238}
239
240/*******************************************************************************
Varun Wadekar7ef3c7e2022-05-06 13:18:49 +0100241 * Validates the GIC-700 Multichip data structure passed by the platform.
242 ******************************************************************************/
243static void gic700_multichip_validate_data(
244 struct gic600_multichip_data *multichip_data)
245{
246 unsigned int i, spi_id_min, spi_id_max, blocks_of_32;
247 unsigned int multichip_spi_blocks = 0U, multichip_espi_blocks = 0U;
248
249 assert(multichip_data != NULL);
250
251 if (multichip_data->chip_count > GIC600_MAX_MULTICHIP) {
252 ERROR("GIC-700 Multichip count (%u) should not exceed %u\n",
253 multichip_data->chip_count, GIC600_MAX_MULTICHIP);
254 panic();
255 }
256
257 for (i = 0U; i < multichip_data->chip_count; i++) {
Varun Wadekar61286d22023-03-08 16:47:38 +0000258 spi_id_min = multichip_data->spi_ids[i].spi_id_min;
259 spi_id_max = multichip_data->spi_ids[i].spi_id_max;
Varun Wadekar7ef3c7e2022-05-06 13:18:49 +0100260
261 if ((spi_id_min == 0U) || (spi_id_max == 0U)) {
262 continue;
263 }
264
265 /* MIN SPI ID check */
266 if ((spi_id_min < GIC700_SPI_ID_MIN) ||
267 ((spi_id_min >= GIC700_SPI_ID_MAX) &&
268 (spi_id_min < GIC700_ESPI_ID_MIN))) {
269 ERROR("Invalid MIN SPI ID {%u} passed for "
270 "Chip %u\n", spi_id_min, i);
271 panic();
272 }
273
274 if ((spi_id_min > spi_id_max) ||
275 ((spi_id_max - spi_id_min + 1) % 32 != 0)) {
276 ERROR("Unaligned SPI IDs {%u, %u} passed for "
277 "Chip %u\n", spi_id_min,
278 spi_id_max, i);
279 panic();
280 }
281
282 /* ESPI IDs range check */
283 if ((spi_id_min >= GIC700_ESPI_ID_MIN) &&
284 (spi_id_max > GIC700_ESPI_ID_MAX)) {
285 ERROR("Invalid ESPI IDs {%u, %u} passed for "
286 "Chip %u\n", spi_id_min,
287 spi_id_max, i);
288 panic();
289
290 }
291
292 /* SPI IDs range check */
293 if (((spi_id_min < GIC700_SPI_ID_MAX) &&
294 (spi_id_max > GIC700_SPI_ID_MAX))) {
295 ERROR("Invalid SPI IDs {%u, %u} passed for "
296 "Chip %u\n", spi_id_min,
297 spi_id_max, i);
298 panic();
299 }
300
301 /* SPI IDs overlap check */
302 if (spi_id_max < GIC700_SPI_ID_MAX) {
303 blocks_of_32 = BLOCKS_OF_32(spi_id_min, spi_id_max);
304 if ((multichip_spi_blocks & blocks_of_32) != 0) {
305 ERROR("SPI IDs of Chip %u overlapping\n", i);
306 panic();
307 }
308 multichip_spi_blocks |= blocks_of_32;
309 }
310
311 /* ESPI IDs overlap check */
312 if (spi_id_max > GIC700_ESPI_ID_MIN) {
313 blocks_of_32 = BLOCKS_OF_32(spi_id_min - GIC700_ESPI_ID_MIN,
314 spi_id_max - GIC700_ESPI_ID_MIN);
315 if ((multichip_espi_blocks & blocks_of_32) != 0) {
316 ERROR("SPI IDs of Chip %u overlapping\n", i);
317 panic();
318 }
319 multichip_espi_blocks |= blocks_of_32;
320 }
321 }
322}
323
324/*******************************************************************************
Elyes Haouas2be03c02023-02-13 09:14:48 +0100325 * Initialize GIC-600 and GIC-700 Multichip operation.
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +0530326 ******************************************************************************/
327void gic600_multichip_init(struct gic600_multichip_data *multichip_data)
328{
329 unsigned int i;
Varun Wadekar7ef3c7e2022-05-06 13:18:49 +0100330 uint32_t gicd_iidr_val = gicd_read_iidr(multichip_data->rt_owner_base);
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +0530331
Varun Wadekar7ef3c7e2022-05-06 13:18:49 +0100332 if ((gicd_iidr_val & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) {
333 gic600_multichip_validate_data(multichip_data);
334 }
335
336 if ((gicd_iidr_val & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_700) {
337 gic700_multichip_validate_data(multichip_data);
338 }
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +0530339
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +0530340 /*
341 * Ensure that G0/G1S/G1NS interrupts are disabled. This also ensures
342 * that GIC-600 Multichip configuration is done first.
343 */
344 if ((gicd_read_ctlr(multichip_data->rt_owner_base) &
345 (CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1S_BIT |
346 CTLR_ENABLE_G1NS_BIT | GICD_CTLR_RWP_BIT)) != 0) {
347 ERROR("GICD_CTLR group interrupts are either enabled or have "
348 "pending writes.\n");
349 panic();
350 }
351
352 /* Ensure that the routing table owner is in disconnected state */
353 if (((read_gicd_chipsr(multichip_data->rt_owner_base) &
354 GICD_CHIPSR_RTS_MASK) >> GICD_CHIPSR_RTS_SHIFT) !=
355 GICD_CHIPSR_RTS_STATE_DISCONNECTED) {
356 ERROR("GIC-600 routing table owner is not in disconnected "
357 "state to begin multichip configuration\n");
358 panic();
359 }
360
361 /* Initialize the GICD which is marked as routing table owner first */
362 set_gicd_dchipr_rt_owner(multichip_data->rt_owner_base,
363 multichip_data->rt_owner);
364
365 set_gicd_chipr_n(multichip_data->rt_owner_base, multichip_data->rt_owner,
366 multichip_data->chip_addrs[multichip_data->rt_owner],
367 multichip_data->
Varun Wadekar61286d22023-03-08 16:47:38 +0000368 spi_ids[multichip_data->rt_owner].spi_id_min,
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +0530369 multichip_data->
Varun Wadekar61286d22023-03-08 16:47:38 +0000370 spi_ids[multichip_data->rt_owner].spi_id_max);
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +0530371
372 for (i = 0; i < multichip_data->chip_count; i++) {
373 if (i == multichip_data->rt_owner)
374 continue;
375
376 set_gicd_chipr_n(multichip_data->rt_owner_base, i,
377 multichip_data->chip_addrs[i],
Varun Wadekar61286d22023-03-08 16:47:38 +0000378 multichip_data->spi_ids[i].spi_id_min,
379 multichip_data->spi_ids[i].spi_id_max);
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +0530380 }
Varun Wadekar61286d22023-03-08 16:47:38 +0000381
382 plat_gic_multichip_data = multichip_data;
383}
384
385/*******************************************************************************
386 * Allow a way to query the status of the GIC600 multichip driver
387 ******************************************************************************/
388bool gic600_multichip_is_initialized(void)
389{
390 return (plat_gic_multichip_data != NULL);
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +0530391}