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