Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:00

0001 /*
0002  * Copyright 2019-2021 NXP
0003  * All rights reserved.
0004  *
0005  *
0006  * SPDX-License-Identifier: BSD-3-Clause
0007  */
0008 
0009 #include "fsl_mecc.h"
0010 
0011 /*******************************************************************************
0012  * Definitions
0013  ******************************************************************************/
0014 
0015 /* Component ID definition, used by tools. */
0016 #ifndef FSL_COMPONENT_ID
0017 #define FSL_COMPONENT_ID "platform.drivers.mecc"
0018 #endif
0019 
0020 /*******************************************************************************
0021  * Prototypes
0022  ******************************************************************************/
0023 /*!
0024  * @brief Gets the instance from the base address to be used to gate or ungate the module clock
0025  *
0026  * @param base MECC base address
0027  *
0028  * @return The MECC instance
0029  */
0030 static uint32_t MECC_GetInstance(MECC_Type *base);
0031 /*******************************************************************************
0032  * Variables
0033  ******************************************************************************/
0034 /*! @brief Pointers to MECC bases for each instance. */
0035 static MECC_Type *const s_meccBases[] = MECC_BASE_PTRS;
0036 /*******************************************************************************
0037  * Code
0038  ******************************************************************************/
0039 static uint32_t MECC_GetInstance(MECC_Type *base)
0040 {
0041     uint32_t instance;
0042 
0043     /* Find the instance index from base address mappings. */
0044     for (instance = 0; instance < ARRAY_SIZE(s_meccBases); instance++)
0045     {
0046         if (s_meccBases[instance] == base)
0047         {
0048             break;
0049         }
0050     }
0051 
0052     assert(instance < ARRAY_SIZE(s_meccBases));
0053 
0054     return instance;
0055 }
0056 
0057 /*!
0058  * brief MECC module initialization function.
0059  *
0060  * param base MECC base address.
0061  */
0062 void MECC_Init(MECC_Type *base, mecc_config_t *config)
0063 {
0064     uint32_t instance                 = MECC_GetInstance(base);
0065     volatile uint64_t *ocramStartAddr = NULL;
0066 
0067     /* enable all the interrupt status */
0068     base->ERR_STAT_EN = kMECC_AllInterruptsStatusEnable;
0069     /* clear all the interrupt status */
0070     base->ERR_STATUS = kMECC_AllInterruptsFlag;
0071     /* disable all the interrpt */
0072     base->ERR_SIG_EN = 0U;
0073 
0074     /* enable ECC function */
0075     base->PIPE_ECC_EN = MECC_PIPE_ECC_EN_ECC_EN(config->enableMecc);
0076 
0077     __DSB();
0078 
0079     if (instance == (uint32_t)kMECC_Instance0)
0080     {
0081         /* Need to be initialized for ECC function operation, note that do not use memset() to initialize,
0082              because it will use STR instruction and STR is byte access and MECC is 64 bits access operation. */
0083         ocramStartAddr = (uint64_t *)config->Ocram1StartAddress;
0084         while (ocramStartAddr < (uint64_t *)config->Ocram1EndAddress)
0085         {
0086             *ocramStartAddr = 0x00;
0087             ocramStartAddr++;
0088         }
0089     }
0090     else if (instance == (uint32_t)kMECC_Instance1)
0091     {
0092         /* Need to be initialized for ECC function operation, note that do not use memset() to initialize,
0093              because it will use STR instruction and STR is byte access and MECC is 64 bits access operation. */
0094         ocramStartAddr = (uint64_t *)config->Ocram2StartAddress;
0095         while (ocramStartAddr < (uint64_t *)config->Ocram2EndAddress)
0096         {
0097             *ocramStartAddr = 0x00;
0098             ocramStartAddr++;
0099         }
0100     }
0101     else
0102     {
0103         ; /* Intentional empty for MISRA rule 15.7 */
0104     }
0105 }
0106 
0107 /*!
0108  * brief Deinitializes the MECC.
0109  *
0110  */
0111 void MECC_Deinit(MECC_Type *base)
0112 {
0113     /* Disable ECC function */
0114     base->PIPE_ECC_EN &= ~MECC_PIPE_ECC_EN_ECC_EN(1);
0115 }
0116 
0117 void MECC_GetDefaultConfig(mecc_config_t *config)
0118 {
0119     assert(NULL != config);
0120 
0121     /* Initializes the configure structure to zero. */
0122     (void)memset(config, 0, sizeof(*config));
0123 
0124     /* Default MECC function. */
0125     config->enableMecc = false;
0126     /* Ocram 1 start address */
0127     config->Ocram1StartAddress = 0x20240000;
0128     /* Ocram 1 end address */
0129     config->Ocram1EndAddress = 0x202BFFFF;
0130     /* Ocram 2 address */
0131     config->Ocram1StartAddress = 0x202C0000;
0132     /* Ocram 2 address */
0133     config->Ocram1EndAddress = 0x2033FFFF;
0134 }
0135 
0136 /* Initialize OCRAM */
0137 
0138 /* Mainly use for debug, it can be deprecated when release */
0139 status_t MECC_ErrorInjection(
0140     MECC_Type *base, uint32_t lowerrordata, uint32_t higherrordata, uint8_t eccdata, uint8_t banknumber)
0141 {
0142     status_t status = kStatus_Success;
0143 
0144     switch (banknumber)
0145     {
0146         case kMECC_OcramBank0:
0147             /* Low 32 bits of Ocram bank0 error injection */
0148             base->ERR_DATA_INJ_LOW0 = lowerrordata;
0149             /* High 32 bits of Ocram bank0 error injection */
0150             base->ERR_DATA_INJ_HIGH0 = higherrordata;
0151             /* Ecc code of Ocram bank0 error injection */
0152             base->ERR_ECC_INJ0 = eccdata;
0153             break;
0154 
0155         case kMECC_OcramBank1:
0156             /* Low 32 bits of Ocram bank1 error injection */
0157             base->ERR_DATA_INJ_LOW1 = lowerrordata;
0158             /* High 32 bits of Ocram bank1 error injection */
0159             base->ERR_DATA_INJ_HIGH1 = higherrordata;
0160             /* Ecc code of Ocram bank1 error injection */
0161             base->ERR_ECC_INJ1 = eccdata;
0162             break;
0163 
0164         case kMECC_OcramBank2:
0165             /* Low 32 bits of Ocram bank2 error injection */
0166             base->ERR_DATA_INJ_LOW2 = lowerrordata;
0167             /* High 32 bits of Ocram bank2 error injection */
0168             base->ERR_DATA_INJ_HIGH2 = higherrordata;
0169             /* Ecc code of Ocram bank2 error injection */
0170             base->ERR_ECC_INJ2 = eccdata;
0171             break;
0172 
0173         case kMECC_OcramBank3:
0174             /* Low 32 bits of Ocram bank3 error injection */
0175             base->ERR_DATA_INJ_LOW3 = lowerrordata;
0176             /* High 32 bits of Ocram bank3 error injection */
0177             base->ERR_DATA_INJ_HIGH3 = higherrordata;
0178             /* Ecc code of Ocram bank3 error injection */
0179             base->ERR_ECC_INJ3 = eccdata;
0180             break;
0181 
0182         default:
0183             status = kStatus_MECC_BankMiss;
0184             break;
0185     }
0186 
0187     return status;
0188 }
0189 
0190 status_t MECC_GetSingleErrorInfo(MECC_Type *base, mecc_single_error_info_t *info, uint8_t banknumber)
0191 {
0192     assert(info != NULL);
0193     status_t status     = kStatus_Success;
0194     uint8_t tempPosLow  = 0U;
0195     uint8_t tempPosHigh = 0U;
0196     uint32_t counter    = 0U;
0197 
0198     switch (banknumber)
0199     {
0200         case kMECC_OcramBank0:
0201             info->singleErrorEccCode =
0202                 (uint8_t)((base->SINGLE_ERR_ADDR_ECC0 & MECC_SINGLE_ERR_ADDR_ECC0_SINGLE_ERR_ECC_MASK) >>
0203                           MECC_SINGLE_ERR_ADDR_ECC0_SINGLE_ERR_ECC_SHIFT);
0204             info->singleErrorAddress = (base->SINGLE_ERR_ADDR_ECC0 & MECC_SINGLE_ERR_ADDR_ECC0_SINGLE_ERR_ADDR_MASK) >>
0205                                        MECC_SINGLE_ERR_ADDR_ECC0_SINGLE_ERR_ADDR_SHIFT;
0206             info->singleErrorDataLow  = base->SINGLE_ERR_DATA_LOW0;
0207             info->singleErrorDataHigh = base->SINGLE_ERR_DATA_HIGH0;
0208             tempPosLow                = (uint8_t)base->SINGLE_ERR_POS_LOW0;
0209             tempPosHigh               = (uint8_t)base->SINGLE_ERR_POS_HIGH0;
0210             break;
0211 
0212         case kMECC_OcramBank1:
0213             info->singleErrorEccCode =
0214                 (uint8_t)((base->SINGLE_ERR_ADDR_ECC1 & MECC_SINGLE_ERR_ADDR_ECC1_SINGLE_ERR_ECC_MASK) >>
0215                           MECC_SINGLE_ERR_ADDR_ECC1_SINGLE_ERR_ECC_SHIFT);
0216             info->singleErrorAddress = (base->SINGLE_ERR_ADDR_ECC1 & MECC_SINGLE_ERR_ADDR_ECC1_SINGLE_ERR_ADDR_MASK) >>
0217                                        MECC_SINGLE_ERR_ADDR_ECC1_SINGLE_ERR_ADDR_SHIFT;
0218             info->singleErrorDataLow  = base->SINGLE_ERR_DATA_LOW1;
0219             info->singleErrorDataHigh = base->SINGLE_ERR_DATA_HIGH1;
0220             tempPosLow                = (uint8_t)base->SINGLE_ERR_POS_LOW1;
0221             tempPosHigh               = (uint8_t)base->SINGLE_ERR_POS_HIGH1;
0222             break;
0223 
0224         case kMECC_OcramBank2:
0225             info->singleErrorEccCode =
0226                 (uint8_t)((base->SINGLE_ERR_ADDR_ECC2 & MECC_SINGLE_ERR_ADDR_ECC2_SINGLE_ERR_ECC_MASK) >>
0227                           MECC_SINGLE_ERR_ADDR_ECC2_SINGLE_ERR_ECC_SHIFT);
0228             info->singleErrorAddress = (base->SINGLE_ERR_ADDR_ECC2 & MECC_SINGLE_ERR_ADDR_ECC2_SINGLE_ERR_ADDR_MASK) >>
0229                                        MECC_SINGLE_ERR_ADDR_ECC2_SINGLE_ERR_ADDR_SHIFT;
0230             info->singleErrorDataLow  = base->SINGLE_ERR_DATA_LOW2;
0231             info->singleErrorDataHigh = base->SINGLE_ERR_DATA_HIGH2;
0232             tempPosLow                = (uint8_t)base->SINGLE_ERR_POS_LOW2;
0233             tempPosHigh               = (uint8_t)base->SINGLE_ERR_POS_HIGH2;
0234             break;
0235 
0236         case kMECC_OcramBank3:
0237             info->singleErrorEccCode =
0238                 (uint8_t)((base->SINGLE_ERR_ADDR_ECC3 & MECC_SINGLE_ERR_ADDR_ECC3_SINGLE_ERR_ECC_MASK) >>
0239                           MECC_SINGLE_ERR_ADDR_ECC3_SINGLE_ERR_ECC_SHIFT);
0240             info->singleErrorAddress = (base->SINGLE_ERR_ADDR_ECC3 & MECC_SINGLE_ERR_ADDR_ECC3_SINGLE_ERR_ADDR_MASK) >>
0241                                        MECC_SINGLE_ERR_ADDR_ECC3_SINGLE_ERR_ADDR_SHIFT;
0242             info->singleErrorDataLow  = base->SINGLE_ERR_DATA_LOW3;
0243             info->singleErrorDataHigh = base->SINGLE_ERR_DATA_HIGH3;
0244             tempPosLow                = (uint8_t)base->SINGLE_ERR_POS_LOW3;
0245             tempPosHigh               = (uint8_t)base->SINGLE_ERR_POS_HIGH3;
0246             break;
0247 
0248         default:
0249             status = kStatus_MECC_BankMiss;
0250             break;
0251     }
0252 
0253     while (tempPosLow > 0U)
0254     {
0255         tempPosLow = tempPosLow >> 1;
0256         counter++;
0257     }
0258 
0259     if (counter == 0U)
0260     {
0261         info->singleErrorPosLow = 0;
0262     }
0263     else
0264     {
0265         info->singleErrorPosLow = counter - 1U;
0266     }
0267 
0268     counter = 0U;
0269     while (tempPosHigh > 0U)
0270     {
0271         tempPosHigh = tempPosHigh >> 1;
0272         counter++;
0273     }
0274 
0275     if (counter == 0U)
0276     {
0277         info->singleErrorPosHigh = 0;
0278     }
0279     else
0280     {
0281         info->singleErrorPosHigh = counter - 1U;
0282     }
0283 
0284     return status;
0285 }
0286 
0287 status_t MECC_GetMultiErrorInfo(MECC_Type *base, mecc_multi_error_info_t *info, uint8_t banknumber)
0288 {
0289     assert(info != NULL);
0290     status_t status = kStatus_Success;
0291 
0292     switch (banknumber)
0293     {
0294         case kMECC_OcramBank0:
0295             info->multiErrorEccCode =
0296                 (uint8_t)((base->MULTI_ERR_ADDR_ECC0 & MECC_MULTI_ERR_ADDR_ECC0_MULTI_ERR_ECC_MASK) >>
0297                           MECC_MULTI_ERR_ADDR_ECC0_MULTI_ERR_ECC_SHIFT);
0298             info->multiErrorAddress = (base->MULTI_ERR_ADDR_ECC0 & MECC_MULTI_ERR_ADDR_ECC0_MULTI_ERR_ADDR_MASK) >>
0299                                       MECC_MULTI_ERR_ADDR_ECC0_MULTI_ERR_ADDR_SHIFT;
0300             info->multiErrorDataLow  = base->MULTI_ERR_DATA_LOW0;
0301             info->multiErrorDataHigh = base->MULTI_ERR_DATA_HIGH0;
0302             break;
0303 
0304         case kMECC_OcramBank1:
0305             info->multiErrorEccCode =
0306                 (uint8_t)((base->MULTI_ERR_ADDR_ECC1 & MECC_MULTI_ERR_ADDR_ECC1_MULTI_ERR_ECC_MASK) >>
0307                           MECC_MULTI_ERR_ADDR_ECC1_MULTI_ERR_ECC_SHIFT);
0308             info->multiErrorAddress = (base->MULTI_ERR_ADDR_ECC1 & MECC_MULTI_ERR_ADDR_ECC1_MULTI_ERR_ADDR_MASK) >>
0309                                       MECC_MULTI_ERR_ADDR_ECC1_MULTI_ERR_ADDR_SHIFT;
0310             info->multiErrorDataLow  = base->MULTI_ERR_DATA_LOW1;
0311             info->multiErrorDataHigh = base->MULTI_ERR_DATA_HIGH1;
0312             break;
0313 
0314         case kMECC_OcramBank2:
0315             info->multiErrorEccCode =
0316                 (uint8_t)((base->MULTI_ERR_ADDR_ECC2 & MECC_MULTI_ERR_ADDR_ECC2_MULTI_ERR_ECC_MASK) >>
0317                           MECC_MULTI_ERR_ADDR_ECC2_MULTI_ERR_ECC_SHIFT);
0318             info->multiErrorAddress = (base->MULTI_ERR_ADDR_ECC2 & MECC_MULTI_ERR_ADDR_ECC2_MULTI_ERR_ADDR_MASK) >>
0319                                       MECC_MULTI_ERR_ADDR_ECC2_MULTI_ERR_ADDR_SHIFT;
0320             info->multiErrorDataLow  = base->MULTI_ERR_DATA_LOW2;
0321             info->multiErrorDataHigh = base->MULTI_ERR_DATA_HIGH2;
0322             break;
0323 
0324         case kMECC_OcramBank3:
0325             info->multiErrorEccCode =
0326                 (uint8_t)((base->MULTI_ERR_ADDR_ECC3 & MECC_MULTI_ERR_ADDR_ECC3_MULTI_ERR_ECC_MASK) >>
0327                           MECC_MULTI_ERR_ADDR_ECC3_MULTI_ERR_ECC_SHIFT);
0328             info->multiErrorAddress = (base->MULTI_ERR_ADDR_ECC3 & MECC_MULTI_ERR_ADDR_ECC3_MULTI_ERR_ADDR_MASK) >>
0329                                       MECC_MULTI_ERR_ADDR_ECC3_MULTI_ERR_ADDR_SHIFT;
0330             info->multiErrorDataLow  = base->MULTI_ERR_DATA_LOW3;
0331             info->multiErrorDataHigh = base->MULTI_ERR_DATA_HIGH3;
0332             break;
0333 
0334         default:
0335             status = kStatus_MECC_BankMiss;
0336             break;
0337     }
0338 
0339     return status;
0340 }