xref: /rk3399_ARM-atf/lib/extensions/ras/std_err_record.c (revision 72e8f2456af54b75a0a1d92aadfce0b4bcde6ba1)
130d81c36SJeenu Viswambharan /*
2*4c700c15SGovindraj Raja  * Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.
330d81c36SJeenu Viswambharan  *
430d81c36SJeenu Viswambharan  * SPDX-License-Identifier: BSD-3-Clause
530d81c36SJeenu Viswambharan  */
609d40e0eSAntonio Nino Diaz 
709d40e0eSAntonio Nino Diaz #include <lib/extensions/ras_arch.h>
809d40e0eSAntonio Nino Diaz #include <lib/utils_def.h>
930d81c36SJeenu Viswambharan 
1030d81c36SJeenu Viswambharan /*
1130d81c36SJeenu Viswambharan  * Probe for error in memory-mapped registers containing error records
1230d81c36SJeenu Viswambharan  * implemented Standard Error Record format. Upon detecting an error, set probe
1330d81c36SJeenu Viswambharan  * data to the index of the record in error, and return 1; otherwise, return 0.
1430d81c36SJeenu Viswambharan  */
ser_probe_memmap(uintptr_t base,unsigned int size_num_k,int * probe_data)1530d81c36SJeenu Viswambharan int ser_probe_memmap(uintptr_t base, unsigned int size_num_k, int *probe_data)
1630d81c36SJeenu Viswambharan {
1730a8d96eSJeenu Viswambharan 	unsigned int num_records, num_group_regs, i;
1830d81c36SJeenu Viswambharan 	uint64_t gsr;
1930d81c36SJeenu Viswambharan 
2030a8d96eSJeenu Viswambharan 	assert(base != 0UL);
2130d81c36SJeenu Viswambharan 
2230d81c36SJeenu Viswambharan 	/* Only 4K supported for now */
2330d81c36SJeenu Viswambharan 	assert(size_num_k == STD_ERR_NODE_SIZE_NUM_K);
2430d81c36SJeenu Viswambharan 
2530a8d96eSJeenu Viswambharan 	num_records = (unsigned int)
2630a8d96eSJeenu Viswambharan 		(mmio_read_32(ERR_DEVID(base, size_num_k)) & ERR_DEVID_MASK);
2730d81c36SJeenu Viswambharan 
2830d81c36SJeenu Viswambharan 	/* A group register shows error status for 2^6 error records */
2930a8d96eSJeenu Viswambharan 	num_group_regs = (num_records >> 6U) + 1U;
3030d81c36SJeenu Viswambharan 
3130d81c36SJeenu Viswambharan 	/* Iterate through group registers to find a record in error */
3230d81c36SJeenu Viswambharan 	for (i = 0; i < num_group_regs; i++) {
3330d81c36SJeenu Viswambharan 		gsr = mmio_read_64(ERR_GSR(base, size_num_k, i));
3430a8d96eSJeenu Viswambharan 		if (gsr == 0ULL)
3530d81c36SJeenu Viswambharan 			continue;
3630d81c36SJeenu Viswambharan 
3730d81c36SJeenu Viswambharan 		/* Return the index of the record in error */
3830d81c36SJeenu Viswambharan 		if (probe_data != NULL)
3930a8d96eSJeenu Viswambharan 			*probe_data = (((int) (i << 6U)) + __builtin_ctzll(gsr));
4030d81c36SJeenu Viswambharan 
4130d81c36SJeenu Viswambharan 		return 1;
4230d81c36SJeenu Viswambharan 	}
4330d81c36SJeenu Viswambharan 
4430d81c36SJeenu Viswambharan 	return 0;
4530d81c36SJeenu Viswambharan }
4630d81c36SJeenu Viswambharan 
4730d81c36SJeenu Viswambharan /*
4830d81c36SJeenu Viswambharan  * Probe for error in System Registers where error records are implemented in
4930d81c36SJeenu Viswambharan  * Standard Error Record format. Upon detecting an error, set probe data to the
5030d81c36SJeenu Viswambharan  * index of the record in error, and return 1; otherwise, return 0.
5130d81c36SJeenu Viswambharan  */
ser_probe_sysreg(unsigned int idx_start,unsigned int num_idx,int * probe_data)5230d81c36SJeenu Viswambharan int ser_probe_sysreg(unsigned int idx_start, unsigned int num_idx, int *probe_data)
5330d81c36SJeenu Viswambharan {
5430a8d96eSJeenu Viswambharan 	unsigned int i;
5530d81c36SJeenu Viswambharan 	uint64_t status;
5630a8d96eSJeenu Viswambharan 	unsigned int max_idx __unused =
5730a8d96eSJeenu Viswambharan 		((unsigned int) read_erridr_el1()) & ERRIDR_MASK;
5830d81c36SJeenu Viswambharan 
5930d81c36SJeenu Viswambharan 	assert(idx_start < max_idx);
60ca9ffc79SJeenu Viswambharan 	assert(check_u32_overflow(idx_start, num_idx) == 0);
6130a8d96eSJeenu Viswambharan 	assert((idx_start + num_idx - 1U) < max_idx);
6230d81c36SJeenu Viswambharan 
6330d81c36SJeenu Viswambharan 	for (i = 0; i < num_idx; i++) {
6430d81c36SJeenu Viswambharan 		/* Select the error record */
6530d81c36SJeenu Viswambharan 		ser_sys_select_record(idx_start + i);
6630d81c36SJeenu Viswambharan 
6730d81c36SJeenu Viswambharan 		/* Retrieve status register from the error record */
6830d81c36SJeenu Viswambharan 		status = read_erxstatus_el1();
6930d81c36SJeenu Viswambharan 
7030d81c36SJeenu Viswambharan 		/* Check for valid field in status */
7130a8d96eSJeenu Viswambharan 		if (ERR_STATUS_GET_FIELD(status, V) != 0U) {
7230d81c36SJeenu Viswambharan 			if (probe_data != NULL)
7330a8d96eSJeenu Viswambharan 				*probe_data = (int) i;
7430d81c36SJeenu Viswambharan 			return 1;
7530d81c36SJeenu Viswambharan 		}
7630d81c36SJeenu Viswambharan 	}
7730d81c36SJeenu Viswambharan 
7830d81c36SJeenu Viswambharan 	return 0;
7930d81c36SJeenu Viswambharan }
80