blob: ca7c43bf9cbf53d171e6a2ddb9c485465ca01bcc [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>
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +053014#include <drivers/arm/gic600_multichip.h>
Max Shvetsov0ac39412019-11-19 11:01:26 +000015#include <drivers/arm/gicv3.h>
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +053016
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +053017#include "../common/gic_common_private.h"
Max Shvetsov0ac39412019-11-19 11:01:26 +000018#include "gic600_multichip_private.h"
Vijayenthiran Subramaniamad3fc762019-09-16 17:05:08 +053019
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 ******************************************************************************/
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;
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 ******************************************************************************/
146static 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 ******************************************************************************/
191void 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}