1 /*
2 * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 /*
8 * Driver for GIC-600AE Fault Management Unit
9 */
10
11 #include <assert.h>
12
13 #include <arch_helpers.h>
14 #include <common/debug.h>
15 #include <drivers/arm/gic600ae_fmu.h>
16 #include <drivers/arm/gicv3.h>
17
18 /* GIC-600 AE FMU specific register offsets */
19
20 /* GIC-600 AE FMU specific macros */
21 #define FMU_ERRIDR_NUM U(44)
22 #define FMU_ERRIDR_NUM_MASK U(0xFFFF)
23
24 /* Safety mechanisms for GICD block */
25 static char *gicd_sm_info[] = {
26 "Reserved",
27 "GICD dual lockstep error",
28 "GICD AXI4 slave interface error",
29 "GICD-PPI AXI4-Stream interface error",
30 "GICD-ITS AXI4-Stream interface error",
31 "GICD-SPI-Collator AXI4-Stream interface error",
32 "GICD AXI4 master interface error",
33 "SPI RAM DED error",
34 "SGI RAM DED error",
35 "Reserved",
36 "LPI RAM DED error",
37 "GICD-remote-GICD AXI4-Stream interface error",
38 "GICD Q-Channel interface error",
39 "GICD P-Channel interface error",
40 "SPI RAM address decode error",
41 "SGI RAM address decode error",
42 "Reserved",
43 "LPI RAM address decode error",
44 "FMU dual lockstep error",
45 "FMU ping ACK error",
46 "FMU APB parity error",
47 "GICD-Wake AXI4-Stream interface error",
48 "GICD PageOffset or Chip ID error",
49 "MBIST REQ error",
50 "SPI RAM SEC error",
51 "SGI RAM SEC error",
52 "Reserved",
53 "LPI RAM SEC error",
54 "User custom SM0 error",
55 "User custom SM1 error",
56 "GICD-ITS Monolithic switch error",
57 "GICD-ITS Q-Channel interface error",
58 "GICD-ITS Monolithic interface error",
59 "GICD FMU ClkGate override"
60 };
61
62 /* Safety mechanisms for PPI block */
63 static char *ppi_sm_info[] = {
64 "Reserved",
65 "PPI dual lockstep error",
66 "PPI-GICD AXI4-Stream interface error",
67 "PPI-CPU-IF AXI4-Stream interface error",
68 "PPI Q-Channel interface error",
69 "PPI RAM DED error",
70 "PPI RAM address decode error",
71 "PPI RAM SEC error",
72 "PPI User0 SM",
73 "PPI User1 SM",
74 "MBIST REQ error",
75 "PPI interrupt parity protection error",
76 "PPI FMU ClkGate override"
77 };
78
79 /* Safety mechanisms for ITS block */
80 static char *its_sm_info[] = {
81 "Reserved",
82 "ITS dual lockstep error",
83 "ITS-GICD AXI4-Stream interface error",
84 "ITS AXI4 slave interface error",
85 "ITS AXI4 master interface error",
86 "ITS Q-Channel interface error",
87 "ITS RAM DED error",
88 "ITS RAM address decode error",
89 "Bypass ACE switch error",
90 "ITS RAM SEC error",
91 "ITS User0 SM",
92 "ITS User1 SM",
93 "ITS-GICD Monolithic interface error",
94 "MBIST REQ error",
95 "ITS FMU ClkGate override"
96 };
97
98 /* Safety mechanisms for SPI Collator block */
99 static char *spicol_sm_info[] = {
100 "Reserved",
101 "SPI Collator dual lockstep error",
102 "SPI-Collator-GICD AXI4-Stream interface error",
103 "SPI Collator Q-Channel interface error",
104 "SPI Collator Q-Channel clock error",
105 "SPI interrupt parity error"
106 };
107
108 /* Safety mechanisms for Wake Request block */
109 static char *wkrqst_sm_info[] = {
110 "Reserved",
111 "Wake dual lockstep error",
112 "Wake-GICD AXI4-Stream interface error"
113 };
114
115 /*
116 * Initialization sequence for the FMU
117 *
118 * 1. enable error detection for error records that are passed in the blk_present_mask
119 * 2. enable MBIST REQ and FMU Clk Gate override safety mechanisms for error records
120 * that are present on the platform
121 *
122 * The platforms are expected to pass `errctlr_ce_en` and `errctlr_ue_en`.
123 */
gic600_fmu_init(uint64_t base,uint64_t blk_present_mask,bool errctlr_ce_en,bool errctlr_ue_en)124 void gic600_fmu_init(uint64_t base, uint64_t blk_present_mask,
125 bool errctlr_ce_en, bool errctlr_ue_en)
126 {
127 unsigned int num_blk = gic_fmu_read_erridr(base) & FMU_ERRIDR_NUM_MASK;
128 uint64_t errctlr;
129 uint32_t smen;
130
131 INFO("GIC600-AE FMU supports %d error records\n", num_blk);
132
133 assert(num_blk == FMU_ERRIDR_NUM);
134
135 /* sanitize block present mask */
136 blk_present_mask &= FMU_BLK_PRESENT_MASK;
137
138 /* Enable error detection for all error records */
139 for (unsigned int i = 0U; i < num_blk; i++) {
140
141 /* Skip next steps if the block is not present */
142 if ((blk_present_mask & BIT(i)) == 0U) {
143 continue;
144 }
145
146 /* Read the error record control register */
147 errctlr = gic_fmu_read_errctlr(base, i);
148
149 /* Enable error reporting and logging, if it is disabled */
150 if ((errctlr & FMU_ERRCTLR_ED_BIT) == 0U) {
151 errctlr |= FMU_ERRCTLR_ED_BIT;
152 }
153
154 /* Enable client provided ERRCTLR settings */
155 errctlr |= (errctlr_ce_en ? (FMU_ERRCTLR_CI_BIT | FMU_ERRCTLR_CE_EN_BIT) : 0);
156 errctlr |= (errctlr_ue_en ? FMU_ERRCTLR_UI_BIT : 0U);
157
158 gic_fmu_write_errctlr(base, i, errctlr);
159 }
160
161 /*
162 * Enable MBIST REQ error and FMU CLK gate override safety mechanisms for
163 * all blocks
164 *
165 * GICD, SMID 23 and SMID 33
166 * PPI, SMID 10 and SMID 12
167 * ITS, SMID 13 and SMID 14
168 */
169 if ((blk_present_mask & BIT(FMU_BLK_GICD)) != 0U) {
170 smen = (GICD_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) |
171 (FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT);
172 gic_fmu_write_smen(base, smen);
173
174 smen = (GICD_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) |
175 (FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT);
176 gic_fmu_write_smen(base, smen);
177 }
178
179 for (unsigned int i = FMU_BLK_PPI0; i < FMU_BLK_PPI31; i++) {
180 if ((blk_present_mask & BIT(i)) != 0U) {
181 smen = (PPI_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) |
182 (i << FMU_SMEN_BLK_SHIFT);
183 gic_fmu_write_smen(base, smen);
184
185 smen = (PPI_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) |
186 (i << FMU_SMEN_BLK_SHIFT);
187 gic_fmu_write_smen(base, smen);
188 }
189 }
190
191 for (unsigned int i = FMU_BLK_ITS0; i < FMU_BLK_ITS7; i++) {
192 if ((blk_present_mask & BIT(i)) != 0U) {
193 smen = (ITS_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) |
194 (i << FMU_SMEN_BLK_SHIFT);
195 gic_fmu_write_smen(base, smen);
196
197 smen = (ITS_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) |
198 (i << FMU_SMEN_BLK_SHIFT);
199 gic_fmu_write_smen(base, smen);
200 }
201 }
202 }
203
204 /*
205 * This function enable the GICD background ping engine. The GICD sends ping
206 * messages to each remote GIC block, and expects a PING_ACK back within the
207 * specified timeout. Pings need to be enabled after programming the timeout
208 * value.
209 */
gic600_fmu_enable_ping(uint64_t base,uint64_t blk_present_mask,unsigned int timeout_val,unsigned int interval_diff)210 void gic600_fmu_enable_ping(uint64_t base, uint64_t blk_present_mask,
211 unsigned int timeout_val, unsigned int interval_diff)
212 {
213 /*
214 * Populate the PING Mask to skip a specific block while generating
215 * background ping messages and enable the ping mechanism.
216 */
217 gic_fmu_write_pingmask(base, ~blk_present_mask);
218 gic_fmu_write_pingctlr(base, (interval_diff << FMU_PINGCTLR_INTDIFF_SHIFT) |
219 (timeout_val << FMU_PINGCTLR_TIMEOUTVAL_SHIFT) | FMU_PINGCTLR_EN_BIT);
220 }
221
222 /* Print the safety mechanism description for a given block */
gic600_fmu_print_sm_info(uint64_t base,unsigned int blk,unsigned int smid)223 void gic600_fmu_print_sm_info(uint64_t base, unsigned int blk, unsigned int smid)
224 {
225 if (blk == FMU_BLK_GICD && smid <= FMU_SMID_GICD_MAX) {
226 INFO("GICD, SMID %d: %s\n", smid, gicd_sm_info[smid]);
227 }
228
229 if (blk == FMU_BLK_SPICOL && smid <= FMU_SMID_SPICOL_MAX) {
230 INFO("SPI Collator, SMID %d: %s\n", smid, spicol_sm_info[smid]);
231 }
232
233 if (blk == FMU_BLK_WAKERQ && (smid <= FMU_SMID_WAKERQ_MAX)) {
234 INFO("Wake Request, SMID %d: %s\n", smid, wkrqst_sm_info[smid]);
235 }
236
237 if (((blk >= FMU_BLK_ITS0) && (blk <= FMU_BLK_ITS7)) && (smid <= FMU_SMID_ITS_MAX)) {
238 INFO("ITS, SMID %d: %s\n", smid, its_sm_info[smid]);
239 }
240
241 if (((blk >= FMU_BLK_PPI0) && (blk <= FMU_BLK_PPI31)) && (smid <= FMU_SMID_PPI_MAX)) {
242 INFO("PPI, SMID %d: %s\n", smid, ppi_sm_info[smid]);
243 }
244 }
245