• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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>
12 
13 #include <common/debug.h>
14 #include <drivers/arm/gic600_multichip.h>
15 #include <drivers/arm/gicv3.h>
16 
17 #include "../common/gic_common_private.h"
18 #include "gic600_multichip_private.h"
19 
20 #warning "GIC-600 Multichip driver is currently experimental and the API may change in future."
21 
22 /*******************************************************************************
23  * GIC-600 multichip operation related helper functions
24  ******************************************************************************/
gicd_dchipr_wait_for_power_update_progress(uintptr_t base)25 static 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  ******************************************************************************/
set_gicd_dchipr_rt_owner(uintptr_t base,unsigned int rt_owner)41 static 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  ******************************************************************************/
set_gicd_chipr_n(uintptr_t base,unsigned int chip_id,uint64_t chip_addr,unsigned int spi_id_min,unsigned int spi_id_max)69 static 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;
76 	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 
103 	chipr_n_val = (GICD_CHIPR_VALUE(chip_addr, spi_block_min, spi_blocks)) |
104 		GICD_CHIPRx_SOCKET_STATE;
105 
106 	/*
107 	 * Wait for DCHIPR.PUP to be zero before commencing writes to
108 	 * GICD_CHIPRx.
109 	 */
110 	gicd_dchipr_wait_for_power_update_progress(base);
111 
112 	/*
113 	 * Assign chip addr, spi min block, number of spi blocks and bring chip
114 	 * online by setting SocketState.
115 	 */
116 	write_gicd_chipr_n(base, chip_id, chipr_n_val);
117 
118 	/*
119 	 * Poll until DCHIP.PUP is zero to verify connection to rt_owner chip
120 	 * is complete.
121 	 */
122 	gicd_dchipr_wait_for_power_update_progress(base);
123 
124 	/*
125 	 * Ensure that write to GICD_CHIPRx is successful and the chip_n came
126 	 * online.
127 	 */
128 	if (read_gicd_chipr_n(base, chip_id) != chipr_n_val) {
129 		ERROR("GICD_CHIPR%u write failed\n", chip_id);
130 		panic();
131 	}
132 
133 	/* Ensure that chip is in consistent state */
134 	if (((read_gicd_chipsr(base) & GICD_CHIPSR_RTS_MASK) >>
135 				GICD_CHIPSR_RTS_SHIFT) !=
136 			GICD_CHIPSR_RTS_STATE_CONSISTENT) {
137 		ERROR("Chip %u routing table is not in consistent state\n",
138 				chip_id);
139 		panic();
140 	}
141 }
142 
143 /*******************************************************************************
144  * Validates the GIC-600 Multichip data structure passed by the platform.
145  ******************************************************************************/
gic600_multichip_validate_data(struct gic600_multichip_data * multichip_data)146 static void gic600_multichip_validate_data(
147 		struct gic600_multichip_data *multichip_data)
148 {
149 	unsigned int i, spi_id_min, spi_id_max, blocks_of_32;
150 	unsigned int multichip_spi_blocks = 0;
151 
152 	assert(multichip_data != NULL);
153 
154 	if (multichip_data->chip_count > GIC600_MAX_MULTICHIP) {
155 		ERROR("GIC-600 Multichip count should not exceed %d\n",
156 				GIC600_MAX_MULTICHIP);
157 		panic();
158 	}
159 
160 	for (i = 0; i < multichip_data->chip_count; i++) {
161 		spi_id_min = multichip_data->spi_ids[i][SPI_MIN_INDEX];
162 		spi_id_max = multichip_data->spi_ids[i][SPI_MAX_INDEX];
163 
164 		if ((spi_id_min != 0) || (spi_id_max != 0)) {
165 
166 			/* SPI IDs range check */
167 			if (!(spi_id_min >= GIC600_SPI_ID_MIN) ||
168 			    !(spi_id_max < GIC600_SPI_ID_MAX) ||
169 			    !(spi_id_min <= spi_id_max) ||
170 			    !((spi_id_max - spi_id_min + 1) % 32 == 0)) {
171 				ERROR("Invalid SPI IDs {%u, %u} passed for "
172 						"Chip %u\n", spi_id_min,
173 						spi_id_max, i);
174 				panic();
175 			}
176 
177 			/* SPI IDs overlap check */
178 			blocks_of_32 = BLOCKS_OF_32(spi_id_min, spi_id_max);
179 			if ((multichip_spi_blocks & blocks_of_32) != 0) {
180 				ERROR("SPI IDs of Chip %u overlapping\n", i);
181 				panic();
182 			}
183 			multichip_spi_blocks |= blocks_of_32;
184 		}
185 	}
186 }
187 
188 /*******************************************************************************
189  * Intialize GIC-600 Multichip operation.
190  ******************************************************************************/
gic600_multichip_init(struct gic600_multichip_data * multichip_data)191 void gic600_multichip_init(struct gic600_multichip_data *multichip_data)
192 {
193 	unsigned int i;
194 
195 	gic600_multichip_validate_data(multichip_data);
196 
197 	INFO("GIC-600 Multichip driver is experimental\n");
198 
199 	/*
200 	 * Ensure that G0/G1S/G1NS interrupts are disabled. This also ensures
201 	 * that GIC-600 Multichip configuration is done first.
202 	 */
203 	if ((gicd_read_ctlr(multichip_data->rt_owner_base) &
204 			(CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1S_BIT |
205 			 CTLR_ENABLE_G1NS_BIT | GICD_CTLR_RWP_BIT)) != 0) {
206 		ERROR("GICD_CTLR group interrupts are either enabled or have "
207 				"pending writes.\n");
208 		panic();
209 	}
210 
211 	/* Ensure that the routing table owner is in disconnected state */
212 	if (((read_gicd_chipsr(multichip_data->rt_owner_base) &
213 		GICD_CHIPSR_RTS_MASK) >> GICD_CHIPSR_RTS_SHIFT) !=
214 			GICD_CHIPSR_RTS_STATE_DISCONNECTED) {
215 		ERROR("GIC-600 routing table owner is not in disconnected "
216 				"state to begin multichip configuration\n");
217 		panic();
218 	}
219 
220 	/* Initialize the GICD which is marked as routing table owner first */
221 	set_gicd_dchipr_rt_owner(multichip_data->rt_owner_base,
222 			multichip_data->rt_owner);
223 
224 	set_gicd_chipr_n(multichip_data->rt_owner_base, multichip_data->rt_owner,
225 			multichip_data->chip_addrs[multichip_data->rt_owner],
226 			multichip_data->
227 			spi_ids[multichip_data->rt_owner][SPI_MIN_INDEX],
228 			multichip_data->
229 			spi_ids[multichip_data->rt_owner][SPI_MAX_INDEX]);
230 
231 	for (i = 0; i < multichip_data->chip_count; i++) {
232 		if (i == multichip_data->rt_owner)
233 			continue;
234 
235 		set_gicd_chipr_n(multichip_data->rt_owner_base, i,
236 				multichip_data->chip_addrs[i],
237 				multichip_data->spi_ids[i][SPI_MIN_INDEX],
238 				multichip_data->spi_ids[i][SPI_MAX_INDEX]);
239 	}
240 }
241