123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- /*
- * Copyright 2019-2021 NXP
- * All rights reserved.
- *
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include "fsl_mecc.h"
- /*******************************************************************************
- * Definitions
- ******************************************************************************/
- /* Component ID definition, used by tools. */
- #ifndef FSL_COMPONENT_ID
- #define FSL_COMPONENT_ID "platform.drivers.mecc"
- #endif
- /*******************************************************************************
- * Prototypes
- ******************************************************************************/
- /*!
- * @brief Gets the instance from the base address to be used to gate or ungate the module clock
- *
- * @param base MECC base address
- *
- * @return The MECC instance
- */
- static uint32_t MECC_GetInstance(MECC_Type *base);
- /*******************************************************************************
- * Variables
- ******************************************************************************/
- /*! @brief Pointers to MECC bases for each instance. */
- static MECC_Type *const s_meccBases[] = MECC_BASE_PTRS;
- /*******************************************************************************
- * Code
- ******************************************************************************/
- static uint32_t MECC_GetInstance(MECC_Type *base)
- {
- uint32_t instance;
- /* Find the instance index from base address mappings. */
- for (instance = 0; instance < ARRAY_SIZE(s_meccBases); instance++)
- {
- if (s_meccBases[instance] == base)
- {
- break;
- }
- }
- assert(instance < ARRAY_SIZE(s_meccBases));
- return instance;
- }
- /*!
- * brief MECC module initialization function.
- *
- * param base MECC base address.
- */
- void MECC_Init(MECC_Type *base, mecc_config_t *config)
- {
- uint32_t instance = MECC_GetInstance(base);
- volatile uint64_t *ocramStartAddr = NULL;
- /* enable all the interrupt status */
- base->ERR_STAT_EN = kMECC_AllInterruptsStatusEnable;
- /* clear all the interrupt status */
- base->ERR_STATUS = kMECC_AllInterruptsFlag;
- /* disable all the interrpt */
- base->ERR_SIG_EN = 0U;
- /* enable ECC function */
- base->PIPE_ECC_EN = MECC_PIPE_ECC_EN_ECC_EN(config->enableMecc);
- __DSB();
- if (instance == (uint32_t)kMECC_Instance0)
- {
- /* Need to be initialized for ECC function operation, note that do not use memset() to initialize,
- because it will use STR instruction and STR is byte access and MECC is 64 bits access operation. */
- ocramStartAddr = (uint64_t *)config->Ocram1StartAddress;
- while (ocramStartAddr < (uint64_t *)config->Ocram1EndAddress)
- {
- *ocramStartAddr = 0x00;
- ocramStartAddr++;
- }
- }
- else if (instance == (uint32_t)kMECC_Instance1)
- {
- /* Need to be initialized for ECC function operation, note that do not use memset() to initialize,
- because it will use STR instruction and STR is byte access and MECC is 64 bits access operation. */
- ocramStartAddr = (uint64_t *)config->Ocram2StartAddress;
- while (ocramStartAddr < (uint64_t *)config->Ocram2EndAddress)
- {
- *ocramStartAddr = 0x00;
- ocramStartAddr++;
- }
- }
- else
- {
- ; /* Intentional empty for MISRA rule 15.7 */
- }
- }
- /*!
- * brief Deinitializes the MECC.
- *
- */
- void MECC_Deinit(MECC_Type *base)
- {
- /* Disable ECC function */
- base->PIPE_ECC_EN &= ~MECC_PIPE_ECC_EN_ECC_EN(1);
- }
- void MECC_GetDefaultConfig(mecc_config_t *config)
- {
- assert(NULL != config);
- /* Initializes the configure structure to zero. */
- (void)memset(config, 0, sizeof(*config));
- /* Default MECC function. */
- config->enableMecc = false;
- /* Ocram 1 start address */
- config->Ocram1StartAddress = 0x20240000;
- /* Ocram 1 end address */
- config->Ocram1EndAddress = 0x202BFFFF;
- /* Ocram 2 address */
- config->Ocram1StartAddress = 0x202C0000;
- /* Ocram 2 address */
- config->Ocram1EndAddress = 0x2033FFFF;
- }
- /* Initialize OCRAM */
- /* Mainly use for debug, it can be deprecated when release */
- status_t MECC_ErrorInjection(
- MECC_Type *base, uint32_t lowerrordata, uint32_t higherrordata, uint8_t eccdata, uint8_t banknumber)
- {
- status_t status = kStatus_Success;
- switch (banknumber)
- {
- case kMECC_OcramBank0:
- /* Low 32 bits of Ocram bank0 error injection */
- base->ERR_DATA_INJ_LOW0 = lowerrordata;
- /* High 32 bits of Ocram bank0 error injection */
- base->ERR_DATA_INJ_HIGH0 = higherrordata;
- /* Ecc code of Ocram bank0 error injection */
- base->ERR_ECC_INJ0 = eccdata;
- break;
- case kMECC_OcramBank1:
- /* Low 32 bits of Ocram bank1 error injection */
- base->ERR_DATA_INJ_LOW1 = lowerrordata;
- /* High 32 bits of Ocram bank1 error injection */
- base->ERR_DATA_INJ_HIGH1 = higherrordata;
- /* Ecc code of Ocram bank1 error injection */
- base->ERR_ECC_INJ1 = eccdata;
- break;
- case kMECC_OcramBank2:
- /* Low 32 bits of Ocram bank2 error injection */
- base->ERR_DATA_INJ_LOW2 = lowerrordata;
- /* High 32 bits of Ocram bank2 error injection */
- base->ERR_DATA_INJ_HIGH2 = higherrordata;
- /* Ecc code of Ocram bank2 error injection */
- base->ERR_ECC_INJ2 = eccdata;
- break;
- case kMECC_OcramBank3:
- /* Low 32 bits of Ocram bank3 error injection */
- base->ERR_DATA_INJ_LOW3 = lowerrordata;
- /* High 32 bits of Ocram bank3 error injection */
- base->ERR_DATA_INJ_HIGH3 = higherrordata;
- /* Ecc code of Ocram bank3 error injection */
- base->ERR_ECC_INJ3 = eccdata;
- break;
- default:
- status = kStatus_MECC_BankMiss;
- break;
- }
- return status;
- }
- status_t MECC_GetSingleErrorInfo(MECC_Type *base, mecc_single_error_info_t *info, uint8_t banknumber)
- {
- assert(info != NULL);
- status_t status = kStatus_Success;
- uint8_t tempPosLow = 0U;
- uint8_t tempPosHigh = 0U;
- uint32_t counter = 0U;
- switch (banknumber)
- {
- case kMECC_OcramBank0:
- info->singleErrorEccCode =
- (uint8_t)((base->SINGLE_ERR_ADDR_ECC0 & MECC_SINGLE_ERR_ADDR_ECC0_SINGLE_ERR_ECC_MASK) >>
- MECC_SINGLE_ERR_ADDR_ECC0_SINGLE_ERR_ECC_SHIFT);
- info->singleErrorAddress = (base->SINGLE_ERR_ADDR_ECC0 & MECC_SINGLE_ERR_ADDR_ECC0_SINGLE_ERR_ADDR_MASK) >>
- MECC_SINGLE_ERR_ADDR_ECC0_SINGLE_ERR_ADDR_SHIFT;
- info->singleErrorDataLow = base->SINGLE_ERR_DATA_LOW0;
- info->singleErrorDataHigh = base->SINGLE_ERR_DATA_HIGH0;
- tempPosLow = (uint8_t)base->SINGLE_ERR_POS_LOW0;
- tempPosHigh = (uint8_t)base->SINGLE_ERR_POS_HIGH0;
- break;
- case kMECC_OcramBank1:
- info->singleErrorEccCode =
- (uint8_t)((base->SINGLE_ERR_ADDR_ECC1 & MECC_SINGLE_ERR_ADDR_ECC1_SINGLE_ERR_ECC_MASK) >>
- MECC_SINGLE_ERR_ADDR_ECC1_SINGLE_ERR_ECC_SHIFT);
- info->singleErrorAddress = (base->SINGLE_ERR_ADDR_ECC1 & MECC_SINGLE_ERR_ADDR_ECC1_SINGLE_ERR_ADDR_MASK) >>
- MECC_SINGLE_ERR_ADDR_ECC1_SINGLE_ERR_ADDR_SHIFT;
- info->singleErrorDataLow = base->SINGLE_ERR_DATA_LOW1;
- info->singleErrorDataHigh = base->SINGLE_ERR_DATA_HIGH1;
- tempPosLow = (uint8_t)base->SINGLE_ERR_POS_LOW1;
- tempPosHigh = (uint8_t)base->SINGLE_ERR_POS_HIGH1;
- break;
- case kMECC_OcramBank2:
- info->singleErrorEccCode =
- (uint8_t)((base->SINGLE_ERR_ADDR_ECC2 & MECC_SINGLE_ERR_ADDR_ECC2_SINGLE_ERR_ECC_MASK) >>
- MECC_SINGLE_ERR_ADDR_ECC2_SINGLE_ERR_ECC_SHIFT);
- info->singleErrorAddress = (base->SINGLE_ERR_ADDR_ECC2 & MECC_SINGLE_ERR_ADDR_ECC2_SINGLE_ERR_ADDR_MASK) >>
- MECC_SINGLE_ERR_ADDR_ECC2_SINGLE_ERR_ADDR_SHIFT;
- info->singleErrorDataLow = base->SINGLE_ERR_DATA_LOW2;
- info->singleErrorDataHigh = base->SINGLE_ERR_DATA_HIGH2;
- tempPosLow = (uint8_t)base->SINGLE_ERR_POS_LOW2;
- tempPosHigh = (uint8_t)base->SINGLE_ERR_POS_HIGH2;
- break;
- case kMECC_OcramBank3:
- info->singleErrorEccCode =
- (uint8_t)((base->SINGLE_ERR_ADDR_ECC3 & MECC_SINGLE_ERR_ADDR_ECC3_SINGLE_ERR_ECC_MASK) >>
- MECC_SINGLE_ERR_ADDR_ECC3_SINGLE_ERR_ECC_SHIFT);
- info->singleErrorAddress = (base->SINGLE_ERR_ADDR_ECC3 & MECC_SINGLE_ERR_ADDR_ECC3_SINGLE_ERR_ADDR_MASK) >>
- MECC_SINGLE_ERR_ADDR_ECC3_SINGLE_ERR_ADDR_SHIFT;
- info->singleErrorDataLow = base->SINGLE_ERR_DATA_LOW3;
- info->singleErrorDataHigh = base->SINGLE_ERR_DATA_HIGH3;
- tempPosLow = (uint8_t)base->SINGLE_ERR_POS_LOW3;
- tempPosHigh = (uint8_t)base->SINGLE_ERR_POS_HIGH3;
- break;
- default:
- status = kStatus_MECC_BankMiss;
- break;
- }
- while (tempPosLow > 0U)
- {
- tempPosLow = tempPosLow >> 1;
- counter++;
- }
- if (counter == 0U)
- {
- info->singleErrorPosLow = 0;
- }
- else
- {
- info->singleErrorPosLow = counter - 1U;
- }
- counter = 0U;
- while (tempPosHigh > 0U)
- {
- tempPosHigh = tempPosHigh >> 1;
- counter++;
- }
- if (counter == 0U)
- {
- info->singleErrorPosHigh = 0;
- }
- else
- {
- info->singleErrorPosHigh = counter - 1U;
- }
- return status;
- }
- status_t MECC_GetMultiErrorInfo(MECC_Type *base, mecc_multi_error_info_t *info, uint8_t banknumber)
- {
- assert(info != NULL);
- status_t status = kStatus_Success;
- switch (banknumber)
- {
- case kMECC_OcramBank0:
- info->multiErrorEccCode =
- (uint8_t)((base->MULTI_ERR_ADDR_ECC0 & MECC_MULTI_ERR_ADDR_ECC0_MULTI_ERR_ECC_MASK) >>
- MECC_MULTI_ERR_ADDR_ECC0_MULTI_ERR_ECC_SHIFT);
- info->multiErrorAddress = (base->MULTI_ERR_ADDR_ECC0 & MECC_MULTI_ERR_ADDR_ECC0_MULTI_ERR_ADDR_MASK) >>
- MECC_MULTI_ERR_ADDR_ECC0_MULTI_ERR_ADDR_SHIFT;
- info->multiErrorDataLow = base->MULTI_ERR_DATA_LOW0;
- info->multiErrorDataHigh = base->MULTI_ERR_DATA_HIGH0;
- break;
- case kMECC_OcramBank1:
- info->multiErrorEccCode =
- (uint8_t)((base->MULTI_ERR_ADDR_ECC1 & MECC_MULTI_ERR_ADDR_ECC1_MULTI_ERR_ECC_MASK) >>
- MECC_MULTI_ERR_ADDR_ECC1_MULTI_ERR_ECC_SHIFT);
- info->multiErrorAddress = (base->MULTI_ERR_ADDR_ECC1 & MECC_MULTI_ERR_ADDR_ECC1_MULTI_ERR_ADDR_MASK) >>
- MECC_MULTI_ERR_ADDR_ECC1_MULTI_ERR_ADDR_SHIFT;
- info->multiErrorDataLow = base->MULTI_ERR_DATA_LOW1;
- info->multiErrorDataHigh = base->MULTI_ERR_DATA_HIGH1;
- break;
- case kMECC_OcramBank2:
- info->multiErrorEccCode =
- (uint8_t)((base->MULTI_ERR_ADDR_ECC2 & MECC_MULTI_ERR_ADDR_ECC2_MULTI_ERR_ECC_MASK) >>
- MECC_MULTI_ERR_ADDR_ECC2_MULTI_ERR_ECC_SHIFT);
- info->multiErrorAddress = (base->MULTI_ERR_ADDR_ECC2 & MECC_MULTI_ERR_ADDR_ECC2_MULTI_ERR_ADDR_MASK) >>
- MECC_MULTI_ERR_ADDR_ECC2_MULTI_ERR_ADDR_SHIFT;
- info->multiErrorDataLow = base->MULTI_ERR_DATA_LOW2;
- info->multiErrorDataHigh = base->MULTI_ERR_DATA_HIGH2;
- break;
- case kMECC_OcramBank3:
- info->multiErrorEccCode =
- (uint8_t)((base->MULTI_ERR_ADDR_ECC3 & MECC_MULTI_ERR_ADDR_ECC3_MULTI_ERR_ECC_MASK) >>
- MECC_MULTI_ERR_ADDR_ECC3_MULTI_ERR_ECC_SHIFT);
- info->multiErrorAddress = (base->MULTI_ERR_ADDR_ECC3 & MECC_MULTI_ERR_ADDR_ECC3_MULTI_ERR_ADDR_MASK) >>
- MECC_MULTI_ERR_ADDR_ECC3_MULTI_ERR_ADDR_SHIFT;
- info->multiErrorDataLow = base->MULTI_ERR_DATA_LOW3;
- info->multiErrorDataHigh = base->MULTI_ERR_DATA_HIGH3;
- break;
- default:
- status = kStatus_MECC_BankMiss;
- break;
- }
- return status;
- }
|