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