blob: 5f42ad994130951cc1e9d41db4ae03313ac93d9c [file] [log] [blame]
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +05301/*
2 * Copyright (c) 2019, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7/*
8 * GIC-600 driver extension for multichip setup
9 */
10
11#include <assert.h>
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +053012
Max Shvetsov0ac39412019-11-19 11:01:26 +000013#include <common/debug.h>
Andre Przywara9e1dc682021-05-18 15:46:58 +010014#include <drivers/arm/arm_gicv3_common.h>
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +053015#include <drivers/arm/gic600_multichip.h>
Max Shvetsov0ac39412019-11-19 11:01:26 +000016#include <drivers/arm/gicv3.h>
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +053017
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +053018#include "../common/gic_common_private.h"
Max Shvetsov0ac39412019-11-19 11:01:26 +000019#include "gic600_multichip_private.h"
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +053020
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +053021/*******************************************************************************
22 * GIC-600 multichip operation related helper functions
23 ******************************************************************************/
24static void gicd_dchipr_wait_for_power_update_progress(uintptr_t base)
25{
26 unsigned int retry = GICD_PUP_UPDATE_RETRIES;
27
28 while ((read_gicd_dchipr(base) & GICD_DCHIPR_PUP_BIT) != 0U) {
29 if (retry-- == 0) {
30 ERROR("GIC-600 connection to Routing Table Owner timed "
31 "out\n");
32 panic();
33 }
34 }
35}
36
37/*******************************************************************************
38 * Sets up the routing table owner.
39 ******************************************************************************/
40static void set_gicd_dchipr_rt_owner(uintptr_t base, unsigned int rt_owner)
41{
42 /*
43 * Ensure that Group enables in GICD_CTLR are disabled and no pending
44 * register writes to GICD_CTLR.
45 */
46 if ((gicd_read_ctlr(base) &
47 (CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1S_BIT |
48 CTLR_ENABLE_G1NS_BIT | GICD_CTLR_RWP_BIT)) != 0) {
49 ERROR("GICD_CTLR group interrupts are either enabled or have "
50 "pending writes. Cannot set RT owner.\n");
51 panic();
52 }
53
54 /* Poll till PUP is zero before intiating write */
55 gicd_dchipr_wait_for_power_update_progress(base);
56
57 write_gicd_dchipr(base, read_gicd_dchipr(base) |
58 (rt_owner << GICD_DCHIPR_RT_OWNER_SHIFT));
59
60 /* Poll till PUP is zero to ensure write is complete */
61 gicd_dchipr_wait_for_power_update_progress(base);
62}
63
64/*******************************************************************************
65 * Configures the Chip Register to make connections to GICDs on
66 * a multichip platform.
67 ******************************************************************************/
68static void set_gicd_chipr_n(uintptr_t base,
69 unsigned int chip_id,
70 uint64_t chip_addr,
71 unsigned int spi_id_min,
72 unsigned int spi_id_max)
73{
74 unsigned int spi_block_min, spi_blocks;
Andre Przywara9e1dc682021-05-18 15:46:58 +010075 unsigned int gicd_iidr_val = gicd_read_iidr(base);
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +053076 uint64_t chipr_n_val;
77
78 /*
79 * Ensure that group enables in GICD_CTLR are disabled and no pending
80 * register writes to GICD_CTLR.
81 */
82 if ((gicd_read_ctlr(base) &
83 (CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1S_BIT |
84 CTLR_ENABLE_G1NS_BIT | GICD_CTLR_RWP_BIT)) != 0) {
85 ERROR("GICD_CTLR group interrupts are either enabled or have "
86 "pending writes. Cannot set CHIPR register.\n");
87 panic();
88 }
89
90 /*
91 * spi_id_min and spi_id_max of value 0 is used to intidicate that the
92 * chip doesn't own any SPI block. Re-assign min and max values as SPI
93 * id starts from 32.
94 */
95 if (spi_id_min == 0 && spi_id_max == 0) {
96 spi_id_min = GIC600_SPI_ID_MIN;
97 spi_id_max = GIC600_SPI_ID_MIN;
98 }
99
100 spi_block_min = SPI_BLOCK_MIN_VALUE(spi_id_min);
101 spi_blocks = SPI_BLOCKS_VALUE(spi_id_min, spi_id_max);
102
Andre Przywara9e1dc682021-05-18 15:46:58 +0100103 switch ((gicd_iidr_val & IIDR_MODEL_MASK)) {
104 case IIDR_MODEL_ARM_GIC_600:
105 chipr_n_val = GICD_CHIPR_VALUE_GIC_600(chip_addr,
106 spi_block_min,
107 spi_blocks);
108 break;
109 case IIDR_MODEL_ARM_GIC_700:
110 chipr_n_val = GICD_CHIPR_VALUE_GIC_700(chip_addr,
111 spi_block_min,
112 spi_blocks);
113 break;
114 default:
115 ERROR("Unsupported GIC model 0x%x for multichip setup.\n",
116 gicd_iidr_val);
117 panic();
118 break;
119 }
120 chipr_n_val |= GICD_CHIPRx_SOCKET_STATE;
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +0530121
122 /*
123 * Wait for DCHIPR.PUP to be zero before commencing writes to
124 * GICD_CHIPRx.
125 */
126 gicd_dchipr_wait_for_power_update_progress(base);
127
128 /*
129 * Assign chip addr, spi min block, number of spi blocks and bring chip
130 * online by setting SocketState.
131 */
132 write_gicd_chipr_n(base, chip_id, chipr_n_val);
133
134 /*
135 * Poll until DCHIP.PUP is zero to verify connection to rt_owner chip
136 * is complete.
137 */
138 gicd_dchipr_wait_for_power_update_progress(base);
139
140 /*
141 * Ensure that write to GICD_CHIPRx is successful and the chip_n came
142 * online.
143 */
144 if (read_gicd_chipr_n(base, chip_id) != chipr_n_val) {
145 ERROR("GICD_CHIPR%u write failed\n", chip_id);
146 panic();
147 }
148
149 /* Ensure that chip is in consistent state */
150 if (((read_gicd_chipsr(base) & GICD_CHIPSR_RTS_MASK) >>
151 GICD_CHIPSR_RTS_SHIFT) !=
152 GICD_CHIPSR_RTS_STATE_CONSISTENT) {
153 ERROR("Chip %u routing table is not in consistent state\n",
154 chip_id);
155 panic();
156 }
157}
158
159/*******************************************************************************
160 * Validates the GIC-600 Multichip data structure passed by the platform.
161 ******************************************************************************/
162static void gic600_multichip_validate_data(
163 struct gic600_multichip_data *multichip_data)
164{
165 unsigned int i, spi_id_min, spi_id_max, blocks_of_32;
166 unsigned int multichip_spi_blocks = 0;
167
168 assert(multichip_data != NULL);
169
170 if (multichip_data->chip_count > GIC600_MAX_MULTICHIP) {
171 ERROR("GIC-600 Multichip count should not exceed %d\n",
172 GIC600_MAX_MULTICHIP);
173 panic();
174 }
175
176 for (i = 0; i < multichip_data->chip_count; i++) {
177 spi_id_min = multichip_data->spi_ids[i][SPI_MIN_INDEX];
178 spi_id_max = multichip_data->spi_ids[i][SPI_MAX_INDEX];
179
180 if ((spi_id_min != 0) || (spi_id_max != 0)) {
181
182 /* SPI IDs range check */
183 if (!(spi_id_min >= GIC600_SPI_ID_MIN) ||
184 !(spi_id_max < GIC600_SPI_ID_MAX) ||
185 !(spi_id_min <= spi_id_max) ||
186 !((spi_id_max - spi_id_min + 1) % 32 == 0)) {
187 ERROR("Invalid SPI IDs {%u, %u} passed for "
188 "Chip %u\n", spi_id_min,
189 spi_id_max, i);
190 panic();
191 }
192
193 /* SPI IDs overlap check */
194 blocks_of_32 = BLOCKS_OF_32(spi_id_min, spi_id_max);
195 if ((multichip_spi_blocks & blocks_of_32) != 0) {
196 ERROR("SPI IDs of Chip %u overlapping\n", i);
197 panic();
198 }
199 multichip_spi_blocks |= blocks_of_32;
200 }
201 }
202}
203
204/*******************************************************************************
205 * Intialize GIC-600 Multichip operation.
206 ******************************************************************************/
207void gic600_multichip_init(struct gic600_multichip_data *multichip_data)
208{
209 unsigned int i;
210
211 gic600_multichip_validate_data(multichip_data);
212
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +0530213 /*
214 * Ensure that G0/G1S/G1NS interrupts are disabled. This also ensures
215 * that GIC-600 Multichip configuration is done first.
216 */
217 if ((gicd_read_ctlr(multichip_data->rt_owner_base) &
218 (CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1S_BIT |
219 CTLR_ENABLE_G1NS_BIT | GICD_CTLR_RWP_BIT)) != 0) {
220 ERROR("GICD_CTLR group interrupts are either enabled or have "
221 "pending writes.\n");
222 panic();
223 }
224
225 /* Ensure that the routing table owner is in disconnected state */
226 if (((read_gicd_chipsr(multichip_data->rt_owner_base) &
227 GICD_CHIPSR_RTS_MASK) >> GICD_CHIPSR_RTS_SHIFT) !=
228 GICD_CHIPSR_RTS_STATE_DISCONNECTED) {
229 ERROR("GIC-600 routing table owner is not in disconnected "
230 "state to begin multichip configuration\n");
231 panic();
232 }
233
234 /* Initialize the GICD which is marked as routing table owner first */
235 set_gicd_dchipr_rt_owner(multichip_data->rt_owner_base,
236 multichip_data->rt_owner);
237
238 set_gicd_chipr_n(multichip_data->rt_owner_base, multichip_data->rt_owner,
239 multichip_data->chip_addrs[multichip_data->rt_owner],
240 multichip_data->
241 spi_ids[multichip_data->rt_owner][SPI_MIN_INDEX],
242 multichip_data->
243 spi_ids[multichip_data->rt_owner][SPI_MAX_INDEX]);
244
245 for (i = 0; i < multichip_data->chip_count; i++) {
246 if (i == multichip_data->rt_owner)
247 continue;
248
249 set_gicd_chipr_n(multichip_data->rt_owner_base, i,
250 multichip_data->chip_addrs[i],
251 multichip_data->spi_ids[i][SPI_MIN_INDEX],
252 multichip_data->spi_ids[i][SPI_MAX_INDEX]);
253 }
254}