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