1 /*
2  * Copyright 2019-2020 NXP
3  * All rights reserved.
4  *
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_xecc.h"
10 
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.xecc"
18 #endif
19 
20 /*******************************************************************************
21  * Prototypes
22  ******************************************************************************/
23 /*******************************************************************************
24  * Variables
25  ******************************************************************************/
26 /*******************************************************************************
27  * Code
28  ******************************************************************************/
29 /*!
30  * brief XECC module initialization function.
31  *
32  * param base XECC base address.
33  */
XECC_Init(XECC_Type * base,const xecc_config_t * config)34 void XECC_Init(XECC_Type *base, const xecc_config_t *config)
35 {
36     /* Enable all the interrupt status */
37     base->ERR_STAT_EN = kXECC_AllInterruptsStatusEnable;
38     /* Clear all the interrupt status */
39     base->ERR_STATUS = kXECC_AllInterruptsFlag;
40     /* Disable all the interrpt */
41     base->ERR_SIG_EN = 0U;
42 
43     /* Set ECC regions, which are 4KB aligned */
44     base->ECC_BASE_ADDR0 = config->Region0BaseAddress >> 12U;
45     base->ECC_END_ADDR0  = config->Region0EndAddress >> 12U;
46     base->ECC_BASE_ADDR1 = config->Region1BaseAddress >> 12U;
47     base->ECC_END_ADDR1  = config->Region1EndAddress >> 12U;
48     base->ECC_BASE_ADDR2 = config->Region2BaseAddress >> 12U;
49     base->ECC_END_ADDR2  = config->Region2EndAddress >> 12U;
50     base->ECC_BASE_ADDR3 = config->Region3BaseAddress >> 12U;
51     base->ECC_END_ADDR3  = config->Region3EndAddress >> 12U;
52 
53     /* Enable ECC function */
54     base->ECC_CTRL = XECC_ECC_CTRL_ECC_EN(config->enableXECC);
55     base->ECC_CTRL |= XECC_ECC_CTRL_WECC_EN(config->enableWriteECC);
56     base->ECC_CTRL |= XECC_ECC_CTRL_RECC_EN(config->enableReadECC);
57     base->ECC_CTRL |= XECC_ECC_CTRL_SWAP_EN(config->enableSwap);
58 
59     /* Make sure XECC register configuration operation has been done. */
60     __DSB();
61 }
62 
63 /*!
64  * brief Deinitializes the XECC.
65  *
66  */
XECC_Deinit(XECC_Type * base)67 void XECC_Deinit(XECC_Type *base)
68 {
69     /* Disable ECC function */
70     base->ECC_CTRL &= ~XECC_ECC_CTRL_ECC_EN(1);
71 }
72 
XECC_GetDefaultConfig(xecc_config_t * config)73 void XECC_GetDefaultConfig(xecc_config_t *config)
74 {
75     assert(NULL != config);
76 
77     /* Initializes the configure structure to zero. */
78     (void)memset(config, 0, sizeof(*config));
79 
80     /* Default XECC function */
81     config->enableXECC = false;
82     /* Default write ECC function */
83     config->enableWriteECC = false;
84     /* Default read ECC function */
85     config->enableReadECC = false;
86     /* Default swap function */
87     config->enableSwap = false;
88 
89     /* ECC region 0 base address */
90     config->Region0BaseAddress = 0U;
91     /* ECC region 0 end address */
92     config->Region0EndAddress = 0U;
93     /* ECC region 1 base address */
94     config->Region1BaseAddress = 0U;
95     /* ECC region 1 end address */
96     config->Region1EndAddress = 0U;
97     /* ECC region 2 base address */
98     config->Region2BaseAddress = 0U;
99     /* ECC region 2 end address */
100     config->Region2EndAddress = 0U;
101     /* ECC region 3 base address */
102     config->Region3BaseAddress = 0U;
103     /* ECC region 3 end address */
104     config->Region3EndAddress = 0U;
105 }
106 
107 /* Mainly use for debug, it can be deprecated when release */
XECC_ErrorInjection(XECC_Type * base,uint32_t errordata,uint8_t erroreccdata)108 status_t XECC_ErrorInjection(XECC_Type *base, uint32_t errordata, uint8_t erroreccdata)
109 {
110     status_t status = kStatus_Success;
111 
112     if ((errordata != 0x00U) || (erroreccdata != 0x00U))
113     {
114         /* error data injection */
115         base->ERR_DATA_INJ = errordata;
116         /* error ecc code injection */
117         base->ERR_ECC_INJ = erroreccdata;
118         /* Make sure injection operation has been done. */
119         __DSB();
120     }
121     else
122     {
123         status = kStatus_Fail;
124     }
125 
126     return status;
127 }
128 
XECC_GetSingleErrorInfo(XECC_Type * base,xecc_single_error_info_t * info)129 void XECC_GetSingleErrorInfo(XECC_Type *base, xecc_single_error_info_t *info)
130 {
131     assert(info != NULL);
132 
133     info->singleErrorAddress  = base->SINGLE_ERR_ADDR;
134     info->singleErrorData     = base->SINGLE_ERR_DATA;
135     info->singleErrorEccCode  = base->SINGLE_ERR_ECC;
136     info->singleErrorBitField = base->SINGLE_ERR_BIT_FIELD;
137     info->singleErrorBitPos   = base->SINGLE_ERR_POS;
138 }
139 
XECC_GetMultiErrorInfo(XECC_Type * base,xecc_multi_error_info_t * info)140 void XECC_GetMultiErrorInfo(XECC_Type *base, xecc_multi_error_info_t *info)
141 {
142     assert(info != NULL);
143 
144     info->multiErrorAddress  = base->MULTI_ERR_ADDR;
145     info->multiErrorData     = base->MULTI_ERR_DATA;
146     info->multiErrorEccCode  = base->MULTI_ERR_ECC;
147     info->multiErrorBitField = base->MULTI_ERR_BIT_FIELD;
148 }
149