Merge changes I573e6478,I52dc3bee,I7e543664 into integration
* changes: feat(gic600ae_fmu): enable all GICD, PPI, ITS SMs feat(gic600ae_fmu): disable SMID for unavailable blocks feat(gic600ae_fmu): introduce support for RAS error handling
This commit is contained in:
commit
9bd3cb5c96
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
|
* Copyright (c) 2021-2022, NVIDIA Corporation. All rights reserved.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -9,6 +9,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include <arch_helpers.h>
|
#include <arch_helpers.h>
|
||||||
#include <common/debug.h>
|
#include <common/debug.h>
|
||||||
|
@ -112,6 +113,135 @@ static char *wkrqst_sm_info[] = {
|
||||||
"Wake-GICD AXI4-Stream interface error"
|
"Wake-GICD AXI4-Stream interface error"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Helper function to find detailed information for a specific IERR */
|
||||||
|
static char __unused *ras_ierr_to_str(unsigned int blkid, unsigned int ierr)
|
||||||
|
{
|
||||||
|
char *str = NULL;
|
||||||
|
|
||||||
|
/* Find the correct record */
|
||||||
|
switch (blkid) {
|
||||||
|
case FMU_BLK_GICD:
|
||||||
|
assert(ierr < ARRAY_SIZE(gicd_sm_info));
|
||||||
|
str = gicd_sm_info[ierr];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FMU_BLK_SPICOL:
|
||||||
|
assert(ierr < ARRAY_SIZE(spicol_sm_info));
|
||||||
|
str = spicol_sm_info[ierr];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FMU_BLK_WAKERQ:
|
||||||
|
assert(ierr < ARRAY_SIZE(wkrqst_sm_info));
|
||||||
|
str = wkrqst_sm_info[ierr];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FMU_BLK_ITS0...FMU_BLK_ITS7:
|
||||||
|
assert(ierr < ARRAY_SIZE(its_sm_info));
|
||||||
|
str = its_sm_info[ierr];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FMU_BLK_PPI0...FMU_BLK_PPI31:
|
||||||
|
assert(ierr < ARRAY_SIZE(ppi_sm_info));
|
||||||
|
str = ppi_sm_info[ierr];
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Probe for error in memory-mapped registers containing error records.
|
||||||
|
* Upon detecting an error, set probe data to the index of the record
|
||||||
|
* in error, and return 1; otherwise, return 0.
|
||||||
|
*/
|
||||||
|
int gic600_fmu_probe(uint64_t base, int *probe_data)
|
||||||
|
{
|
||||||
|
uint64_t gsr;
|
||||||
|
|
||||||
|
assert(base != 0UL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read ERR_GSR to find the error record 'M'
|
||||||
|
*/
|
||||||
|
gsr = gic_fmu_read_errgsr(base);
|
||||||
|
if (gsr == U(0)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the index of the record in error */
|
||||||
|
if (probe_data != NULL) {
|
||||||
|
*probe_data = (int)__builtin_ctzll(gsr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The handler function to read RAS records and find the safety
|
||||||
|
* mechanism with the error.
|
||||||
|
*/
|
||||||
|
int gic600_fmu_ras_handler(uint64_t base, int probe_data)
|
||||||
|
{
|
||||||
|
uint64_t errstatus;
|
||||||
|
unsigned int blkid = (unsigned int)probe_data, ierr, serr;
|
||||||
|
|
||||||
|
assert(base != 0UL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FMU_ERRGSR indicates the ID of the GIC
|
||||||
|
* block that faulted.
|
||||||
|
*/
|
||||||
|
assert(blkid <= FMU_BLK_PPI31);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find more information by reading FMU_ERR<M>STATUS
|
||||||
|
* register
|
||||||
|
*/
|
||||||
|
errstatus = gic_fmu_read_errstatus(base, blkid);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If FMU_ERR<M>STATUS.V is set to 0, no RAS records
|
||||||
|
* need to be scanned.
|
||||||
|
*/
|
||||||
|
if ((errstatus & FMU_ERRSTATUS_V_BIT) == U(0)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FMU_ERR<M>STATUS.IERR indicates which Safety Mechanism
|
||||||
|
* reported the error.
|
||||||
|
*/
|
||||||
|
ierr = (errstatus >> FMU_ERRSTATUS_IERR_SHIFT) &
|
||||||
|
FMU_ERRSTATUS_IERR_MASK;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FMU_ERR<M>STATUS.SERR indicates architecturally
|
||||||
|
* defined primary error code.
|
||||||
|
*/
|
||||||
|
serr = errstatus & FMU_ERRSTATUS_SERR_MASK;
|
||||||
|
|
||||||
|
ERROR("**************************************\n");
|
||||||
|
ERROR("RAS %s Error detected by GIC600 AE FMU\n",
|
||||||
|
((errstatus & FMU_ERRSTATUS_UE_BIT) != 0U) ?
|
||||||
|
"Uncorrectable" : "Corrected");
|
||||||
|
ERROR("\tStatus = 0x%lx \n", errstatus);
|
||||||
|
ERROR("\tBlock ID = 0x%x\n", blkid);
|
||||||
|
ERROR("\tSafety Mechanism ID = 0x%x (%s)\n", ierr,
|
||||||
|
ras_ierr_to_str(blkid, ierr));
|
||||||
|
ERROR("\tArchitecturally defined primary error code = 0x%x\n",
|
||||||
|
serr);
|
||||||
|
ERROR("**************************************\n");
|
||||||
|
|
||||||
|
/* Clear FMU_ERR<M>STATUS */
|
||||||
|
gic_fmu_write_errstatus(base, probe_data, errstatus);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialization sequence for the FMU
|
* Initialization sequence for the FMU
|
||||||
*
|
*
|
||||||
|
@ -138,8 +268,12 @@ void gic600_fmu_init(uint64_t base, uint64_t blk_present_mask,
|
||||||
/* Enable error detection for all error records */
|
/* Enable error detection for all error records */
|
||||||
for (unsigned int i = 0U; i < num_blk; i++) {
|
for (unsigned int i = 0U; i < num_blk; i++) {
|
||||||
|
|
||||||
/* Skip next steps if the block is not present */
|
/*
|
||||||
|
* Disable all safety mechanisms for blocks that are not
|
||||||
|
* present and skip the next steps.
|
||||||
|
*/
|
||||||
if ((blk_present_mask & BIT(i)) == 0U) {
|
if ((blk_present_mask & BIT(i)) == 0U) {
|
||||||
|
gic_fmu_disable_all_sm_blkid(base, i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,22 +302,26 @@ void gic600_fmu_init(uint64_t base, uint64_t blk_present_mask,
|
||||||
*/
|
*/
|
||||||
if ((blk_present_mask & BIT(FMU_BLK_GICD)) != 0U) {
|
if ((blk_present_mask & BIT(FMU_BLK_GICD)) != 0U) {
|
||||||
smen = (GICD_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) |
|
smen = (GICD_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) |
|
||||||
(FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT);
|
(FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT) |
|
||||||
|
FMU_SMEN_EN_BIT;
|
||||||
gic_fmu_write_smen(base, smen);
|
gic_fmu_write_smen(base, smen);
|
||||||
|
|
||||||
smen = (GICD_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) |
|
smen = (GICD_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) |
|
||||||
(FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT);
|
(FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT) |
|
||||||
|
FMU_SMEN_EN_BIT;
|
||||||
gic_fmu_write_smen(base, smen);
|
gic_fmu_write_smen(base, smen);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i = FMU_BLK_PPI0; i < FMU_BLK_PPI31; i++) {
|
for (unsigned int i = FMU_BLK_PPI0; i < FMU_BLK_PPI31; i++) {
|
||||||
if ((blk_present_mask & BIT(i)) != 0U) {
|
if ((blk_present_mask & BIT(i)) != 0U) {
|
||||||
smen = (PPI_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) |
|
smen = (PPI_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) |
|
||||||
(i << FMU_SMEN_BLK_SHIFT);
|
(i << FMU_SMEN_BLK_SHIFT) |
|
||||||
|
FMU_SMEN_EN_BIT;
|
||||||
gic_fmu_write_smen(base, smen);
|
gic_fmu_write_smen(base, smen);
|
||||||
|
|
||||||
smen = (PPI_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) |
|
smen = (PPI_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) |
|
||||||
(i << FMU_SMEN_BLK_SHIFT);
|
(i << FMU_SMEN_BLK_SHIFT) |
|
||||||
|
FMU_SMEN_EN_BIT;
|
||||||
gic_fmu_write_smen(base, smen);
|
gic_fmu_write_smen(base, smen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,11 +329,13 @@ void gic600_fmu_init(uint64_t base, uint64_t blk_present_mask,
|
||||||
for (unsigned int i = FMU_BLK_ITS0; i < FMU_BLK_ITS7; i++) {
|
for (unsigned int i = FMU_BLK_ITS0; i < FMU_BLK_ITS7; i++) {
|
||||||
if ((blk_present_mask & BIT(i)) != 0U) {
|
if ((blk_present_mask & BIT(i)) != 0U) {
|
||||||
smen = (ITS_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) |
|
smen = (ITS_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) |
|
||||||
(i << FMU_SMEN_BLK_SHIFT);
|
(i << FMU_SMEN_BLK_SHIFT) |
|
||||||
|
FMU_SMEN_EN_BIT;
|
||||||
gic_fmu_write_smen(base, smen);
|
gic_fmu_write_smen(base, smen);
|
||||||
|
|
||||||
smen = (ITS_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) |
|
smen = (ITS_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) |
|
||||||
(i << FMU_SMEN_BLK_SHIFT);
|
(i << FMU_SMEN_BLK_SHIFT) |
|
||||||
|
FMU_SMEN_EN_BIT;
|
||||||
gic_fmu_write_smen(base, smen);
|
gic_fmu_write_smen(base, smen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
|
* Copyright (c) 2021-2022, NVIDIA Corporation. All rights reserved.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -258,3 +258,47 @@ void gic_fmu_write_pingmask(uintptr_t base, uint64_t val)
|
||||||
{
|
{
|
||||||
GIC_FMU_WRITE_64(base, GICFMU_PINGMASK, 0, val);
|
GIC_FMU_WRITE_64(base, GICFMU_PINGMASK, 0, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper function to disable all safety mechanisms for a given block
|
||||||
|
*/
|
||||||
|
void gic_fmu_disable_all_sm_blkid(uintptr_t base, unsigned int blkid)
|
||||||
|
{
|
||||||
|
uint32_t smen, max_smid = U(0);
|
||||||
|
|
||||||
|
/* Sanity check block ID */
|
||||||
|
assert((blkid >= FMU_BLK_GICD) && (blkid <= FMU_BLK_PPI31));
|
||||||
|
|
||||||
|
/* Find the max safety mechanism ID for the block */
|
||||||
|
switch (blkid) {
|
||||||
|
case FMU_BLK_GICD:
|
||||||
|
max_smid = FMU_SMID_GICD_MAX;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FMU_BLK_SPICOL:
|
||||||
|
max_smid = FMU_SMID_SPICOL_MAX;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FMU_BLK_WAKERQ:
|
||||||
|
max_smid = FMU_SMID_WAKERQ_MAX;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FMU_BLK_ITS0...FMU_BLK_ITS7:
|
||||||
|
max_smid = FMU_SMID_ITS_MAX;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FMU_BLK_PPI0...FMU_BLK_PPI31:
|
||||||
|
max_smid = FMU_SMID_PPI_MAX;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable all Safety Mechanisms for a given block id */
|
||||||
|
for (unsigned int i = 0U; i < max_smid; i++) {
|
||||||
|
smen = (blkid << FMU_SMEN_BLK_SHIFT) | (i << FMU_SMEN_SMID_SHIFT);
|
||||||
|
gic_fmu_write_smen(base, smen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
|
* Copyright (c) 2021-2022, NVIDIA Corporation. All rights reserved.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -37,6 +37,7 @@
|
||||||
/* SMEN constants */
|
/* SMEN constants */
|
||||||
#define FMU_SMEN_BLK_SHIFT U(8)
|
#define FMU_SMEN_BLK_SHIFT U(8)
|
||||||
#define FMU_SMEN_SMID_SHIFT U(24)
|
#define FMU_SMEN_SMID_SHIFT U(24)
|
||||||
|
#define FMU_SMEN_EN_BIT BIT(0)
|
||||||
|
|
||||||
/* Error record IDs */
|
/* Error record IDs */
|
||||||
#define FMU_BLK_GICD U(0)
|
#define FMU_BLK_GICD U(0)
|
||||||
|
@ -86,10 +87,10 @@
|
||||||
|
|
||||||
/* Safety Mechamism limit */
|
/* Safety Mechamism limit */
|
||||||
#define FMU_SMID_GICD_MAX U(33)
|
#define FMU_SMID_GICD_MAX U(33)
|
||||||
|
#define FMU_SMID_PPI_MAX U(12)
|
||||||
|
#define FMU_SMID_ITS_MAX U(14)
|
||||||
#define FMU_SMID_SPICOL_MAX U(5)
|
#define FMU_SMID_SPICOL_MAX U(5)
|
||||||
#define FMU_SMID_WAKERQ_MAX U(2)
|
#define FMU_SMID_WAKERQ_MAX U(2)
|
||||||
#define FMU_SMID_ITS_MAX U(14)
|
|
||||||
#define FMU_SMID_PPI_MAX U(12)
|
|
||||||
|
|
||||||
/* MBIST Safety Mechanism ID */
|
/* MBIST Safety Mechanism ID */
|
||||||
#define GICD_MBIST_REQ_ERROR U(23)
|
#define GICD_MBIST_REQ_ERROR U(23)
|
||||||
|
@ -100,12 +101,17 @@
|
||||||
#define ITS_FMU_CLKGATE_ERROR U(14)
|
#define ITS_FMU_CLKGATE_ERROR U(14)
|
||||||
|
|
||||||
/* ERRSTATUS bits */
|
/* ERRSTATUS bits */
|
||||||
#define FMU_ERRSTATUS_V_BIT BIT(30)
|
#define FMU_ERRSTATUS_BLKID_SHIFT U(32)
|
||||||
#define FMU_ERRSTATUS_UE_BIT BIT(29)
|
#define FMU_ERRSTATUS_BLKID_MASK U(0xFF)
|
||||||
#define FMU_ERRSTATUS_OV_BIT BIT(27)
|
#define FMU_ERRSTATUS_V_BIT BIT(30)
|
||||||
#define FMU_ERRSTATUS_CE_BITS (BIT(25) | BIT(24))
|
#define FMU_ERRSTATUS_UE_BIT BIT(29)
|
||||||
#define FMU_ERRSTATUS_CLEAR (FMU_ERRSTATUS_V_BIT | FMU_ERRSTATUS_UE_BIT | \
|
#define FMU_ERRSTATUS_OV_BIT BIT(27)
|
||||||
FMU_ERRSTATUS_OV_BIT | FMU_ERRSTATUS_CE_BITS)
|
#define FMU_ERRSTATUS_CE_BITS (BIT(25) | BIT(24))
|
||||||
|
#define FMU_ERRSTATUS_CLEAR (FMU_ERRSTATUS_V_BIT | FMU_ERRSTATUS_UE_BIT | \
|
||||||
|
FMU_ERRSTATUS_OV_BIT | FMU_ERRSTATUS_CE_BITS)
|
||||||
|
#define FMU_ERRSTATUS_IERR_MASK U(0xFF)
|
||||||
|
#define FMU_ERRSTATUS_IERR_SHIFT U(8)
|
||||||
|
#define FMU_ERRSTATUS_SERR_MASK U(0xFF)
|
||||||
|
|
||||||
/* PINGCTLR constants */
|
/* PINGCTLR constants */
|
||||||
#define FMU_PINGCTLR_INTDIFF_SHIFT U(16)
|
#define FMU_PINGCTLR_INTDIFF_SHIFT U(16)
|
||||||
|
@ -137,11 +143,14 @@ void gic_fmu_write_pingnow(uintptr_t base, uint32_t val);
|
||||||
void gic_fmu_write_smen(uintptr_t base, uint32_t val);
|
void gic_fmu_write_smen(uintptr_t base, uint32_t val);
|
||||||
void gic_fmu_write_sminjerr(uintptr_t base, uint32_t val);
|
void gic_fmu_write_sminjerr(uintptr_t base, uint32_t val);
|
||||||
void gic_fmu_write_pingmask(uintptr_t base, uint64_t val);
|
void gic_fmu_write_pingmask(uintptr_t base, uint64_t val);
|
||||||
|
void gic_fmu_disable_all_sm_blkid(uintptr_t base, unsigned int blkid);
|
||||||
|
|
||||||
void gic600_fmu_init(uint64_t base, uint64_t blk_present_mask, bool errctlr_ce_en, bool errctlr_ue_en);
|
void gic600_fmu_init(uint64_t base, uint64_t blk_present_mask, bool errctlr_ce_en, bool errctlr_ue_en);
|
||||||
void gic600_fmu_enable_ping(uint64_t base, uint64_t blk_present_mask,
|
void gic600_fmu_enable_ping(uint64_t base, uint64_t blk_present_mask,
|
||||||
unsigned int timeout_val, unsigned int interval_diff);
|
unsigned int timeout_val, unsigned int interval_diff);
|
||||||
void gic600_fmu_print_sm_info(uint64_t base, unsigned int blk, unsigned int smid);
|
void gic600_fmu_print_sm_info(uint64_t base, unsigned int blk, unsigned int smid);
|
||||||
|
int gic600_fmu_probe(uint64_t base, int *probe_data);
|
||||||
|
int gic600_fmu_ras_handler(uint64_t base, int probe_data);
|
||||||
|
|
||||||
#endif /* __ASSEMBLER__ */
|
#endif /* __ASSEMBLER__ */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue