xref: /rk3399_ARM-atf/lib/extensions/ras/std_err_record.c (revision 30d81c36da441bcd0fbccbc3ac1a7268d2cc5ad2)
1 /*
2  * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 #include <ras_arch.h>
7 #include <utils_def.h>
8 
9 /*
10  * Probe for error in memory-mapped registers containing error records
11  * implemented Standard Error Record format. Upon detecting an error, set probe
12  * data to the index of the record in error, and return 1; otherwise, return 0.
13  */
14 int ser_probe_memmap(uintptr_t base, unsigned int size_num_k, int *probe_data)
15 {
16 	int num_records, num_group_regs, i;
17 	uint64_t gsr;
18 
19 	assert(base != 0);
20 
21 	/* Only 4K supported for now */
22 	assert(size_num_k == STD_ERR_NODE_SIZE_NUM_K);
23 
24 	num_records = (mmio_read_32(ERR_DEVID(base, size_num_k)) & ERR_DEVID_MASK);
25 
26 	/* A group register shows error status for 2^6 error records */
27 	num_group_regs = (num_records >> 6) + 1;
28 
29 	/* Iterate through group registers to find a record in error */
30 	for (i = 0; i < num_group_regs; i++) {
31 		gsr = mmio_read_64(ERR_GSR(base, size_num_k, i));
32 		if (gsr == 0)
33 			continue;
34 
35 		/* Return the index of the record in error */
36 		if (probe_data != NULL)
37 			*probe_data = ((i << 6) + __builtin_ctz(gsr));
38 
39 		return 1;
40 	}
41 
42 	return 0;
43 }
44 
45 /*
46  * Probe for error in System Registers where error records are implemented in
47  * Standard Error Record format. Upon detecting an error, set probe data to the
48  * index of the record in error, and return 1; otherwise, return 0.
49  */
50 int ser_probe_sysreg(unsigned int idx_start, unsigned int num_idx, int *probe_data)
51 {
52 	int i;
53 	uint64_t status;
54 	unsigned int max_idx __unused = read_erridr_el1() & ERRIDR_MASK;
55 
56 	assert(idx_start < max_idx);
57 	assert(check_u32_overflow(idx_start, num_idx) == 0);
58 	assert((idx_start + num_idx - 1) < max_idx);
59 
60 	for (i = 0; i < num_idx; i++) {
61 		/* Select the error record */
62 		ser_sys_select_record(idx_start + i);
63 
64 		/* Retrieve status register from the error record */
65 		status = read_erxstatus_el1();
66 
67 		/* Check for valid field in status */
68 		if (ERR_STATUS_GET_FIELD(status, V)) {
69 			if (probe_data != NULL)
70 				*probe_data = i;
71 			return 1;
72 		}
73 	}
74 
75 	return 0;
76 }
77